Implementation Dynamic Specification Using RSQL-Parser Example

Introducing

Changes Is Enemy, But We Must Prepared . –

I have been code with spring boot and thymeleaf, When the *User Interface * add a new search criteria the backend code (my repository, service and controller) must changed too. Honestly I don’t like that. to much changing :(.
I try searching library to handle changes, so make minimum rewriting code when User Interface Changed.
And Woww Gotchaaaa… RSQL-PARSER

What Is Rsql-Parser

RSQL-Parser is a query language for parametrized filtering of entries in RESTful APIs. It’s based on FIQL (Feed Item Query Language) – an URI-friendly syntax for expressing filters across the entries in an Atom Feed. FIQL is great for use in URI; there are no unsafe characters, so URL encoding is not required. On the other side, FIQL’s syntax is not very intuitive and URL encoding isn’t always that big deal, so RSQL also provides a friendlier syntax for logical operators and some of the comparison operators.-Github Rsql parser

Before we go to dev this is pom.xml i have used

spring-boot-starter-parent: 1.3.5

lombok :1.16.8

mysql

rsql-parser : 2.1.0

commons-lang : 2.6

hibernate-java8 : 5.0.5.Final

java 8

This Is my Table

1

2

3

4

5

6

7

8

9

10

11

12

13

CREATE TABLE`table_testing_rsql`(

`id`bigint(20)NOTNULL,

`date_test`date DEFAULTNULL,

`big_decimal_test`decimal(38,10)DEFAULTNULL,

`date_time_test`datetime DEFAULTNULL,

`varchar_test`varchar(100)DEFAULTNULL,

`int_test`int(11)DEFAULTNULL,

`float_test`float(10,1)DEFAULTNULL,

`char_test`char(1)DEFAULTNULL,

`double_test`doubleDEFAULTNULL,

PRIMARY KEY(`id`)

)

i have try to cover all datatype we usually using in the application.

JPARsqlConverter.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

if(op.equals(EQUAL)){

if(type.equals(String.class)&&argument.toString().contains("*")){

returnbuilder.like(attrPath,argument.toString().replace('*','%'));

}elseif(argument==null){

returnbuilder.isNull(attrPath);

}else{

returnbuilder.equal(attrPath,argument);

}

}

if(op.equals(NOT_EQUAL)){

if(type.equals(String.class)&&argument.toString().contains("*")){

returnbuilder.notLike(attrPath,argument.toString().replace('*','%'));

}elseif(argument==null){

returnbuilder.isNotNull(attrPath);

}else{

returnbuilder.notEqual(attrPath,argument);

}

}

All value String convert into Object appropriate with the Pojo Attribute DataType.

Implementation RSQL in Services layer

Simple Like That..
p_filter like this
– Where Clause Equals –> bigDecimalTest==1234556.1234567890
– Where Clause Not Equals –>idTest!=1
– Where Clause IN –> charTest=in=(A,B)
– Where Clause Not In –> doubleTest=out=(1.456789,156789.56789)
– Where Clause Grater Than –>doubleTest=gt=156789.56789
– Where Clause Less Than –> floatTest=le=5.5
– Where Clause Like –> varcharTest==ou**
– Where Clause Not Like –> varcharTest!=ou**
– Complex Query clausa –> ( dateTest=in=(2016-05-24,2016-05-25);intTest=in=(1,4)),idTest==5″

note :
Logical AND –> ;
Logical OR –> ,-

i Have create 10 classes test too prove all is well.
And then , this is the result testing Junit.