Spring
The
Spring Framework is an open source application framework and Inversion of Control container for the Java platform.
JPA
Java Persistence API (JPA) provides POJO (Plain Old Java Object) standard and object relational mapping (OR mapping) for data persistence among
applications. Persistence, which deals with storing and retrieving of
application data
REST
As described in a dissertation by Roy Fielding, REST is an "architectural style" that basically
exploits the existing technology and protocols of the Web, including HTTP
(Hypertext Transfer Protocol) and XML. REST is simpler to use than the well-known SOAP (Simple
Object Access Protocol) approach, which requires writing or using a provided server program (to
serve data) and a client program (to request data). SOAP, however, offers potentially more
capability. For example, a syndicator that wanted to include up-to-date stock prices to subscribing
Web sites might need to use SOAP, which allows a greater amount of program interaction between
client and server.
Incorporating these technologies together is a little bit of challenge.
JPA is a specification it has many implementation.Hibernate is one of the most widely used implementation.Here we are going to use hibernate(4.x.x) as JPA implementation.
REST too has many implementaion.
We will focus mainly on Oracle
Jersey and JBOSS
RESTEasy.
Jersey will work only on Glassfish but RESTEasy will work on any Application Server.
But we need to do some changes accordingly.
Let's see how to make these stuffs work together for a GlassFish Application Server.
Here is our applicationContext.xml:-
applicationContext.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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:flow="http://www.springframework.org/schema/webflow-config"
xmlns:jms="http://www.springframework.org/schema/jms"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd ">
<!-- specifying the property file -->
<bean id="placeholderPropertiesuserdao" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:application.properties" />
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
</bean>
<bean class="com.opensourzesupport
.rest.network.ProductResource" p:platformTransactionManager-ref="transactionManager" />
<!-- datasource information -->
<bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource" destroy-method="close" >
<property name="uRL" value="${db.jdbc.url}" />
<property name="user" value="${db.jdbc.user}" />
<property name="password" value="${db.jdbc.password}" />
</bean>
<context:component-scan base-package="com.opensourzesupport.model" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" p:entityManagerFactory-ref="entityManagerFactory"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
<property name="persistenceUnitName" value="app_persist_unit"/>
<property name="dataSource" ref="dataSource"/>
<property name="persistenceXmlLocation" value="classpath:persistence.xml"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="${db.orm.showsql}" />
<property name="generateDdl" value="${db.orm.generateDdl}" />
<property name="database" value="${db.type}"/>
<property name="databasePlatform" value="${db.orm.dialect}" />
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>
</beans>
We will use
JAXB and JPA annotation together in our POJO class.
All the annoted classes will be specified in persistence.xml and it should be in classpath
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="app_persist_unit" transaction-type="RESOURCE_LOCAL">
<description>Oracle db Persistence Unit</description>
<class>com.opensourzesupport.rest.model.Product</class>
</persistence-unit>
</persistence>
Web.xml(if using Jersey)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>spring-jpa-rest</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<!-- <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>-->
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.opensourzesupport.rest</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
Web.xml(if using RESTEasy )
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>spring-jpa-rest</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Auto scan REST service -->
<context-param>
<param-name>resteasy.scan</param-name>
<param-value>true</param-value>
</context-param>
<!-- this need same with resteasy servlet url-pattern -->
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/rest</param-value>
</context-param>
<listener>
<listener-class>
org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
</listener-class>
</listener>
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class>
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
Product.java is our annoted POJO class.
Product.java
package com.opensourzesupport.rest.model;
import com.opensourzesupport.rest.util.Constants;
import javax.persistence.*;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* @author Prasobh.K
*/
@XmlRootElement
@Entity
@NamedQueries({
@NamedQuery(name = Constants.GET_PRODUCT,
query = "select T from Product T")})
@XmlAccessorType(XmlAccessType.FIELD)
public class Product {
@Column
@Id
String name;
@Column
String description;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
ProductList.java
package com.opensourzesupport.rest.model;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* @author Prasobh.K
*/
@XmlRootElement(name="root")
public class ProductList {
public List product ;
public List getProducts() {
return product;
}
public void setProducts(List products) {
this.product = products;
}
}
ProductResource.java is our service class, where we will do all rest based annotations.
ProductResource.java
package com.opensourzesupport.rest.network;
import com.opensourzesupport.rest.model.Product;
import com.opensourzesupport.rest.model.ProductList;
import com.opensourzesupport.rest.util.Constants;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
/**
*
* @author Prasobh.K
*/
@Path("/service")
public class ProductResource {
@PersistenceContext
private EntityManager em = null;
private PlatformTransactionManager platformTransactionManager = null;
private List list = new ArrayList();
public void setPlatformTransactionManager(PlatformTransactionManager platformTransactionManager) {
this.platformTransactionManager = platformTransactionManager;
}
@GET
@Produces({MediaType.APPLICATION_XML})
@Path("/product/xml")
public ProductList getXML() {
ProductList productList = new ProductList();
productList.setProducts(getRoot());
return productList;
}
@GET
@Produces({MediaType.TEXT_PLAIN})
@Path("/product/save")
public String saveProduct() {
TransactionStatus transactionStatus = platformTransactionManager.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED));
Product product = new Product();
product.setName("TestProduct");
product.setDescription("testing Persistance");
String status = "Failed";
try {
em.persist(product);
platformTransactionManager.commit(transactionStatus);
status = "Success";
} catch (Exception e) {
System.out.println("Error" + e);
platformTransactionManager.rollback(transactionStatus);
}
return status;
}
@GET
@Produces({MediaType.APPLICATION_JSON})
@Path("/product/get")
public Product getProduct() {
try {
Query query = em.createNamedQuery(Constants.GET_PRODUCT);
Product p = (Product) query.getSingleResult();
return p;
} catch (Exception e) {
System.out.println("Error" + e);
}
return null;
}
@GET
@Produces({MediaType.APPLICATION_JSON})
@Path("/product/json")
public List getJSON() {
return getRoot();
}
@GET
@Produces({MediaType.TEXT_HTML})
@Path("/html")
public List getHTML() {
return getRoot();
}
public List getRoot() {
List root = new ArrayList();
Product product1 = new Product();
product1.setName("IOS");
product1.setDescription("Mobile");
root.add(product1);
Product product2 = new Product();
product2.setName("Android");
product2.setDescription("Mobile");
root.add(product2);
Product product3 = new Product();
product3.setName("BlacBerry");
product3.setDescription("Mobile");
root.add(product3);
Product product4 = new Product();
product4.setName("J2ME");
product4.setDescription("Mobile");
root.add(product4);
return root;
}
}
Output :
http://localhost:8080/webservice/rest/service/products/xml
<root>
<product>
<name>IOS</name>
<description>Mobile</description>
</product>
<product>
<name>Android</name>
<description>Mobile</description>
</product>
<product>
<name>BlacBerry</name>
<description>Mobile</description>
</product>
<product>
<name>J2ME</name>
<description>Mobile</description>
</product>
<products>
<name>IOS</name>
<description>Mobile</description>
</products>
<products>
<name>Android</name>
<description>Mobile</description>
</products>
<products>
<name>BlacBerry</name>
<description>Mobile</description>
</products>
<products>
<name>J2ME</name>
<description>Mobile</description>
</products>
</root>
http://localhost:8080/webservice/rest/service/products/json
{"product":
[{"name":"IOS","description":"Mobile"},
{"name":"Android","description":"Mobile"},
{"name":"BlacBerry","description":"Mobile"},
{"name":"J2ME","description":"Mobile"}]
}
http://localhost:8080/webservice/rest/service/product/save
Success
http://localhost:8080/webservice/rest/service/product/get
{"name":"TestProduct","description":"testing Persistance"}
if(RESTEasy )
include :
scannotation-1.0.3.jar
resteasy-jaxb-provider-2.3.4.Final.jar
resteasy-jaxrs-2.3.4.Final.jar
if(Jersey)
include :
jersey-core-1.14.jar
jersey-server-1.14.jar
jersey-spring-1.9.jar
Jar Files Used for Jersey
To Make RESTEasy to work with JBOSS(jboss-5.1.0.GA), please use the following configuration :
applicationContext.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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:flow="http://www.springframework.org/schema/webflow-config"
xmlns:jms="http://www.springframework.org/schema/jms"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd ">
<context:component-scan base-package="com.opensourzesupport.rest" />
<!-- <tx:annotation-driven />-->
<context:annotation-config/>
<!-- specifying the property file -->
<bean id="placeholderPropertiesuserdao" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:application.properties" />
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
</bean>
<bean class="com.opensourzesupport.rest.network.ProductResource" p:platformTransactionManager-ref="transactionManager" />
<!-- datasource information -->
<bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource" destroy-method="close" >
<property name="uRL" value="${db.jdbc.url}" />
<property name="user" value="${db.jdbc.user}" />
<property name="password" value="${db.jdbc.password}" />
</bean>
<!-- <bean class="com.opensourzesupport.rest.core.SpringApplicationContext"></bean>-->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" p:entityManagerFactory-ref="entityManagerFactory"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
<property name="persistenceUnitName" value="persistanceUnit"/>
<property name="dataSource" ref="dataSource"/>
<property name="persistenceXmlLocation" value="classpath:persistence.xml"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="${db.orm.showsql}" />
<property name="generateDdl" value="${db.orm.generateDdl}" />
<property name="database" value="${db.type}"/>
<property name="databasePlatform" value="${db.orm.dialect}" />
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>
</beans>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>spring-jpa-rest</display-name>
<listener>
<listener-class>
org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
</listener-class>
</listener>
<listener>
<listener-class>
org.jboss.resteasy.plugins.spring.SpringContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class>
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>rest</param-value>
</context-param>
<context-param>
<param-name>resteasy.scan</param-name>
<param-value>false</param-value>
</context-param>
</web-app>
ProductResource.java
package com.opensourzesupport.rest.network;
import com.opensourzesupport.rest.core.SpringApplicationContext;
import com.opensourzesupport.rest.model.Product;
import com.opensourzesupport.rest.model.ProductList;
import com.opensourzesupport.rest.util.Constants;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
/**
*
* @author Prasobh.K
*/
@Component
@Path("/service")
public class ProductResource {
@PersistenceContext
private EntityManager em = null;
private PlatformTransactionManager platformTransactionManager = null;
private List<ProductList> list = new ArrayList<ProductList>();
public PlatformTransactionManager getPlatformTransactionManager() {
if(platformTransactionManager == null){
platformTransactionManager = (PlatformTransactionManager) SpringApplicationContext.getBean("transactionManager");
}
return platformTransactionManager;
}
public void setPlatformTransactionManager(PlatformTransactionManager platformTransactionManager) {
System.out.println("setting ptm");
this.platformTransactionManager = platformTransactionManager;
}
@GET
@Produces({MediaType.APPLICATION_XML})
@Path("/products/xml")
public List<Product> getXML() {
return getRoot();
}
@GET
@Produces({MediaType.TEXT_PLAIN})
@Path("/product/save")
public String saveProduct() {
System.out.println("platformTransactionManager "+platformTransactionManager);
TransactionStatus transactionStatus =platformTransactionManager.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED));
Product product = new Product();
product.setName("TestProduct");
product.setDescription("testing Persistance");
String status = "Failed";
try {
em.persist(product);
platformTransactionManager.commit(transactionStatus);
status = "Success";
} catch (Exception e) {
System.out.println("Error" + e);
platformTransactionManager.rollback(transactionStatus);
}
return status;
}
@GET
@Produces({MediaType.APPLICATION_JSON})
@Path("/product/get")
public Product getProduct() {
try {
Query query = em.createNamedQuery(Constants.GET_PRODUCT);
Product p = (Product) query.getSingleResult();
return p;
} catch (Exception e) {
System.out.println("Error" + e);
}
return null;
}
@GET
@Produces({MediaType.APPLICATION_JSON})
@Path("/products/json")
public List<Product> getJSON() {
return getRoot();
}
@GET
@Produces({MediaType.TEXT_HTML})
@Path("/html")
public List<Product> getHTML() {
return getRoot();
}
public List<Product> getRoot() {
List<Product> root = new ArrayList<Product>();
Product product1 = new Product();
product1.setName("IOS");
product1.setDescription("Mobile");
root.add(product1);
Product product2 = new Product();
product2.setName("Android");
product2.setDescription("Mobile");
root.add(product2);
Product product3 = new Product();
product3.setName("BlacBerry");
product3.setDescription("Mobile");
root.add(product3);
Product product4 = new Product();
product4.setName("J2ME");
product4.setDescription("Mobile");
root.add(product4);
return root;
}
}
Libraries Used :