Thursday, February 28, 2013

Spring-WS JAXB Java Webservice tutorial

This post shows how to create webservices using spring-ws. It took me a while to resolve numerous simple issues but I finally figured out how all this works.

I used "contract-first" approach by creating schema and wsdl first. Then, I created a Eclipse maven war type project, updated it with all required dependencies. One can take the reverse approach by exposing an EndPoint java class as a webservice and let Spring-ws publish wsdl dynamically.

I added a goal to generate Java code from schema that represents the payload of the webservice operations. 

I created a Java EndPoint class that will serve webservice requests.

Lastly, I created the spring webservices context file that defines all the webservice beans and marshaller/unmarshaller.

1. Define dispatcher servlet for Spring web services in  web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/web-application-config.xml</param-value>
</context-param>

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

<servlet>
<servlet-name>xyz-ws</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<init-param>
<param-name>transformWsdlLocations</param-name>
<param-value>true</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>xyz-ws</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>

2. Create spring-ws context xml file to define web service beans
<?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:context="http://www.springframework.org/schema/context"
  xmlns:sws="http://www.springframework.org/schema/web-services"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context.xsd
  http://www.springframework.org/schema/web-services
  http://www.springframework.org/schema/web-services/web-services-2.0.xsd">

  <sws:annotation-driven />

<context:component-scan base-package="com.xyz.abc.integration"
annotation-config="true" />

<bean id="XYZWebService"
class="org.springframework.ws.wsdl.wsdl11.SimpleWsdl11Definition">
<constructor-arg value="classpath:/XYZWebService.wsdl"/>
</bean>

<bean id="XYZSchema" class="org.springframework.xml.xsd.SimpleXsdSchema">
<property name="xsd" value="classpath:/XYZSchema.xsd" />
</bean>

if you wanted Spring to generate wsdl automatically, comment out previous two lines and use this
<sws:dynamic-wsdl id="XYZWebService" portTypeName="XYZWebServicePort" locationUri="/xyzWebService/" targetNamespace="http://www.abc.com/XYZWebService/"> <sws:xsd location="classpath:/XYZSchema.xsd" /> </sws:dynamic-wsdl>

<bean id="marshallingPayloadMethodProcessor"
class="org.springframework.ws.server.endpoint.adapter.method.MarshallingPayloadMethodProcessor">
<constructor-arg ref="marshaller" />
</bean>

<bean id="defaultMethodEndpointAdapter"
class="org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter">
<property name="methodArgumentResolvers">
<list>
<ref bean="marshallingPayloadMethodProcessor" />
</list>
</property>
<property name="methodReturnValueHandlers">
<list>
<ref bean="marshallingPayloadMethodProcessor" />
</list>
</property>
</bean>

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

<bean id="exceptionResolver"
class="org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver">
<property name="defaultFault" value="SERVER" />
<property name="exceptionMappings">
<props>
<prop key="org.springframework.oxm.ValidationFailureException">CLIENT,Invalid</prop>
<prop key="javax.xml.bind.JAXBException">CLIENT,Invalid Request - Parser failed</prop>
</props>
</property>
</bean>

<bean id="xyzEndpoint" class="com.xyz.abc.integration.XYZEndpoint" scope="request">
<property name="someBusinessService" ref="someBusinessService"/>
</bean>

3. Create application context file to define other beans
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
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/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<context:annotation-config/>

<bean id="someBusinessService" class="com.xyz.abc.integration.SomeBusinessServiceImpl" scope="request"/>

</beans>

4. Create xsd schemas for webservice input/output
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.xyz.com/schemas/abc"
elementFormDefault="qualified">

<xsd:element name="SendOrderRequest">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Field11" type="xsd:string" maxOccurs="1" minOccurs="0"/>
<xsd:element name="Filed22" type="xsd:string" maxOccurs="1" minOccurs="0" />
<xsd:element name="Field33" type="xsd:string" maxOccurs="1" minOccurs="0" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>

<xsd:element name="SendOrderResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Field1" type="xsd:string" maxOccurs="1" minOccurs="0" />
<xsd:element name="Field2" type="xsd:string" maxOccurs="1" minOccurs="0" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>

</xsd:schema>

5. Create WSDL for service

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.abc.com/XYZWebService"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:rew="http://www.abc.com/schemas/XYZ"
name="XYZWebService" targetNamespace="http://www.abc.com/XYZWebService/">

<wsdl:types>
<xsd:schema targetNamespace="http://www.abc.com/XYZWebService/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import namespace="http://www.abc.com/schemas/XYZ"
schemaLocation="XYZSchema.xsd" />
</xsd:schema>
</wsdl:types>
<wsdl:message name="sendOrderRequest">
<wsdl:part element="rew:SendOrderRequest" name="sendOrderRequest" />
</wsdl:message>
<wsdl:message name="sendOrderResponse">
<wsdl:part element="rew:SendOrderResponse" name="sendOrderResponse" />
</wsdl:message>

