http://www.myprettyproducts.com/product?filter="type.eq(3).and(prize.lt(500))"In QueryDsl you use the generated QueryType classes to construct a BooleanExpression object which you can use in the where clause of a select query like this:
QProduct qProduct = QProduct.product; JPQLQuery query = new JPAQuery(entityManager).from(qProduct) .where(qProduct.type.eq(3).and(qProduct.prize.lt(500)); return query.list(qProduct);Now if I could use qProduct.type.eq(3).and(qProduct.prize.lt(500) in a url and convert this string expression to Java code we are done.
Hey, wait a minute are we opening up the system for code injection? Yes, but there is a solution to this I will cover later on.
So how do we convert the expression string to Java code at runtime? I use MVEL for this part. That's a powerful evaluation language for Java applications, which evaluates a script. Now how it works is that you setup a map of key value pairs for the variables that are expected in the expression string. For the example above this would be: "type", qProduct.type and "prize", qProduct.prize. Code example:
This following code will take any valid expression string using the type and prize attributes. The conditional operators are the ones allowed by the QueryDsl QueryType metadata objects and depend on the attributes Type.
Predicate toProductPredicate(String expressionFilter){ Map<String, Object> vars = new HashMap<String, Object>(); vars.put("type", qProduct.type); vars.put("prize", qProduct.prize); return (Predicate)MVEL.eval(expressionFilter, vars); } public Collection<product> findAllProducts(String filterExpression){ QProduct qProduct = QProduct.product; JPQLQuery query = new JPAQuery(entityManager).from(qProduct) .where(toProductPredicate(expressionString)); return query.list(qProduct); }
How to go about the code injection vulnerability.
You want to restrict the expression to only include terms and constructions that lead to a valid QueryDsl Predicate and nothing more. For this purpose I wrote a custom dynamic Parser using Parboild. Parboild is a socalled PEG (Parsing expression grammar) parser. See all detail in the followup post: Filter expressions in Rest urls leveraging QueryDsl Part 2