JAX-RS - Accessing Matrix Parameters by using @MatrixParam and PathSegment

[Updated: Mar 16, 2017, Created: Mar 9, 2017]

The annotation @MatrixParam is used to capture matrix parameters. We would use this annotation as an alternative to @QueryParam. Matrix parameters are more powerful than query parameters because they can be inserted in the middle of the URI. Let's understand usage of @MatrixParam by examples.

Matrix parameter at the end of URI

Per matrix parameter format, let's consider following resource URI:

  /customers;state=TX

The above example URI is to get all customers who are form the specified state.

The following JAX-RS resource method getCustomers(..) captures the matrix parameter 'state':

@Path("/")
public class CustomerResource {

  @GET
  @Path("customers")
  public String getCustomers(@MatrixParam("state") String state) {
      String info = String.format("resource getCustomers(). state:%s%n", state);
      return info;
  }
    .............
}

output

resource getCustomers(). state:tx

Matrix parameters in the middle of URI

  /customers;state=tx/orders

Let's try following resource method

 @Path("/")
 public class CustomerResource {
    .....
    @GET
    @Path("customers/orders")
    public String getOrders(@MatrixParam("state") String state) {
        String info = String.format("resource getCustomers(). state=%s%n", state);
        return info;
    }
    ...
 }

output

resource getCustomers(). state=null

The value of state is unexpectedly null this time. The reason is, JAX-RS does not support @MatrixParam to capture the params if they are in the middle, instead we are provided another way to access matrix parameters i.e. PathSegment.

@MatrixParam are not supported for the matrix parameters which are not at the end of the URI. That is probably because matrix params should closely be tied to the part they belong to. For example consider the situation where there are more than one matrix params parts. Should we use @MatrixParam variables loosely in method argument list without specifying what part/segment of the url path they belong to? What if multiple parts have parameters with same name?

Using PathSegment to get matrix param in the middle

PathSegment is an interface. Its instance can be injected by annotating it with @PathParam:

@Path("/")
public class CustomerResource {
    .............
  @GET
  @Path("{var:customers}/orders")
  public String getOrders(@PathParam("var") PathSegment ps) {
      String info = String.format("resource getOrders(). Path:%s, MatrixParams:%s%n",
              ps.getPath(), ps.getMatrixParameters());
      return info;
  }
    .............
}

output

resource getOrders(). Path:customers, MatrixParams:{state=[tx]}

It works this time. Note that we are using template '{var:customers}' instead of simple 'customer', that's because PathSegment only works with @PathParam. We opt to use regex with variable name 'var' and a constant regex expression value 'customers' so it is same as the last example

Multiple matrix parameter parts

Let's extend our example URI to have multiple matrix params part segments:

/customers;state=tx/orders;minBill=60/2017-2

'orders;minBill=60' specifies to get all orders with minimum bill amount 60. The last part '2017-2' specifies the month when orders were placed.

The resource method

@Path("/")
public class CustomerResource {
    .............
  @GET
  @Path("{var1:customers}/{var2:orders}/{month}")
  public String getMonthOrders(@PathParam("var1") PathSegment customerPs,
                               @PathParam("var2") PathSegment orderPs,
                               @PathParam("month") String month) {
      String info = String.format("resource getMonthOrders(). Customers Matrix Param: %s," +
                      " Orders Matrix Param: %s, month :%s%n", customerPs.getMatrixParameters(),
              orderPs.getMatrixParameters(), month);
      return info;
  }
    .............
}

output

resource getMonthOrders(). Customers Matrix Param: {state=[tx]}, Orders Matrix Param: {minBill=[60]}, month :2017-2

Using List of PathSegment

We can use List<PathSegment> in resource method, if there are multiple consecutive possible matrix parts. This is useful when we use regex expression to capture multiple path segment in one resource method.

@Path("/")
public class CustomerResource {
    .............
  @GET
  @Path("testA/{var:.+}")
  public String testList(@PathParam("var") List<PathSegment> pathSegmentList) {
      String temp = "";
      for (PathSegment pathSegment : pathSegmentList) {
       temp+= String.format("Path: %s, Matrix Params %s<br/>", pathSegment.getPath(),
               pathSegment.getMatrixParameters());
      }

      String info = String.format("resource testList.<br/> Matrix Param List:<br/> %s<br/>", temp);
      return info;
  }
}

The regex [.+] will match any character. In above example all paths starting with testA (exclusively) will be captured by 'var' and will be passed as pathSegment list to our resource method.

For example the URI:

/testA/test1;param1=val1;param2=val2/test2/test3;param3=val3

will give following output.

resource testList.
Matrix Param List:
Path: test1, Matrix Params {param1=[val1], param2=[val2]}
Path: test2, Matrix Params {}
Path: test3, Matrix Params {param3=[val3]}

test2 shows empty param map. That's because in our URI, that part doesn't have any matrix params.

Example Project

Dependencies and Technologies Used :

  • jersey-container-servlet 2.25.1: Jersey core Servlet 3.x implementation.
  • JDK 1.8
  • Maven 3.3.9

Matrix Parameters Example Select All Download
  • jaxrs-matrix-param
    • src
      • main
        • java
          • com
            • logicbig
              • example

See Also