Easy XPath retrieval in Java

on July 13, 2012

Many experienced Mendix Developers use Java to express low-level, complex algorithms. Retrieving data from the database using XPath is often part of this process. The verbosity of Java in combination with its somewhat limited type checker (see this blogpost) makes this quite a tedious process. However, the latest community commons release (2.3) includes an XPath utility class which significantly eases retrieving data from the database. This blog post demonstrates how to use thisĀ XPath class to significantly simplify your java code.


Let’s, for example, take the following domain model and method:

Sample domain model

As an example let’s try to implement the following java action (the case is somewhat artificial to keep it as short as possible):

Example java action specification

Example java action specification

If you would create a microflow, the XPath used to solve the problem would look like this:

Reference XPath

Reference Xpath

Some naive implementations

A first, naive java implementation would look like this:

However, using raw strings in XPath is generally recognized as a bad practice; if the domain model changes you would like to get compile errors, but you will not get those when using strings. Fortunately this can easily be avoided by using format strings and the proxy classes generated by the Mendix Business Modeler. As soon as the domain model changes, the proxy classes are regenerated, and the identifiers used in this code will become unresolvable (and thus result in compiler errors).

Unfortunately this approach still has its limitations:

  • The approach is very sensitive to database injection attacks, take for example the search query (mind the single quote): “ ' or true() = true()
  • If no category is provided, a null pointer exception will be thrown, instead of yielding no results.
  • Setting up a proper format string is an error prone process, especially when changing the query in a later stadium. If the query consists of many identifiers, it becomes a tedious process to match a formatter with its substitution, making the code hardly readable.

To avoid the first two issues, one has to introduce additional null checks (if (category == null) return "";) and sanitize the input (StringEscapeUtils.escapeXml(searchQuery)). Both exceptional cases are easily forgotten.

The XPath generator class

The XPath class provided by the community commons module provides an easier approach to tackle this problem. The class provides a fluent interface to writing XPath. Using generics, type inference and class reflection, the class allows you to write XPath queries which are structurally equal to the XPath expressions generated by the Business Modeler.

XPath expressions are constructed using the XPath.Create(context, proxyclass) method. This class instantiates a fluent XPath interface and binds it to a specific Entity type. Or to just dive into the code:

Using the XPath class, our XPath expression is now structurally equivalent to the original XPath expression as defined in the Business Modeler. Furthermore a lot of code has been eliminated:

  • No proxy instances or lists need to be instantiated (List<Product> instead of List<IMendixObject>), this saves a lot of boilerplate null checks and unnecessary variables, significantly reducing the amount of code.
  • Values are converted automatically. For example a java boolean tranlates nicely into XPath true() or false().
  • No null checks are needed, since we can pass both proxy classes or IMendixObject objects directly into the XPath. Null checks are performed by the library and translate correctly into XPath NULL values.
  • No data sanitizing is needed, string values are always sanitized by the library.
  • Common functions like Sorting, offset, limit, first and count are directly available as methods of the fluent interface.
  • XPath constant values are easily introduced in the query by using for example XPath.BeginOfCurrentDay.

It would be to superfluous to explain the full fluent API here, but one can easily dive into (and extend) the class at javasource/communitycommons/XPath.java after importing the module. Feel free to post any improvements or suggestions here!

  • You guys are doing some really exciting stuff. I just wrote some naive JavaActions and will revisit them soon. I would love to see this as part of the standard API though, to encourage best practices in general plus having less modules in your project is a good thing.

  • I just want to state for the record, again, that this is awesome!

  • hgeldenhuys

    Just my yearly reminder to say how cool this is.

  • hgeldenhuys

    Lets keep with tradition. Thank Michel! Another year, and I still use it!