JAX-RS Path Segments and Matrix Parameters
Matrix Parameters are different from Query Parameters. Query parameters are typically placed at the end of the URI using the ? character. Matrix Parameters can be placed in every URI segment using the ; character. This tutorial shows you how to retrieve the matrix parameters, either programatically or injecting with @MatrixParam
annotation.
JAX-RS Path Segments and Matrix Parameters with @PathParam
The @PathParam
JAX-RS annotation can not only inject the value of a path parameter, it can also inject instances of PathSegment
.
Get Single Path Segment
We can inject an instance of PathSegment
using the @PathParam
annotation. Using this PathSegment
we can obtain the value of the actual URI segment using the getPath()
method. We can also obtain a map containing all the matrix parameters applied to that particular URI segment using the getMatrixParameters()
.
package com.memorynotfound.rs;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import java.util.List;
@Path("/cars")
public class CarResource {
@GET
@Path("{brand}/{model}")
@Produces(MediaType.APPLICATION_JSON)
public Response getCars(@PathParam("brand") String brand,
@PathParam("model") PathSegment car){
String model = car.getPath();
String color = car.getMatrixParameters().getFirst("color");
System.out.println("brand: " + brand);
System.out.println("model: " + model);
System.out.println("color: " + color);
return Response.ok().build();
}
}
In the previous code, suppose we make a HTTP GET request with the following path. Notice we included a matrix parameter color for the path parameter model.
GET /cars/BMW/320;color=black
The service will print out the following info to the console:
brand: BMW
model: 320
color: black
Get Multiple Path Segment
You can match multiple URI segments with a single path parameter. You do this by injecting a list of PathSegments for that single path parameter.
package com.memorynotfound.rs;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import java.util.List;
@Path("/cars")
public class CarResource {
@GET
@Path("{brand}/{model: .+}/{year}")
@Produces(MediaType.APPLICATION_JSON)
public Response getCars(@PathParam("brand") String brand,
@PathParam("model") List<PathSegment> cars,
@PathParam("year") Integer year){
System.out.println("brand: " + brand);
for (PathSegment segment : cars){
System.out.println("model: " + segment.getPath());
for (String name : segment.getMatrixParameters().keySet()){
String value = segment.getMatrixParameters().getFirst(name);
System.out.println("\tmatrix param name: " + name + " value: " + value);
}
}
System.out.println("year: " + year);
return Response.ok().build();
}
}
In this example we are mapping the model BMW and E92 to the same model path parameter. We also provide different matrix parameters to these path segments.
GET /cars/BMW/E92;color=black/M3;maker=john/2015
This will produce the following output:
brand: BMW
model: E92
matrix param name: color value: black
model: M3
matrix param name: maker value: john
year: 2015
Get Path Segments and Matrix Parameters Programatically
Instead of injecting the PathSegment
using the @PathParam
, we can also retrieve these programatically by injecting an instance of UriInfo
with the @Context
annotation. Next we can get a list of the PathSegment
using the getPathSegments()
.
package com.memorynotfound.rs;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import java.util.List;
@Path("/orders")
public class OrderResource {
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response getOrders(@Context UriInfo info){
PathSegment model = info.getPathSegments().get(1);
System.out.println("id: " + model.getPath());
for (String name : model.getMatrixParameters().keySet()){
String value = model.getMatrixParameters().getFirst(name);
System.out.println("\tmatrix param name: " + name + " value: " + value);
}
return Response.ok().build();
}
}
We provide a matrix parameter to the id path parameter.
GET /orders/4492;delivery=immediate
This generates the following output:
id: 4492
matrix param name: delivery value: immediate
Get Matrix Parameters with @MatrixParam
We can also inject the matrix parameters immediately using the @MatrixParam
JAX-RS annotation.
Note: when using the@MatrixParam
and you have repeating matrix parameters defined in your URI that are applied to many different path segments it is uncertain which matrix parameter is used. And if this is the case you should go back and use thePathSegment
to get the matrix parameters.
package com.memorynotfound.rs;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
@Path("/products")
public class ProductResource {
@GET
@Path("{id}/{status}")
@Produces(MediaType.APPLICATION_JSON)
public Response getProducts(@PathParam("id") String id,
@MatrixParam("delivery") String delivery,
@PathParam("status") String status){
System.out.println("id: " + id);
System.out.println("delivery: " + delivery);
System.out.println("status: " + status);
return Response.ok().build();
}
}
Notice we registered 2 matrix parameters for different path segments. As we can only map a single matrix parameter with the @MatrixParam
annotation, it is uncertain which parameter will be mapped.
GET /products/4492;delivery=immediate/active;delivery=delayed
Produces the following output
id: 4492
delivery: delayed
status: active
Sending Matrix Parameters with JAX-RS Client API
This example shows you how to pass matrix parameters using JAX-RS Client API. By building each path separately you can register separate matrix parameters for each URI Path Segment. You can add a matrix parameter using the WebTarget#matrixParam(name, value)
method.
package com.memorynotfound.rs;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.Response;
public class RunClient {
public static void main(String... args){
Client client = ClientBuilder.newClient();
Response response = client
.target("http://localhost:8081/jaxrs-matrix-param/api/cars/{brand}")
.resolveTemplate("brand", "BMW")
.path("E92").matrixParam("color", "black")
.path("M3").matrixParam("maker", "john")
.path("2015")
.request()
.get();
if (response.getStatus() == 200){
System.out.println("Response: " + response.readEntity(String.class));
}
client.close();
}
}
Best explanation of PathSegment / Matrix Parameters I’ve found on the net, thank you!