Jersey (JAX-RS) Java types to consume request parameter values guide

In Jersey (JAX-RS), to consume HTTP request parameter, cookie, header, path variable and matrix parameter string values, we have following options:

  1. Primitive types – int, char, float, long, double, byte and others.
  2. Types with constructor which accepts single String argument.
  3. Types with a static method with name valueOf or fromString which accepts single String argument. For e.g. Integer.valueOf(String) or java.util.UUID.fromString(String).
  4. Types with implementation of ParamConverterProvider JAX-RS extension SPI which return ParamConverter instance. ParamConverter require fromString method implementation, which takes single String argument and convert that to return a specific type. ParamConverterProvider implementation should be registered as provider with Jersey.
  5. List, Set or SortedSet of types defined above. When we expect parameters to have multiple values for same name, we should use these collection.

In this guide we will see examples to create custom Java classes and use them to consume HTTP request parameter values.

Implementation of ParamConverterProvider JAX-RS extension can be used to consume parameters values into existing util classes like Date or LocalDateTime or custom types.

This is a part of Jersey (JAX-RS) Restful Web Services Development Guides series. Please read Jersey + Spring Boot getting started guide.

Java type with single String argument constructor to consume request parameters values

File: ConstructorDateParamModel.java

package in.geekmj.model;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

/**
 * 
 * @author geekmj
 * DateParamModel is a class with a constructor with one String Argument
 * We can use it as custom type for mapping request parameters, cookies or headers values 
 */
public class ConstructorDateParamModel {

	private String dateAsString;

	/* Expecting ISO-8601 format date string */
	public ConstructorDateParamModel(String dateAsString) {
		this.dateAsString = dateAsString;

	}

	public LocalDateTime getDate() {
		LocalDateTime dateTime = null;
		try {
			dateTime = LocalDateTime.parse(dateAsString, DateTimeFormatter.ISO_DATE_TIME);
		} catch (DateTimeParseException ex) {
			System.err.println("Conversion of dateAsString: " + dateAsString + " using ISO date time failed.");
		}
		try {
			dateTime = LocalDateTime.parse(dateAsString, DateTimeFormatter.ISO_DATE);
		} catch (DateTimeParseException ex) {
			System.err.println("Conversion of dateAsString: " + dateAsString + " using ISO date failed.");
		}

		return dateTime;
	}

}

Above ConstructorDataParamModel can use as type for consuming HTTP request parameter and other values. It has a single String argument constructor. Constructor String argument expected here in ISO Date format. This value parsed with method LocalDateTime.parse(String dateAsString, DateTimeFormatter.ISO_DATE) in another method getDate, which return LocalDateTime object.  When String value is not in ISO Date format, getDate return null value.

Java Type with static method valueOf or fromString to consume request parameters values

File: StaticMethodDateParamModel.java

package in.geekmj.model;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

/**
 * 
 * @author geekmj 
 * DateParamModel is a class with a static method valueOf with one String
 * Argument. We can use it as custom type for mapping request parameters,
 * cookies or headers values.
 */
public class StaticMethodDateParamModel {

	private String dateAsString;

	public StaticMethodDateParamModel() {
	}

	public String getDateAsString() {
		return dateAsString;
	}

	public void setDateAsString(String dateAsString) {
		this.dateAsString = dateAsString;
	}

	public LocalDateTime getDate() {
		LocalDateTime dateTime = null;
		try {
			dateTime = LocalDateTime.parse(dateAsString, DateTimeFormatter.ISO_DATE_TIME);
		} catch (DateTimeParseException ex) {
			System.err.println("Conversion of dateAsString: " + dateAsString + " using ISO date time failed.");
		}
		try {
			dateTime = LocalDateTime.parse(dateAsString, DateTimeFormatter.ISO_DATE);
		} catch (DateTimeParseException ex) {
			System.err.println("Conversion of dateAsString: " + dateAsString + " using ISO date failed.");
		}

		return dateTime;
	}

	/*
	 * Expecting ISO-8601 format date string
	 *  
	 */
	public static StaticMethodDateParamModel valueOf(String dateAsString) {
		StaticMethodDateParamModel staticMethodDateParamModel = new StaticMethodDateParamModel();
		staticMethodDateParamModel.setDateAsString(dateAsString);
		return staticMethodDateParamModel;
	}

}

Above StaticMethodDateParamModel can use as type for consuming HTTP request parameter and other values. It has a single String argument method valueOf which return StaticMethodDateParamModel instance. Similar to previous class we have getDate method here.

Java Types consuming request parameters values with ParamConverterProvider implementation

File : DateParamModel.java

package in.geekmj.model;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

/**
 * 
 * @author geekmj
 * 
 * It is a class with one String attribute dateAsString. Method getDate
 * convert dateAsString to LocalDateTime. We will use it as a custom
 * Type for Request Parameter, Header, Path, Cookie and Matrix values.
 */
