Jersey (JAX-RS) @FormParam HTML form data handling

There are multiple ways for consuming HTML form data (application/x-www-form-urlencoded) in Jersey. Using @FormParam annotation we can inject Form values in Resource method. We can use it just like other @*Param.

Jersey resource method need to know they have to handle HTML form data, for it we explicitly specify @Consumes("application/x-www-form-urlencoded").

Jersey (JAX-RS) form data handling illustration

There are multiple ways in which we can handle HTML form data using Jersey. Injecting Form data using @FormParam is one of them.

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

Use @FormParam

Using @FormParam we can inject specific HTML form parameters values in Resource method. It’s use is similar to other @*Param annotations.

File: FormParamResource.java

package in.geekmj.resource;

import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import org.springframework.stereotype.Component;

/**
 * 
 * @author geekmj Three ways to get Form data in Jersey
 */
@Path("/form-data")
@Produces(MediaType.TEXT_HTML)
@Component
public class FormParamResource {

	/**
	 * Using @FormParam inject form data in method arguments
	 * 
	 * @param name
	 * @param phoneNumber
	 * @return
	 */
	@POST
	@Path("/form-param")
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public Response getFormDataUsingFormParam(@FormParam("name") String name, @FormParam("phone") String phoneNumber) {
		
		return Response.ok(getHtmlResponse(name, phoneNumber)).build();
	}

	private String getHtmlResponse(String name, String phoneNumber) {
		StringBuilder responseStr = new StringBuilder("<html><head><title>Form Data</title></head><body>");
		responseStr.append("<h2>Submitted form data</h2><div><span>Name : "+name+"</span><br/><span>Phone : "+phoneNumber+"</span></div></body>");
		return responseStr.toString();
	}
}

We have used @FormParam to get name and phone from x-www-form-urlencoded form data request.

Use MultivaluedMap in method injection

We can inject all Form values in method as MultivaluedMap<String,String> when method has consume("application/x-www-form-urlencoded") annotation.

Note: It may not work in Spring Boot when Spring Web module used. You may can see a warning in log saying A servlet request to the URI http://xyz.com/abc contains form parameters in the request body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using @FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected.

File: FormParamResource.java

package in.geekmj.resource;

import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import org.springframework.stereotype.Component;

/**
 * 
 * @author geekmj Three ways to get Form data in Jersey
 */
@Path("/form-data")
@Produces(MediaType.TEXT_HTML)
@Component
public class FormParamResource {

	/**
	 * Using Multivalued Map inject form data in method single map argument
	 * Note: It may not work if another Servlet is processing the request before Jersey Servlet or filter
	 * @param name
	 * @param phoneNumber
	 * @return
	 */
	@POST
	@Path("/multivalued-map")
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public Response getFormDataUsingMultivaluedMap(MultivaluedMap<String, String> formParams) {
		
		//Same as formValues.get("name").get(0);
		String name = formParams.getFirst("name");
		String phoneNumber = formParams.getFirst("phone");
		return Response.ok(getHtmlResponse(name, phoneNumber)).build();
	}

	private String getHtmlResponse(String name, String phoneNumber) {
		StringBuilder responseStr = new StringBuilder("<html><head><title>Form Data</title></head><body>");
		responseStr.append("<h2>Submitted form data</h2><div><span>Name : "+name+"</span><br/><span>Phone : "+phoneNumber+"</span></div></body>");
		return responseStr.toString();
	}
}

Use UriInfo method injection with @Context

We can get all form values in MultivaluedMap<string, string> using UriInfo.getQueryParameters() method. UriInfo can injected as method attribute using @Context annotation.

Note: It may not work in Spring Boot when Spring Web module used.

package in.geekmj.resource;

import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import org.springframework.stereotype.Component;

/**
 * 
 * @author geekmj Three ways to get Form data in Jersey
 */
@Path("/form-data")
@Produces(MediaType.TEXT_HTML)
@Component
public class FormParamResource {

	/**
	 * Using Multivalued Map inject form data in method single map argument
	 * Note: It may not work if another Servlet is processing the request before Jersey Servlet or filter
	 * @param name
	 * @param phoneNumber
	 * @return
	 */
	@POST
	@Path("/context")
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public Response getFormDataUsingContext(@Context UriInfo ui) {
		
		MultivaluedMap<String, String> formValues = ui.getQueryParameters();
		
		//Same as formValues.get("name").get(0);
		String name = formValues.getFirst("name");
		String phoneNumber = formValues.getFirst("phone");
		return Response.ok(getHtmlResponse(name, phoneNumber)).build();
	}

	private String getHtmlResponse(String name, String phoneNumber) {
		StringBuilder responseStr = new StringBuilder("<html><head><title>Form Data</title></head><body>");
		responseStr.append("<h2>Submitted form data</h2><div><span>Name : "+name+"</span><br/><span>Phone : "+phoneNumber+"</span></div></body>");
		return responseStr.toString();
	}
}

Testing form data handling by Jersey

File: testform.html

<!DOCTYPE html>
<html>
	<head>
	<meta charset="UTF-8">
	<title>Form to test Jersey form data handling</title>
	</head>
<body>

	<h2>Jersey form data handling using @formParam annotation</h2>
	<form action="/form-data/form-param" method="POST" name="form1">
		<label>Name</label> <input maxlength="15" name="name"/> 
		<br/><br/>
		<label>Phone</label> <input maxlength="15" name="phone"/> 
		<br/><br/>
		<input type="submit" value="Submit" />
		<input type="reset" value="Reset" />
	</form>
	<br/>
	<h2>Jersey form data handling using MultivaluedMap injected</h2>
	<form action="/form-data/multivalued-map" method="POST" name="form2">
		<label>Name</label> <input maxlength="15" name="name" /> 
		<br/><br/>
		<label>Phone</label> <input maxlength="15" name="phone"/> 
		<br/><br/>
		<input type="submit" value="Submit" />
		<input type="reset" value="Reset" />
	</form>
	<br/>
	<h2>Jersey form data handling using context.getQueryParameters() </h2>
	<form action="/form-data/context" method="POST" name="form3">
		<label>Name</label> <input maxlength="15" name="name"/> 
		<br/><br/>
		<label>Phone</label> <input maxlength="15" name="phone"/> 
		<br/><br/>
		<input type="submit" value="Submit" />
		<input type="reset" value="Reset" />
	</form>
</body>
</html>

Download complete source code for this project and then follow this instruction to run the application.

Go to http://localhost:8080/testform.html.

jersey form data handling gif

Jersey form data handling test

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 *