Monday, July 01, 2013

JAX-RS Spring JPA Hibernate Maven web application

1. Workspace directory structure
C:\workspace\FFWD_NO_EJB>tree
Folder PATH listing
Volume serial number is 1C03-D338
C:.
├───.settings
├───src
│   └───main
│       ├───java
│       │   └───com
│       │       └───persistent
│       │           ├───entity
│       │           │   └───util
│       │           ├───rest
│       │           └───service
│       ├───resources
│       │   └───META-INF
│       └───webapp
│           └───WEB-INF
└───target

2. Entity java class
package com.persistent.entity;


import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;


@Entity
@XmlRootElement
@Table(name="AUTH_STAT")
public class Status implements Serializable {

    @Id
    @Column(name="AUTH_STAT_CD")
    private String statusCode;

    @Column(name = "AUTH_STAT_DSC")
    private String statusDescr;

    @Column(name = "AUTH_SEREVITY_ID")
    private Integer severity;

    @Column(name = "CREATE_TS")
    private Date createTimestamp;

    @Column(name = "CREATE_USER_ID")
    private String createUserId;

    @Column(name = "UPD_USER_ID")
    private String updUserId;

    @Column(name = "UPD_TS")
    private Date updTimestamp;


3. REST service Impl (create a service interface too)

ackage com.persistent.rest;


import java.util.List;
import java.util.StringTokenizer;

import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.persistent.entity.Status;
import com.persistent.service.StatusService;

// The Java class will be hosted at the URI path "/persons"

@Component
@Path("/status")
public class StatusResourceWs implements StatusResource {
    @Autowired
    StatusService statusService;
    private Logger log = Logger.getLogger(this.getClass());
    // The Java method will process HTTP GET requests

    @GET
    @Path("{code}")
    @Produces("application/xml")
    public Status getStatus(@PathParam("code") String code) {
        log.info("Hit getStatus");
        Status status = statusService.getByCode(code);
        log.info("Sending: \n\n" + status + "\n\n");
        return status;
    }


4. JPA impl class (Crete a interface too)
package com.persistent.service;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.persistent.entity.Status;
import com.persistent.service.StatusService;


@Service("statusService")
public class StatusServiceJpa implements StatusService {
    private Logger log = Logger.getLogger(this.getClass());
    private EntityManager entityManager;

    @PersistenceContext
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    /* (non-Javadoc)
     * @see com.persistent.service.jpa.StatusService#getById(int)
     */
    @Transactional(readOnly = true)
    public Status getByCode(String code) {
        return entityManager.find(Status.class, code);
    }
}



5. Persistence.xml definition in META-INF directory of war file
<persistence 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"
        version="1.0">

    <persistence-unit name="status_persistence" transaction-type="RESOURCE_LOCAL">
        <class>com.persistent.entity.Status</class>
    </persistence-unit>

</persistence>


6. Spring application context file contents - goes into WEB-INF/classes

<?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:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
            ">
    <!--  Scan for both Jersey Rest Annotations a -->
    <context:component-scan
        base-package="com.persistent.rest,com.persistent.service,com.persistence.entity" />
    <context:annotation-config />
   
    <tx:annotation-driven />
   
    <jee:jndi-lookup id="dataSource" jndi-name="jdbc/BPPSDataSource" expected-type="javax.sql.DataSource"/>
   
    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
        p:dataSource-ref="dataSource" p:jpaVendorAdapter-ref="jpaAdapter">
        <property name="persistenceUnitName" value="status_persistence" />
        <property name="jpaProperties">
            <value>
                  hibernate.query.factory_class=org.hibernate.hql.classic.ClassicQueryTranslatorFactory
                hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect
                hibernate.connection.driver_class=oracle.jdbc.driver.OracleDriver
                  hibernate.show_sql=true
                hibernate.default_schema=BFPS
            </value>
        </property>
    </bean>
   
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
        p:entityManagerFactory-ref="entityManagerFactory" />
   