<wsdl:portType name="XYZWebService">
<wsdl:operation name="SendOrder">
<wsdl:input message="tns:sendOrderRequest" name="SendOrderRequest" />
<wsdl:output message="tns:sendOrderResponse" name="SendOrderResponse" />
</wsdl:operation>
</wsdl:portType>

<!-- Do we need to define soapAction -->
<wsdl:binding name="XYZWebServiceSOAP" type="tns:XYZWebService">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />

<wsdl:operation name="SendOrder">
<soap:operation soapAction="" />
<wsdl:input name="SendOrderRequest">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="SendOrderResponse">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="XYZWebService">
<wsdl:port binding="tns:XYZWebServiceSOAP" name="XYZWebServiceSOAP">
<soap:address location="http://localhost:7001/XYZService/ws" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>


6. Create Endpoint java class
@Endpoint
public class XYZEndpoint {

private static final Logger LOG = Logger.getLogger(XYZEndpoint.class);

private static final String NAMESPACE_URI = "http://www.xyz.com/schemas/xyz";


private SomeBusinessService someBusinessService;

public SomeBusinessService getSomeBusinessService() {
return this.someBusinessService;
}

public void setSomeBusinessService(SomeBusinessService someBusinessService) {
this.someBusinessService = someBusinessService;
}

@PayloadRoot(localPart = "SendOrderRequest", namespace = NAMESPACE_URI)
@ResponsePayload
public SendOrderResponse sendOrder(@RequestPayload SendOrderRequest request, SoapHeader header)
{
LOG.info("in sendOrder.....");
com.xyz.abc.integration.jaxb.ObjectFactory of = new com.xyz.abc.integration.jaxb.ObjectFactory();
SendOrderResponse resp = of.createSendOrderResponse();

resp.setField1(request.getField11());
return resp;
}

7. maven pom
<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>
<scope>test</scope>
</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>
</dependencies>
<build>
<finalName>XYZService</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.xyz.abc.integration.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>

8. WSDL and XSD location

http://localhost:7001/XYZService/XYZWebService.wsdl
http://localhost:7001/XYZService/XYZSchema.xsd

9. SOAP UI 
http://localhost:7001/XYZService

Wednesday, February 20, 2013

Oracle SOA components

Mediator:
Route: Determines the service component (BPEL process, business rule, human task, and mediator) to which to send the messages.
Validate: Provides support for validating the incoming message payload by using a schematron or an XSD file.
Filter: If specified in the rules, applies a filter expression that specifies the contents (payload) of a message be analyzed before any service is invoked.
Transformation: If specified in the rules, transforms document data from one XML schema to another, thus enabling data interchange among applications using different schemas.

Adapters:
Files
DB
JMS
JCA
BAM
FTP

Oracle Business Rules
Oracle Business Rules, initiated by a BPEL process service component, enable dynamic decisions at runtime allowing you to automate policies, constraints, computations, and reasoning while separating rule logic from underlying application code. In addition, the human task and mediator service components can make use of rules for dynamic routing. A mediator service component can use a business rule for routing messages, and a human task can use a business rule for routing assignments. The Oracle Metadata Repository (MDS) stores the rulesets for Oracle Business Rules.

Oracle BPEL Process Manager
Oracle BPEL Process Manager provides the standard for assembling a set of discrete services into an end-to-end process flow, radically reducing the cost and complexity of process integration initiatives. Oracle BPEL Process Manager enables you to orchestrate synchronous and asynchronous services into end-to-end BPEL process flows.
You integrate BPEL processes with external services (known as partner links). You also integrate technology adapters and services, such as human tasks, transformations, notifications, and business rules within the process.


Tuesday, February 19, 2013

Spring MDP Java example

1. MDP code
package com.xyz.web.test;

import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

import org.apache.log4j.Logger;

/**
 */
public class QueueListenerBean implements MessageListener {

private static final Logger LOG = Logger.getLogger(QueueListenerBean.class);

  /**
   * Retrieve the int value of the TextMessage and
   * increment the RMI counter by that much.
   */
  public void onMessage(Message msg) {
      LOG.info("In OnMessage()");
    try {
        TextMessage textMessage = (TextMessage) msg;
        System.out.println("Message received:" + textMessage.toString());
        LOG.info("Message received:" + textMessage.toString());
    }
    catch(Exception ex) {
      ex.printStackTrace();
    }
  }
}

2. Spring Application Context file
<?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:jee="http://www.springframework.org/schema/jee"
  xsi:schemaLocation="
  http://www.springframework.org/schema/jee
  http://www.springframework.org/schema/jee/spring-jee.xsd
  http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans.xsd">

<jee:jndi-lookup id="myConnectionFactory" jndi-name="jms/entryQueueCXF"
proxy-interface="javax.jms.QueueConnectionFactory" cache="false"
resource-ref="false" lookup-on-startup="true" />

<bean id="myMessageListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="myConnectionFactory" />
<property name="destinationResolver" ref="jndiDestinationResolver" />
<property name="destinationName" value="jms/ClipEntryInQueue" />
<property name="messageListener" ref="myMessageListener" />
</bean>

<bean id="jndiDestinationResolver"
class="org.springframework.jms.support.destination.JndiDestinationResolver">
<property name="cache" value="true" />
</bean>

<bean id="myMessageListener" class="com.xyz.web.test.QueueListenerBean" />

</beans>


3. Web.xml
<?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">

  <display-name>Spring MDB Example</display-name>
  <!-- -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/applicationContext.xml</param-value>
</context-param>
 <!--  
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>file:/temp/applicationContext.xml</param-value>
</context-param>
  -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

</web-app>

Thursday, February 07, 2013

Method cache using ehcache, Spring, Java

Configuration in application context
<ehcache:annotation-driven cache-manager="cacheManager"/> 

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> 
 <property name="configLocation"> <value>classpath:/ehcache-emrb-config.xml</value> </property> 
</bean> 

<bean id="managementService" class="net.sf.ehcache.management.ManagementService" init-method="init" destroy-method="dispose"> 
   <constructor-arg ref="cacheManager"/> 
   <constructor-arg ref="mbeanServer"/> 
   <constructor-arg index="2" value="true"/> 
   <constructor-arg index="3" value="true"/> 
   <constructor-arg index="4" value="true"/> 
   <constructor-arg index="5" value="true"/> 
 </bean> 
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean"> <property name="locateExistingServerIfPossible" value="true"/> </bean>

Configuration in ehcache config file
<?xml version="1.0" encoding="UTF-8"?> 
<ehcache> 
  <defaultCache maxElementsInMemory="500" eternal="true" overflowToDisk="false"
    memoryStoreEvictionPolicy="LFU" /> <cache name="siteValidationCache" eternal="true"
    maxElementsInMemory="25000" overflowToDisk="false" diskPersistent="false"       memoryStoreEvictionPolicy="LRU" /> 
</ehcache>


Code annotation to add
@Cacheable(cacheName = "xyzCache", keyGenerator = @KeyGenerator(name = "com.abc.def.ghi.common.data.impl.AbcCacheKeyGenerator"))
public SomePojo addSomeThingToCacheMethod(String some) throws DataAccessException {
}

Code annotation to remove
@TriggersRemove(cacheName="xyzCache",  keyGenerator = @KeyGenerator (
           name = "com.abc.def.ghi.common.data.impl.AbcCacheKeyGenerator"))))
public SomePojo deleteSomeThingFromCacheMethod(String some);

Programmatic way to access cache
Cache xyzCache = CacheManager.getInstance().getCache("xyzCache");
xyzCache.remove(someKey);

Friday, February 01, 2013

J2EE patterns

J2EE Patterns
  1.  MVC
  2.  Business Delegate
  3.  Composite Entity
  4.  Data Access Object
  5.  Front Controller
  6.  Intercepting Filter
  7.  Service Locator
  8.  Transfer Object


BPEL Example

Synchronous (Short running) BPEL process consists of following:
1. Receive from client
2. Invoke
3. Reply to client

Right hand partner_links represent references to external services invoked by BPEL process

Sample BPEL Process example:
RoutePOEntryPoint (WebService Client for Composite app)
--> RoutePO (Mediator ) decides which BPEL to process
     --> ApproveCreditCardOrderBPEL for CreditCard orders --> uses ValidateCCService external web service as a partner link
      --> FullfillmentBPEL for PayPal orders -->  uses USPS adapter OR UPSJMSAdapter OR FedExJMS adapter as partner links
-->

Testing using Selenium, Eclipse, JUnit

  1. Use firefox plugin for selenium to
    1. record in firefox
  2. Export test case as Java JUnit class
  3. Start Selenium standalone server
    1. C:\apps\selenium>java -jar selenium-server-standalone-2.28.0.jar
  4. Import test case into Java project
  5. Add jars in C:\apps\selenium\selenium-2.28.0\libs to JUnit test classpat
  6. Run Junit test 

GoF Design Patterns



Creational Patterns

  1.  Abstract Factory
  2.  Builder
  3.  Factory Method
  4.  Prototype
  5.  Singleton

Structural Patterns

  1.  Adapter
  2.  Bridge
  3.  Composite
  4.  Decorator
  5.  Façade
  6.  Flyweight
  7.  Proxy

Behavioral Patterns

  1.  Chain of Responsibility
  2.  Command
  3.  Interpreter
  4.  Iterator
  5.  Mediator
  6.  Memento
  7.  Observer
  8.  State
  9.  Strategy
  10.  Template Method
  11.  Visitor