public class DateParamModel {

	private String dateAsString;

	public String getDateAsString() {
		return dateAsString;
	}

	public void setDateAsString(String dateAsString) {
		this.dateAsString = dateAsString;
	}

	public LocalDateTime getDate() {
		LocalDateTime dateTime = null;
		try {
			dateTime = LocalDateTime.parse(dateAsString, DateTimeFormatter.ISO_DATE_TIME);
		} catch (DateTimeParseException ex) {
			System.err.println("Conversion of dateAsString: " + dateAsString + " using ISO date time failed.");
		}
		try {
			dateTime = LocalDateTime.parse(dateAsString, DateTimeFormatter.ISO_DATE);
		} catch (DateTimeParseException ex) {
			System.err.println("Conversion of dateAsString: " + dateAsString + " using ISO date failed.");
		}

		return dateTime;
	}

}

File: DateParamModelConvertorProvider.java

package in.geekmj.config;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.ParamConverterProvider;
import javax.ws.rs.ext.Provider;

import in.geekmj.model.DateParamModel;

@Provider
public class DateParamModelConvertorProvider implements ParamConverterProvider {

	@Override
	public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {

		if (rawType.getName().equals(DateParamModel.class.getName())) {
			return new ParamConverter<T>() {

				@SuppressWarnings("unchecked")
				@Override
				public T fromString(String value) {
					DateParamModel dateParamModel = new DateParamModel();
					dateParamModel.setDateAsString(value);
					return (T) dateParamModel;
				}

				@Override
				public String toString(T bean) {
					return ((DateParamModel) bean).getDateAsString();
				}

			};
		}

		return null;
	}

}

Now DateParamModel can used as Type for consuming HTTP request parameter and other values. Observe, DateParamModel don’t have single String argument constructor or method. This conversion handled at DateParamModelConvertorProvider level.

Using Custom Java types in Resource

File : CustomTypeParamterConsumeResource.java

package in.geekmj.resource;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.ws.rs.Consumes;
import javax.ws.rs.CookieParam;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.springframework.stereotype.Component;

import in.geekmj.model.ConstructorDateParamModel;
import in.geekmj.model.DateParamModel;
import in.geekmj.model.StaticMethodDateParamModel;

@Path("/custom-type-for-parameters")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Component
public class CustomTypeParamterConsumeResource {

	@QueryParam("datesAsStrings")
	private List<DateParamModel> dateParamModels;

	@CookieParam("dateParamModelAsCookie")
	private StaticMethodDateParamModel cookieDateParamModel;

	@HeaderParam("dateParamModelAsHeader")
	private ConstructorDateParamModel headerDateParamModel;

	@GET
	public Response getCustomType(@QueryParam("dateAsString") DateParamModel dateParamModel) {

		Map<String, Object> result = new HashMap<String, Object>();

		boolean error = false;

		if (dateParamModel != null && dateParamModel.getDate() != null) {
			result.put("dateAsString", dateParamModel.getDate());
		} else if (dateParamModel != null) {
			error = true;
		}

		if (headerDateParamModel != null && headerDateParamModel.getDate() != null) {
			result.put("dateParamModelAsHeader", headerDateParamModel.getDate());
		} else if (headerDateParamModel != null) {
			error = true;
		}

		if (cookieDateParamModel != null && cookieDateParamModel.getDate() != null) {
			result.put("dateParamModelAsCookie", cookieDateParamModel.getDate());
		} else if (cookieDateParamModel != null) {
			error = true;
		}

		if (dateParamModels != null && dateParamModels.size() > 0) {
			List<LocalDateTime> localDateTimes = new ArrayList<LocalDateTime>();

			for (DateParamModel dateParamModelTemp : dateParamModels) {
				if (dateParamModelTemp.getDate() != null) {
					localDateTimes.add(dateParamModelTemp.getDate());
				} else {
					error = true;
				}
			}

			result.put("datesAsStrings", localDateTimes);
		}

		return error ? Response.status(Status.BAD_REQUEST)
				.entity("{'error:'Expected dateAsString in ISO DATE format''}").build()
				: Response.ok().entity(result).build();
	}

}

Above Resource takes ISO Date strings as request parameter, cookie and header values. In response it returns a JSON with dates detail.

Testing GET request for URL http://localhost:8080/custom-type-for-parameters?dateAsString=1994-11-05T08:15:30%2B01:00&datesAsStrings=2016-01-03T10:15:30&datesAsStrings=2016-01-03T10:15:30 with Postman chrome plugin.

Postman HTTP Request & Response for API URI custom-type-for-parameters

Postman HTTP Request & Response for API URI custom-type-for-parameters

References

  1. Official Jersey Documentation
Download Icon SmallDownload the Full ProjectGithub IconFollow Project On Github

Leave a Reply

Your email address will not be published. Required fields are marked *