    <bean id="jpaAdapter"
        class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
        p:database="ORACLE" p:showSql="true" />
</beans>



7. web.xml definition
<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>Jersey Spring Web Application</servlet-name>
        <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey Spring Web Application</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
</web-app>



8. Maven pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.persistent</groupId>
    <artifactId>FFWD_NO_EJB</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>FFWD_NO_EJB</name>
    <repositories>
        <repository>
            <id>maven2-repository.dev.java.net</id>
            <name>Java.net Maven 2 Repository</name>
            <url>http://download.java.net/maven/2/</url>
            <!-- <layout>default</layout> -->
        </repository>
        <repository>
            <id>maven-repository.dev.java.net</id>
            <name>Java.net Maven 1 Repository (legacy)</name>
            <url>http://download.java.net/maven/1</url>
            <layout>legacy</layout>
        </repository>
    </repositories>
    <build>
        <finalName>FFWD_NO_EJB</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <inherited>true</inherited>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>maven-jetty-plugin</artifactId>
                <version>6.1.10</version>
            </plugin>
        </plugins>
    </build>
    <properties>
        <spring.version>2.5.5</spring.version>
        <hibernate.version>3.3.2.GA</hibernate.version>
        <commons-dbcp.version>1.2.2</commons-dbcp.version>
        <commons-logging.version>1.0.4</commons-logging.version>
        <jersey-version>1.0.2</jersey-version>
        <log4j.version>1.2.13</log4j.version>
    </properties>
    <dependencies>
        <!-- Adding in JPA With It's Requirements -->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>${commons-logging.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring</artifactId>
            <version>${spring.version}</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>${commons-dbcp.version}</version>
            <scope>runtime</scope>
        </dependency>
        <!--Explicitly add -->
        <!-- change cglib-nodep Farrukh Najmi From net.java.dev.jersey.users Dec.
            10, 2007 -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib-nodep</artifactId>
            <version>2.1_3</version>
        </dependency>
        <dependency>
            <groupId>geronimo-spec</groupId>
            <artifactId>geronimo-spec-jta</artifactId>
            <version>1.0.1B-rc4</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
           
            <!-- <artifactId>hibernate</artifactId> <version>3.2.5.ga</version> Explicitly
                remove: See: http://blog.interface21.com/main/2007/06/11/asm-version-incompatibilities-using-spring-autowired-with-hibernate/ -->
            <exclusions>
           
