<body><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener('load', function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <div id="navbar-iframe-container"></div> <script type="text/javascript" src="https://apis.google.com/js/platform.js"></script> <script type="text/javascript"> gapi.load("gapi.iframes:gapi.iframes.style.bubble", function() { if (gapi.iframes && gapi.iframes.getContext) { gapi.iframes.getContext().openChild({ url: 'https://www.blogger.com/navbar.g?targetBlogID\x3d8334277\x26blogName\x3dSriram\x27s+Blog\x26publishMode\x3dPUBLISH_MODE_BLOGSPOT\x26navbarType\x3dBLUE\x26layoutType\x3dCLASSIC\x26searchRoot\x3dhttps://metallicatony.blogspot.com/search\x26blogLocale\x3den\x26v\x3d2\x26homepageUrl\x3dhttp://metallicatony.blogspot.com/\x26vt\x3d6147907796332168684', where: document.getElementById("navbar-iframe-container"), id: "navbar-iframe" }); } }); </script>

Friday, November 08, 2013

CRUD APIs or Web Services (REST & SOAP) using Java, Apache CXF, Spring, Hibernate, Maven and Log4J

This sample project is an extension to the previous project CRUD using Java Spring and Hibernate. This project focuses on building a web application to expose the already developed features (from the previous project) as REST and SOAP webservices. To accomplish this task, Apache CXF was used. CXF makes the development of RESTful and SOAPful services simple by using java annotations. It internally uses HTTP binding to map a java method (service or operation) to any given URI and HTTP verb. Spring framework is internally used by CXF to create spring beans and inject those beans in the web application to service the incoming requests.

What’s new in this project?
1) Creation of a web application
2) Integration and configuration of Apache CXF to expose web services
3) Annotations to configure REST services @Path, @Produces, @GET, @POST, @PUT and @DELETE
4) Annotations to configure SOAP services @WebService, @WebMethod and @WebParam
5) REST and SOAP endpoint declarations and web.xml configurations

pom.xml
As a first step, the pom.xml of previous project was taken and added with the following dependencies
 
<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-frontend-jaxws</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-rs-extension-providers</artifactId>
 <version>${cxf.version}</version>
</dependency>
<dependency>
 <groupId>org.codehaus.jackson</groupId>
 <artifactId>jackson-jaxrs</artifactId>
 <version>${jackson.version}</version>
</dependency>
<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-web</artifactId>
 <version>${spring.version}</version>
</dependency>

cxf-rt-transports-http is the transport layer of CXF which abstracts the binding and transport details to the rest of the layers. cxf-rt-frontend-jaxws and cxf-rt-frontend-jaxrs are the frontends of CXF that are used to expose SOAP and REST services respectively. cxf-rt-rs-extension-providers has optional extensions that may or may not be needed. jackson-jaxrs is needed for adding JSON functionality to the needed webservices. These two artifacts will be configured as extensions in CXF that will be covered later. Spring-web is internally used by CXF and so its needed. The complete version of pom.xml can be located in the project which can be downloaded from the link provided at the bottom of this post.

Apart from the above dependencies there is one more important addition to pom.xml. Its plugins. There are 2 plugins added – one for the maven-war-plugin. This is used to build a war artifact out of the project. The web.xml relative path need to be mentioned in this plugin so that it picks it up properly. Second plugin is about adding tomcat plugin to the project so that the built webapp artifact (war file) can be automatically deployed in a light-weight tomcat by just executing a simple maven goal. Had this option not available, it would be time consuming to have tomcat installed separately and to deploy the built war file every time a change was made in the code. Maven goals are essentially tasks (Mojos) which can be used effectively to execute something. These goals are configured as plugins for maven.
<build>
<pluginManagement>
  <plugins>
  <plugin>            
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.3</version>
    <configuration>
    <webXml>src/main/webapp/WEB-INF/web.xml</webXml>        
   </configuration>
   </plugin>
    <plugin>
      <groupId>org.apache.tomcat.maven</groupId>
      <artifactId>tomcat7-maven-plugin</artifactId>
      <version>2.1</version>
                <configuration>
                    <path>/</path>
                    <port>8090</port>
    </configuration>
    </plugin>
  </plugins>
