Apache CXF: JAX-RS Restful web service using @FormParam annotation

In this article, we will learn and implement @FormParam annotation in JAX-RS Restful web service. @FormParam binds the value/s of form parameter sent by the client in the POST request into formal arguments of Java method

@FormParam v/s @QueryParam

Use @FormParam for POST request when using form and prefer @QueryParam for GET requests

Annotation Used

  • @FormParam (javax.ws.rs.FormParam)
  • @Path (javax.ws.rs.Path)
  • @GET (javax.ws.rs.GET)
  • @Service (org.springframework.stereotype.Service)

Technology Used

  • Java 1.7
  • Eclipse Luna IDE
  • Spring-4.0.0-RELEASE
  • Apache-CXF-3.0.0
  • Apache Maven 3.2.1
  • Apache Tomcat 7.0.54

Mavenize or download required jars

Add Apache-CXF-3.0.0 and Spring-4.0.0-RELEASE dependencies to pom.xml

<dependencies>
		<!-- Apache CXF -->
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxrs</artifactId>
			<version>${cxf.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-transports-http</artifactId>
			<version>${cxf.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-transports-http-jetty</artifactId>
			<version>${cxf.version}</version>
		</dependency>

		<!-- Apache HTTP components for writing test client -->
		<dependency>
			<groupId>commons-httpclient</groupId>
			<artifactId>commons-httpclient</artifactId>
			<version>3.1</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
			<version>${apache.httpcomponents.version}</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpcore</artifactId>
			<version>${apache.httpcomponents.version}</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpmime</artifactId>
			<version>${apache.httpcomponents.version}</version>
			<scope>compile</scope>
		</dependency>

		<!-- Spring framework -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
		</dependency>
	</dependencies>

Folks who aren’t familiar with Maven concepts or don’t require maven for their project, can download the below jars individually from the spring site or maven repository and include them in the classpath.

Directory Structure

Before moving on, let us understand the directory/package structure once you create project in Eclipse IDE
Maven has to follow certain directory structure

  • src/test/java –> test related files, mostly JUnit test cases
  • src/main/java –> create java source files under this folder
  • src/main/resources –> all configuration files placed here
  • Maven Dependencies or Referenced Libraries –> includes jars in the classpath
  • WEB-INF under webapp –> stores web.xml & other configuration files related to web application

Project Structure (Package Explorer view in Eclipse)

1_ApacheCXF_FormParam_Project_Structure_In_Eclipse

Jars Libraries Used in the Project (Maven Dependencies)

2_ApacheCXF_FormParam_Jars_In_Classpath

Web application

For any web application, entry point is web.xml which describes how the incoming http requests are served / processed. Further, it describes about the global-context and local-context param (i.e.; <context-param> & <init-param>) for loading files particular to project requirements & contains respective listener.

With this introduction, we will understand how we configured web.xml for Apache CXF JAX-RS Restful web service

web.xml (the entry point –> under WEB-INF)

This web.xml file describes,

  • Like any JEE web framework register org.apache.cxf.transport.servlet.CXFServlet with servlet container
  • http requests with URL pattern “/services/*” will be sent to the registered servlet called “CXFServlet” (org.apache.cxf.transport.servlet.CXFServlet)
  • <context-param> with its attributes describes the location of the “apache-cxf-service.xml” file from where it has to be loaded. We will discuss briefly about this file
  • <welcome-file-list> files under this tag is the start-up page

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<display-name>ApacheCXF-FormParam</display-name>

	<!-- Apache CXF -->
	<servlet>
		<servlet-name>CXFServlet</servlet-name>
		<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>CXFServlet</servlet-name>
		<url-pattern>/services/*</url-pattern>
	</servlet-mapping>

	<!-- web context param -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>WEB-INF/apache-cxf-services.xml</param-value>
	</context-param>

	<!-- listener -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- welcome file list -->
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>

 

Apache CXF services

Apache CXF comes with spring based configuration, so it is easy to register beans in the spring container much like we do any bean in spring application. CXFServlet receives the incoming http requests and invokes corresponding registered beans in according to http url path

NOTE: For this Restful JAX-RS application, we are using Spring annotations to define/register beans in the spring container thereby avoiding lot of boilerplate code to write

This apache-cxf-services.xml describes,

  • <context:annotation-config /> to activate annotation on the registered beans with the application context
  • <context:component-scan base-package=”” /> this tag scans all classes & sub-classes under the value of base-package attribute and register them with the Spring container
  • <jaxrs:server /> defines which service bean to be invoked for the incoming http requests. In this case, any wild card pattern “/” will invoke “playerService” which is registered as service bean using @Service(“playerService”) annotation (on top of the PlayerServiceImpl java class)
  • for two different beans we can have two different url-pattern(address) like
		<jaxrs:server id="restContainer" address="/">
			<jaxrs:serviceBeans>
				<ref bean="playerService" />
			</jaxrs:serviceBeans>
		</jaxrs:server>
		
		<jaxrs:server id="twotest" address="/two">
			<jaxrs:serviceBeans>
				<ref bean="testService" />
			</jaxrs:serviceBeans>
		</jaxrs:server>

apache-cxf-services.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
	xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
	http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<!-- to turn on annotation wiring == turns on only the registered beans
		through ApplicationContext -->
	<context:annotation-config />

	<!-- scans and register beans using annotation-config (metadata) -->
	<context:component-scan base-package="com.apache.cxf.formparam.service" />

	<!-- register restful web service endpoints -->
	<jaxrs:server id="restContainer" address="/">
		<jaxrs:serviceBeans>
			<ref bean="playerService" />
		</jaxrs:serviceBeans>
	</jaxrs:server>
</beans>

 

Let’s see coding in action

 

URL Pattern

Http url for any common web application is http://<server>:<port>/<root-context>/<from_here_application_specific_path>

In our example, we are going to deploy the war into local Tomcat 7.0 server so our server and port are localhost and 8080 respectively. Context root is the project name i.e.; ApacheCXF-FormParam. Initial path for this application is http://localhost:8080/ApacheCXF-FormParam

We have configured “/services/*” as url-pattern for CXFServlet in web.xml and at interface-level (or say class-level) path configured is “/player” using @Path annotation. Next respective path for each method annotated with @Path (method-level)

Player Service interface

A simple method which takes three-arguments using @FormParam annotation (multiple parameters)
URL: http://localhost:8080/ApacheCXF-FormParam/services/player/addinfo
POST request from the form will invoke this method, when relative action (path) is set to services/player/addinfo

NOTE: It’s always a good programming to do code-to-interface and have its implementation separately

IPlayerService.java

package com.apache.cxf.formparam.service;

import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;

@Path("/player")
public interface IPlayerService {

	// http://localhost:8080/ApacheCXF-FormParam/services/player/addinfo
	@POST
	@Path("/addinfo")
	public Response getPlayerInfo(
			@FormParam("name") String playerName,
			@FormParam("age") int age,
			@FormParam("matches") int matches);
}

Player Service implementation

Implements above interface returning Response object

PlayerServiceImpl.java

package com.apache.cxf.formparam.service;

import javax.ws.rs.core.Response;

import org.springframework.stereotype.Service;

@Service("playerService")
public class PlayerServiceImpl implements IPlayerService {

	/**
	 * this method takes three argument from FormParam and returns a Response
	 */
	public Response getPlayerInfo(String playerName, int age, int matches) {

		String playerInfo = "Player with information " + "[name=" + playerName +  ", age=" + age + ", matches=" + matches + "]" + " added to the database";
		return Response.status(200).entity(playerInfo).build();
	}
}

 

View Technologies

 

Start up page which redirects the request to the addPlayer.html page
index.jsp (\src\main\webapp\index.jsp)

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>JAX-RS Restful web service</title>
</head>
<body>
	<center>
		<b>Welcome to the JAX-RS Restful web service Learning</b>
		<h2>
			<%
				response.sendRedirect("addPlayer.html");
			%>
		</h2>
	</center>
</body>
</html>

 

Simple HTML form with POST action (method) which takes three inputs from the user to add a player to the database
addPlayer.html (\src\main\webapp\addPlayer.html)

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>JAX-RS Restful web service</title>
</head>
<body>
	<center>
		<b>Welcome to the JAX-RS Restful web service Learning</b>
		<form method="post" action="services/player/addinfo">
			<table>
				<tr>
					<td>Name:</td>
					<td><input type="text" name="name" /></td>
				</tr>
				<tr>
					<td>Age:</td>
					<td><input type="text" name="age" /></td>
				</tr>
				<tr>
					<td>Matches:</td>
					<td><input type="text" name="matches" /></td>
				</tr>
				<tr>
					<td colspan="1"><input name="submit" type="submit"
						value="Add Player" /></td>
					<td colspan="1"><input name="reset" type="reset" value="Reset" /></td>
				</tr>
			</table>
		</form>
	</center>
</body>
</html>

 

Deployment

  • Run maven command to build the war : mvn clean install (use command prompt or integrated maven in eclipse IDE
  • Copy the war file from the target folder
  • Paste it into apache tomcat (webapps folder)
  • Start the tomcat server

Test the service !!

 

Testing

Access the default URL http://localhost:8080/ApacheCXF-FormParam it will redirect to addPlayer.html page which displays user fields for entering name, age & matches to capture player information and store it in the database

Or else directly access the URL for the same page
http://localhost:8080/ApacheCXF-FormParam/addPlayer.html  –> displays below page
3_ApacheCXF_FormParam_addPlayer_page

Enter details of any player like
Name                    :  Steve Waugh
Age                        :  49
Matches              :  168

And click “Add Player” button
4_ApacheCXF_FormParam_addPlayer_enter_details

Clicking “Add Player” button will invokes POST method configured in the form tag with action=“services/player/addinfo”

On successful execution of the request, a success message is returned to the user as shown below
5_ApacheCXF_FormParam_addPlayer_success_page

Conclusion:  When the requirement is to send the data from the form, then this approach would be appropriate

Download project

ApacheCXF-@FormParam-annotation (4kB)

Happy Coding !!
Happy Learning !!

Apache CXF: JAX-RS Restful web service using @HeaderParam/@Context annotation
Apache CXF: JAX-RS Restful web service using @MatrixParam annotation