                <exclusion>
                    <groupId>javax.transaction</groupId>
                    <artifactId>jta</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>asm</groupId>
                    <artifactId>asm</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>asm</groupId>
                    <artifactId>asm-attrs</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>cglib</groupId>
                    <artifactId>cglib</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- JPA Additions end. -->
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>${jersey-version}</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey.contribs</groupId>
            <artifactId>jersey-spring</artifactId>
            <version>${jersey-version}</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
    </dependencies>
</project>



9. Access REST url at http://localhost:7001/FFWD/rest/status/S

Simple JAX-RS Restful WebService example

1. Create service implementation
@Path("/pojo")
public class PojoRestfulService {

@GET
@Path("/person")
@Produces(MediaType.APPLICATION_JSON)
public Person getPerson() {
Person p = new Person("xyz");
return p;
}
}


2. Update web.xml
<servlet>
  <servlet-name>Jersey Web Application</servlet-name>
  <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>com.sun.jersey.config.property.packages</param-name>
      <!--You need to change this line to match your package name -->
      <param-value>foo.rest</param-value>
    </init-param>
    <init-param>
            <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
            <param-value>true</param-value>
        </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
  <servlet-name>Jersey Web Application</servlet-name>
  <url-pattern>/*</url-pattern>
  </servlet-mapping>


3. Create client
public static void main(String[] args) {

ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING,
Boolean.TRUE);
Client client = Client.create(clientConfig);

WebResource resource = client.resource("http://localhost:7001/MavenWebProject/pojo/person");
ClientResponse response = resource.accept(MediaType.APPLICATION_JSON)
.get(ClientResponse.class);

String output = response.getEntity(String.class);
System.out.println(output);
}

4. Client output
{"name":"xyz"}

Spring WS JAXB Web Sevice Client

1. See the WSDL and schema in my previous post here
2. Define beans in applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util-2.0.xsd">

<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
<property name="soapVersion">
<util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_11" />
</property>
</bean>

<bean id="XYZOrderServiceMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPath" value="com.abc.XYZ.integration.test.jaxb" />
</bean>

<bean id="XYZOrderServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory" />
<property name="marshaller" ref="XYZOrderServiceMarshaller"></property>
<property name="unmarshaller" ref="XYZOrderServiceMarshaller"></property>
<property name="messageSender">
<bean
class="org.springframework.ws.transport.http.CommonsHttpMessageSender">
</bean>
</property>
<property name="defaultUri"
value="http://localhost:7001/XYZService/ws/XYZWebService.wsdl" />
</bean>

<bean id="XYZOrderServiceClient" class="com.abc.XYZ.integration.test.XYZOrderServiceClient">
<constructor-arg ref="XYZOrderServiceTemplate"></constructor-arg>
</bean>
</beans>

3. JUnit test case to invoke web service client

package com.abc.XYZ.integration.test;

import static org.junit.Assert.assertNotNull;

import org.junit.BeforeClass;
import org.junit.Test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class XYZServiceClientTest {

private static ClassPathXmlApplicationContext context = null;

@BeforeClass
public static void setUpBeforeClass() throws Exception {
context = new ClassPathXmlApplicationContext("/applicationContext.xml");
}

@Test
public void testPlaceOrder() {
XYZOrderServiceClient client = (XYZOrderServiceClient) context
.getBean("XYZOrderServiceClient");
String orderRef = client.placeOrder("offerId1");

assertNotNull(orderRef);
}
}

4. Service Client

package com.abc.XYZ.integration.test;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.ws.client.core.WebServiceTemplate;

import com.abc.XYZ.integration.test.jaxb.ObjectFactory;
import com.abc.XYZ.integration.test.jaxb.SendOrderRequest;
import com.abc.XYZ.integration.test.jaxb.SendOrderResponse;

public class XYZOrderServiceClient {

private static final Log logger = LogFactory.getLog(XYZOrderServiceClient.class);
private static final ObjectFactory WS_CLIENT_FACTORY = new ObjectFactory();

private WebServiceTemplate webServiceTemplate;

public XYZOrderServiceClient(WebServiceTemplate webServiceTemplate) {
this.webServiceTemplate = webServiceTemplate;
}

public String placeOrder(String offerId) {
logger.debug("Preparing PlaceOrderRequest.....");
SendOrderRequest request = WS_CLIENT_FACTORY.createSendOrderRequest();
request.setHHId(offerId);

logger.debug("Invoking Web service Operation[PlaceOrder]....");
SendOrderResponse response = (SendOrderResponse) webServiceTemplate
.marshalSendAndReceive(request);
logger.debug("Order reference:" + response.getField1());
return response.getField1();
}
}

5. maven POM.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.abc.XYZ.integration</groupId>
<artifactId>XYZtest</artifactId>
<version>0.0.1-SNAPSHOT</version>

<dependencies>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.0.3</version>
</dependency>
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<scope>compile</scope>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-core</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.2.1</version>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
</dependencies>

<build>
<finalName>XYZServiceTest</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>com.sun.tools.xjc.maven2</groupId>
<artifactId>maven-jaxb-plugin</artifactId>
<version>1.1.1</version>
<configuration>
<generatePackage>com.abc.XYZ.integration.test.jaxb</generatePackage>
<schemaDirectory>src\main\resources</schemaDirectory>
<generateDirectory>src\main\java</generateDirectory>
<removeOldOutput>true</removeOldOutput>
<includeSchemas>
<includeSchema>*.xsd</includeSchema>
</includeSchemas>
<includeBindings>
<includeBinding>*.xjb</includeBinding>
</includeBindings>
<strict>false</strict>
<verbose>true</verbose>
</configuration>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>



Simple JAX-WS webservice in WebLogic using Java

1. Build jax-ws webservice using annotations
package foo;

import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.soap.SOAPBinding;

@WebService(name = "ConversionService", serviceName="ConversionService", targetNamespace = "http://tempuri.org/")
@SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL)
public class ConversionServiceImpl implements ConversionService {


/* (non-Javadoc)
* @see foo.ConversionService#convert(double)
*/
@WebMethod(operationName = "convert")
public double convert(double i)
{
double answer = 1.0;
return answer;
}
}

2. sun-jaxws.xml
<?xml version="1.0" encoding="UTF-8"?>
<endpoints
  xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"
  version="2.0">
  <endpoint
    name="ConversionService"
    implementation="foo.ConversionServiceImpl"
    url-pattern="/ConversionService"/>
</endpoints>

3. web.xml
<listener>
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>

<servlet>
<servlet-name>jaxws</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>jaxws</servlet-name>
<url-pattern>/ConversionService</url-pattern>
</servlet-mapping>

4. WebLogic's web service test client
http://localhost:7001/wls_utc/

5. Access webserice wsdl
http://localhost:7001/WARContextRoot/ConversionService?wsdl