</pluginManagement>
</build>

Once this configuration is done, running
1) mvn clean install will clean and then build the project to produce a war file.
2) mvn tomcat7:run will deploy the built war file and start the light-weight tomcat server.

Web descriptor changes (web.xml)
The next important configuration is the web application descriptor – web.xml. A folder WEB-INF is created under src/main/webapp where this file is created. This is the configuration that any application server is going to parse as a first step to know what to do.

As expected “org.springframework.web.context.ContextLoaderListener” is provided as a listener class. This is the spring context of our web application. When the application loads into memory, Spring creates the context by creating beans that are mentioned in the configuration files. These configuration file names are the params for “contextConfigLocation” param (here it is applicationContext.xml and cxf-bean.xml).

The most important configuration is for CXF. CXF is a servlet. A web servlet is something that keeps waiting and listening for requests at the configured URL. Once it receives a request, it serves them and continues to listen till it is brought down. That’s exactly what CXF does. It keeps listening at the root URL(/) wherever this application is deployed. Once it gets a request, it invokes the corresponding Spring beans to serve the request accordingly. Here is the complete web.xml file

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<web-app 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"
 version="2.5">
 <display-name>Employee Service</display-name>
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
  classpath*:cxf-bean.xml,
  classpath*:applicationContext.xml
  </param-value>
 </context-param>

 <context-param>
  <param-name>initializeContextOnStartup</param-name>
  <param-value>true</param-value>
 </context-param>

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

 <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>/*</url-pattern>
 </servlet-mapping>
</web-app>

Application Context Configuration Changes (applicationContext.xml)
This xml file contains the definition of all the spring beans needed for our application. This is exactly the same configuration what was used in the previous project. If you want to, please refer the explanation in the previous post CRUD using Spring and Hibernate

CXF bean configuration changes (cxf-bean.xml)
This is the master configuration file for apache cxf containing the definitions for JAXRS containers. This file is referred from web.xml. This means that web.xml file is parsed by the application server before even this file is parsed. This again in turn means all the spring beans are instantiated and readily available in the spring context before this step. This file is used to configure the jaxrs (rest) or jaxws(soap) service endpoints and map them to the corresponding spring beans. Any providers or extensions if any needed are also configured here. If you have a look at the file , its pretty much understandable. We ignore the built-in CXF JSON feature but instead use Jackson JSON and so its configured as a provider.

Employee Services (REST)
Apart from the above configurations, rest all is self-explanatory. I have created Employee Service interface (com.samples.service package) and exposed some HTTP operations. The corresponding Employee Service Impl (com.samples.service.impl package) has the implementation details. Things to note are the annotations that are used to map the HTTP methods of a specific URL to a specific method of a spring service bean. These annotations (@Path, @PathParam, @GET, @POST etc) are in the Interface (EmployeeService.java) These service beans internally call the BO beans which in turn call the DAO beans. The BO beans also depend on adapter beans to convert the hibernate entity objects to web response objects as needed by the service beans.

The list of REST services exposed (wadl) from this webapp can be seen by accessing the endpoint
http://localhost:8090/?_wadl

Employee Services (SOAP)
A sample SOAP service is exposed in EmployeeServiceWS interface. The corresponding implementation can be found in EmployeeServiceWSImpl. This is different from REST services in just the annotations (@WebService, @WebMethod, @WebParam) that are used. An additional configuration is provided in cxf-bean.xml file to refer the bean name(employeeServiceWS) of SOAP service and the endpoint where it serves.
<jaxws:endpoint id="employeeServiceSOAP" implementor="#employeeServiceWS" address="/soapservices" />
The list of SOAP services exposed (wsdl) from this webapp can be known by accessing the endpoint
 http://localhost:8090/soapservices?wsdl 
The above two endpoints can be imported in SOAP UI and the services can be validated easily. Below is a screenshot of the imported wadl and wsdl in SOAP UI. This entire project can be downloaded from my GitHub repository - EmployeeWebApp Project and feel free to play around with it.

Labels: ,