JAX-RS Server API Snippets

September 28th, 2014 by

Because a lot of my current projects are using JAX-RS in different versions I’d like to write down and share some frequently used snippets for implementing RESTful web-services with the JAX-RS specification here.


Using RegEx in Path Expressions

Sometimes we need to extract multiple parameters from a path expression e.g. in the following example where year, month and day are fragments if the path.

public Response getOrders(@PathParam("year") final int year, @PathParam("month") final int month, @PathParam("day") final int day) {
	return Response.ok("Year: " + year + ", month: " + month + ", day: " + day).build();

When we’re calling the method e.g. using curl, we’re getting the expected result:

$ curl -XGET http://localhost:8080/app/rs/orders/2004-12-24
Year: 2004, month: 12, day: 24%

Using Default Parameters

Instead of handling expected values manually we may use a simply annotation instead:

public Response getUsers(@DefaultValue("10") @QueryParam("limit") int limit){
	// ...

Handling and Mapping Exceptions

Sometimes we want to modify exceptions being passed to the client, filter the payload, set a specific HTTP status for the response:

So first of all let’s say we have the following exception:

class CustomException extends Exception {}

Then the following provider allows us to pass the exception and set the HTTP response status to 400 (BAD_REQUEST)

public class ConcurrentEntityModificationExceptionMapper implements ExceptionMapper<CustomException> {
	public Response toResponse(final CustomException e) {
		return Response.status(Status.BAD_REQUEST).entity(e).type(MediaType.APPLICATION_JSON).build();

Finally our RESTful webservice just needs to declare the exception thrown

public class SomeService {
	public Response getSth() throws CustomException {
		// do sth.
		return Response.ok().build();


Sometimes when a web-service implementation is growing too big or we want to encapsulate similar operations in a separate class, we may separate concerns using sub-resources:

This is our base web-service that’s getting the sub-resources injected and delegates the work to its sub-resources.

public class PermissionService {
	ReadPermissionService readPermissionService;
	WritePermissionService writePermissionService;
	public ReadPermissionService readPermissions(){
		return readPermissionService;
	public WritePermissionService writePermissions(){
		return writePermissionService;

This is one example of a sub-resource here:

public class ReadPermissionService {
	public Response getReadPermission(@PathParam("name") final String name) {
		// do stuff
		return Response.ok().build();

Setting the REST-Service’s Application Path

Say we’d like to set “/rs” as the prefix for all RESTful web-services in our application, depending on the application server and JAX-RS version used we may either set it by modifying the web.xml or using a configuration class.

Option 1: Modify web.xml


Option 2: Configuration class

public class RESTConfiguration extends Application {}

Obtain Contextual Information

Sometimes we need to access information from the HTTP request or the servlet configuration in our REST service.

JAX-RS allows us to inject instance of the following contextual objects using the qualifier @Context.

The following classes may be injected:

An example:

public Response echo(@Context HttpServletRequest req){
	// do stuff with request ..
	return Response.ok().build();

Handling Files with specific Media Types

Let’s say we have an image store and we’d like to allow the users of our service to download images of different media types by their given file-name.

This is our solution:

public Response fetchImage(@PathParam("image") final String image) {
	File imageFile = new File("/tmp/" + image);
	if (!imageFile.exists()) {
		throw new WebApplicationException(404);
	String mediaType = new MimetypesFileTypeMap().getContentType(imageFile);
	return Response.ok(imageFile, mediaType).build();

We’re now able to download an image with the correct media type using the following URL: /rs/images/head.png

Handling Generic Collections

Type erasure might cause errors when the type information in a generic collection is needed to select a suitable message body writer. That’s why we’re using the wrapper class, GenericEntity<T> here.

public Response getUsers(){
	List<User> users = userBean.findAll();
	return Response.ok(new GenericEntity<List<User>>(users){}).build();

De-/Serialize Custom Domain Objects

Sometimes we encounter domain objects that may not be wrapped using JAX-B annotations or Jackson/YourTrustedJsonProvider annotations so that we need to write custom serializers and deserializers for them.

Here is an example for this use-case:

Custom MessageBodyWriter

public class CarToExoticFormatWriter implements MessageBodyWriter<Car> {
  public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
    return Car.class.isAssignableFrom(type);
  public long getSize(Car car, Class<?> type, Type genericType, Annotation annotations[], MediaType mediaType) {
    return -1;
  public void writeTo(Car car, Class<?> type, Type genericType, Annotation[] annotations,
      MediaType mediaType, MultivaluedMap<String, Object> headers, OutputStream out) throws IOException {
    Writer Writer = new OutputStreamWriter(out);
	// ..

Custom MessageBodyReader

public class MyCustomUnmarshaller implements MessageBodyReader {
	public boolean isReadable(Class aClass, Type type, Annotation[] annotations, MediaType mediaType) {
		return true;
	public Object readFrom(Class aClass, Type type, Annotation[] annotations, MediaType mediaType, MultivaluedMap multivaluedMap, InputStream is) throws IOException, WebApplicationException {
		Object result = .... // unmarshal here
		return result;


Additional REST articles of mine

Please feel free to have a look at these tutorials of mine covering different aspects of handling or creating RESTful webservices.

Article Updates

  • 2015-08-06: Links to other REST articles of mine added.
  • 2015-10-22: Link list updated.

Tags: , , , , , , , ,

Leave a Reply

Please note, that no personal information like your IP address is stored and you're not required to enter you real name.

Comments must be approved before they are published, so please be patient after having posted a comment - it might take a short while.

Please leave these two fields as-is: