Ehcache With CXF Web Service
Ehcache With CXF Web Service explains about the step by step details of Creating / Developing restful services using Apache CXF, Eclipse and Ehcache
Apache CXF is a free and open source project, and a fully featured Webservice framework. It helps you building webservices using different front-end API's, like as JAX-RS and JAX-WS.
Ehcache is a famous open source caching implementation available in java, By using caching technique, we can reduce the method invocation and reduce the response time dramatically. Ehcache consists with more functionalities as compared to spring cache
You can see the below example, which is demonstrate Ehcache With CXF Web Service
Required Libraries
You need to download
Following jar must be in classpath (You need to download spring 3.1 or higher separately)
- aopalliance-1.0.jar
- commons-logging-1.1.1.jar
- cxf-2.7.3.jar
- httpasyncclient-4.0-beta3.jar
- httpclient-4.2.1.jar
- httpcore-4.2.2.jar
- httpcore-nio-4.2.2.jar
- neethi-3.0.2.jar
- org.springframework.aop-3.1.1.RELEASE.jar
- org.springframework.asm-3.1.1.RELEASE.jar
- org.springframework.beans-3.1.1.RELEASE.jar
- org.springframework.context-3.1.1.RELEASE.jar
- org.springframework.core-3.1.1.RELEASE.jar
- org.springframework.expression-3.1.1.RELEASE.jar
- org.springframework.web-3.1.1.RELEASE.jar
- wsdl4j-1.6.2.jar
- jaxb-impl-2.2.6.jar
- javax.ws.rs-api-2.0-m10.jar
- slf4j-api-1.6.2.jar
- jettison-1.3.3.jar (JSON library)
- ehcache-core-2.5.1.jar
- cglib-nodep-2.1_3.jar
Ehcache With CXF Web Service
I am creating a sample restful service project that pass Student object and return with some changes on that object. The service is using simple POJO (Plain Old Java Object) bean.
Firstly create a Dynamic Web Project (File->New->Dynamic Web Project) named "CXFRestfulTutorial" according to following screenshot
Create a Student Object
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "Student")
public class Student {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Create a Service Interface
This service interface will defines which methods of restful service, to be invoked by the client
Here we implement the service interface created on the previous step
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.springframework.cache.annotation.Cacheable;
@Consumes("application/json")
@Produces("application/json")
public class ChangeStudentDetailsImpl{
@Cacheable(value="student", key="#student.name")
@POST
@Path("/changeName")
public Student changeName(Student student) {
System.out.println("Inside changeName method");
student.setName("HELLO " + student.getName());
return student;
}
}
Create a cxf.xml
You need to add
for working on annotations and also need to specify which cacheManager we are using
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:cxf="http://cxf.apache.org/core" xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd 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://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"> <import resource="classpath:META-INF/cxf/cxf.xml" /> <cache:annotation-driven /> <cxf:bus> <cxf:features> <cxf:logging /> </cxf:features> </cxf:bus> <jaxrs:server address="/rest" id="base"> <jaxrs:serviceBeans> <ref bean="StudentService" /> </jaxrs:serviceBeans> </jaxrs:server> <bean class="com.student.ChangeStudentDetailsImpl" id="StudentService" /> <!-- Ehcache library setup --> <bean class="org.springframework.cache.ehcache.EhCacheCacheManager" id="cacheManager" p:cache-manager-ref="ehcache" /> <bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" id="ehcache" p:config-location="WEB-INF/ehcache.xml" /> </beans>
Create a ehcache.xml
We are spacifying cache configurations on ehcache.xml
<ehcache> <diskStore path="java.io.tmpdir" /> <cache name="student" maxElementsInMemory="100" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" maxElementsOnDisk="10000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" /> </ehcache>
Change web.xml
Change the web.xml file to find CXF servlet and cxf.xml
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 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"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>WEB-INF/cxf.xml</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>
Publishing CXF Restful Service
Deployed CXF Restful Service
Now just call "CXF Restful Client" in order to run this restful service
Need to change the code like following on client
URL url = new URL("http://localhost:8080/CXFRestfulTutorial/rest/changeName");
Here I am calling the client twice and showing the result below, From the result you can see that "Inside changeName method" is showing only once, this is because when first request is coming from client response is cached after that Student object is returned from the cache
Output
Aug 29, 2012 3:56:47 AM org.apache.cxf.interceptor.LoggingInInterceptor INFO: Inbound Message ---------------------------- ID: 2 Address: http://localhost:8080/CXFRestfulTutorial/rest/changeName Encoding: ISO-8859-1 Http-Method: POST Content-Type: application/json Headers: {Accept=[text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2], connection=[keep-alive], Content-Length=[26], content-type=[application/json], host=[localhost:8080], user-agent=[Java/1.7.0_03]} Payload: {"Student":{"name":"Tom"}} -------------------------------------- Inside changeName method Aug 29, 2012 3:56:50 AM org.apache.cxf.interceptor.LoggingOutInterceptor INFO: Outbound Message --------------------------- ID: 2 Response-Code: 200 Content-Type: application/json Headers: {Date=[Tue, 28 Aug 2012 22:26:50 GMT]} Payload: {"Student":{"name":"HELLO Tom"}} --------------------------------------
Aug 29, 2012 4:05:19 AM org.apache.cxf.interceptor.LoggingInInterceptor INFO: Inbound Message ---------------------------- ID: 3 Address: http://localhost:8080/CXFRestfulTutorial/rest/changeName Encoding: ISO-8859-1 Http-Method: POST Content-Type: application/json Headers: {Accept=[text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2], connection=[keep-alive], Content-Length=[26], content-type=[application/json], host=[localhost:8080], user-agent=[Java/1.7.0_03]} Payload: {"Student":{"name":"Tom"}} -------------------------------------- Aug 29, 2012 4:05:24 AM org.apache.cxf.interceptor.LoggingOutInterceptor INFO: Outbound Message --------------------------- ID: 3 Response-Code: 200 Content-Type: application/json Headers: {Date=[Tue, 28 Aug 2012 22:35:22 GMT]} Payload: {"Student":{"name":"HELLO Tom"}} --------------------------------------