diff --git a/spring-security-rest-full/pom.xml b/spring-security-rest-full/pom.xml
index f26ef6df37..e8971b6fa3 100644
--- a/spring-security-rest-full/pom.xml
+++ b/spring-security-rest-full/pom.xml
@@ -107,7 +107,15 @@
querydsl-jpa
3.6.2
-
+
+
+
+
+ cz.jirutka.rsql
+ rsql-parser
+ 2.0.0
+
+
diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/rsql/CustomRsqlVisitor.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/rsql/CustomRsqlVisitor.java
new file mode 100644
index 0000000000..64c84678af
--- /dev/null
+++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/rsql/CustomRsqlVisitor.java
@@ -0,0 +1,34 @@
+package org.baeldung.persistence.dao.rsql;
+
+import org.baeldung.persistence.model.User;
+import org.springframework.data.jpa.domain.Specification;
+
+import cz.jirutka.rsql.parser.ast.AndNode;
+import cz.jirutka.rsql.parser.ast.ComparisonNode;
+import cz.jirutka.rsql.parser.ast.OrNode;
+import cz.jirutka.rsql.parser.ast.RSQLVisitor;
+
+public class CustomRsqlVisitor implements RSQLVisitor, Void> {
+
+ private UserRsqlSpecBuilder builder;
+
+ public CustomRsqlVisitor() {
+ builder = new UserRsqlSpecBuilder();
+ }
+
+ @Override
+ public Specification visit(final AndNode node, final Void param) {
+ return builder.createSpecification(node);
+ }
+
+ @Override
+ public Specification visit(final OrNode node, final Void param) {
+ return builder.createSpecification(node);
+ }
+
+ @Override
+ public Specification visit(final ComparisonNode node, final Void params) {
+ return builder.createSpecification(node);
+ }
+
+}
diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/rsql/RsqlSearchOperation.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/rsql/RsqlSearchOperation.java
new file mode 100644
index 0000000000..769063cbee
--- /dev/null
+++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/rsql/RsqlSearchOperation.java
@@ -0,0 +1,28 @@
+package org.baeldung.persistence.dao.rsql;
+
+import cz.jirutka.rsql.parser.ast.ComparisonOperator;
+import cz.jirutka.rsql.parser.ast.RSQLOperators;
+
+public enum RsqlSearchOperation {
+ EQUAL(RSQLOperators.EQUAL), NOT_EQUAL(RSQLOperators.NOT_EQUAL), GREATER_THAN(RSQLOperators.GREATER_THAN), GREATER_THAN_OR_EQUAL(RSQLOperators.GREATER_THAN_OR_EQUAL), LESS_THAN(RSQLOperators.LESS_THAN), LESS_THAN_OR_EQUAL(RSQLOperators.LESS_THAN_OR_EQUAL), IN(
+ RSQLOperators.IN), NOT_IN(RSQLOperators.NOT_IN);
+
+ private ComparisonOperator operator;
+
+ private RsqlSearchOperation(final ComparisonOperator operator) {
+ this.operator = operator;
+ }
+
+ public static RsqlSearchOperation getSimpleOperator(final ComparisonOperator operator) {
+ for (final RsqlSearchOperation operation : values()) {
+ if (operation.getOperator() == operator) {
+ return operation;
+ }
+ }
+ return null;
+ }
+
+ public ComparisonOperator getOperator() {
+ return operator;
+ }
+}
diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/rsql/UserRsqlSpecBuilder.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/rsql/UserRsqlSpecBuilder.java
new file mode 100644
index 0000000000..202370a64b
--- /dev/null
+++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/rsql/UserRsqlSpecBuilder.java
@@ -0,0 +1,58 @@
+package org.baeldung.persistence.dao.rsql;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.baeldung.persistence.model.User;
+import org.springframework.data.jpa.domain.Specifications;
+
+import cz.jirutka.rsql.parser.ast.ComparisonNode;
+import cz.jirutka.rsql.parser.ast.LogicalNode;
+import cz.jirutka.rsql.parser.ast.LogicalOperator;
+import cz.jirutka.rsql.parser.ast.Node;
+
+public class UserRsqlSpecBuilder {
+
+ public Specifications createSpecification(final Node node) {
+ if (node instanceof LogicalNode) {
+ return createSpecification((LogicalNode) node);
+ }
+ if (node instanceof ComparisonNode) {
+ return createSpecification((ComparisonNode) node);
+ }
+ return null;
+ }
+
+ public Specifications createSpecification(final LogicalNode logicalNode) {
+ final List> specs = new ArrayList>();
+ Specifications temp;
+ for (final Node node : logicalNode.getChildren()) {
+ temp = createSpecification(node);
+ if (temp != null) {
+ specs.add(temp);
+ }
+ }
+
+ Specifications result = specs.get(0);
+
+ if (logicalNode.getOperator() == LogicalOperator.AND) {
+ for (int i = 1; i < specs.size(); i++) {
+ result = Specifications.where(result).and(specs.get(i));
+ }
+ }
+
+ else if (logicalNode.getOperator() == LogicalOperator.OR) {
+ for (int i = 1; i < specs.size(); i++) {
+ result = Specifications.where(result).or(specs.get(i));
+ }
+ }
+
+ return result;
+ }
+
+ public Specifications createSpecification(final ComparisonNode comparisonNode) {
+ final Specifications result = Specifications.where(new UserRsqlSpecification(comparisonNode.getSelector(), comparisonNode.getOperator(), comparisonNode.getArguments()));
+ return result;
+ }
+
+}
diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/rsql/UserRsqlSpecification.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/rsql/UserRsqlSpecification.java
new file mode 100644
index 0000000000..77b491babe
--- /dev/null
+++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/rsql/UserRsqlSpecification.java
@@ -0,0 +1,94 @@
+package org.baeldung.persistence.dao.rsql;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+
+import org.baeldung.persistence.model.User;
+import org.springframework.data.jpa.domain.Specification;
+
+import cz.jirutka.rsql.parser.ast.ComparisonOperator;
+
+public class UserRsqlSpecification implements Specification {
+
+ private String property;
+ private ComparisonOperator operator;
+ private List arguments;
+
+ public UserRsqlSpecification(final String property, final ComparisonOperator operator, final List arguments) {
+ super();
+ this.property = property;
+ this.operator = operator;
+ this.arguments = arguments;
+ }
+
+
+ @Override
+ public Predicate toPredicate(final Root root, final CriteriaQuery> query, final CriteriaBuilder builder) {
+ final List