Pattern based development Defining SOA Frameworks

Pattern based development Defining SOA Frameworks

Recapitulation of adapter based solution: In the previous part we managed to deliver a working solution, based on extensive adapter usage at quite high cost. Reliability is questionable and Reusability is not at its best, even with adapter-based entity service WSDL exposed for external calls.

There are at least two questions without clear answers:

  • Why would we need BPEL, with all its service state handling capability(aka dehydration) and related infrastructure (DB, service engines), for creating Entity Service? (Entity in this context also means transportable, atomic and independent.)
  • If answer to the first question is “because it is simple” (for developers), then the second question is are we ready to pay for this imaginal simplicity by reduced reliability and the constant chance to get NullPointerException from any possible adapter (with no remedy to cure the problem), as below

Note: You may not get this error in standard Employee File-to-DB OFM examples due to simplicity of the transferred objects. A real life EBO could be far more complex, as you can see from the model in the previous post. It doesn’t mean that a minimalistic approach can prevent this error from happening. The Service Abstraction design principle has nothing to do with blunt minimisation

Alternative II (Contract-First)

We cannot get rid of all adapters, but we can reduce their footprint. First, we must standardise the contract of the Employee service and ensure that operations, declared in the contract, will be performed only through exposed contract. The Standardised contract will be used for generating a service skeleton with fully annotated Java classes from WSDL (its XSD primarily). JAXB is the architecture specification especially intended for designtime (“Top-Down” implementation) and runtime access API, and marshalling of XML data. There are several good JAXB tools available – Projects Metro and Kenai, with xjc command line utility, used everywhere (IBM WS, for instance). If contract is not based on XML data representation, it’s not a problem – Google offers GSON library for JSON data. Here we would like to check how Oracle tools can fulfil the designtime part of the so called “SDP framework”. We start from creating new SOAP Web Service Project as demonstrated below



WSDL Implementation

The Operations and Data model for the new WSDL were covered in the first part of this article, discussing usecase implementation. We have a well-develop XSD with all necessary QDT and QDO, and for the data part of service contract, the operation we need to provide is select (by ID), as insert is done outside of the service scope (interface tables of CDC). Moreover, as an example we have a WSDL, generated by adapter framework from the first approach. It doesn’t mean that we should copy it, but it can be a good reference point.



The source of the new WSDL with annotations presented below. Posted deliberately, do double-checking.

<?xml version="1.0" encoding="UTF-8" ?>
<definitions targetNamespace="urn:MDMEmployee"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="urn:MDMEmployee"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap"
xmlns:con="http://cdm.company.com/v01/contract"
xmlns:req="http://cdm.company.com/v01/request"
xmlns:emp="http://cdm.company.com/v01/employee" xmlns:java="http://schemas.xmlsoap.org/wsdl/java/"
xmlns:format="http://schemas.xmlsoap.org/wsdl/formatbinding/"
xmlns:ejb="http://schemas.xmlsoap.org/wsdl/ejb/">

<!--Types: Employee EBO type and associated Contract EBO -->
<types>
<xsd:schema targetNamespace="urn:MDMEmployee/types" elementFormDefault="qualified"/>
<xsd:schema>
<xsd:import schemaLocation="../Schemas/EmployeeEBO.xsd" namespace="http://cdm.company.com/v01/employee"/>
</xsd:schema>
<xsd:schema>
<xsd:import schemaLocation="../Schemas/Contract.xsd" namespace="http://cdm.company.com/v01/contract"/>
</xsd:schema>
</types>

<!-- Messages: Request with ID and Response with EBO -->
<message name="getEmployeeRequest">
<part name="ResourceID" type="xsd:long"/>
</message>
<message name="EBOEmployeeData">
<part name="return" element="emp:Employee"/>
</message>

<!-- Types and operations, in and out -->
<portType name="MDMEmployeeHandlerPortType">
<operation name="getEmployeeByID">
<input message="tns:getEmployeeRequest"/>
<output message="tns:EBOEmployeeData"/>
</operation>
</portType>

<!-- Binding operations, messages, ports-->
<binding name="MDMEmployeeHandlerPortTypeSOAP11Binding" type="tns:MDMEmployeeHandlerPortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="getEmployeeByID">
<soap:operation style="document" soapAction="urn:MDMEmployee/getEmployeeByID"/>
<input>
<soap:body use="literal" parts="ResourceID"/>
</input>
<output>
<soap:body use="literal" parts="return"/>
</output>
</operation>
</binding>

<!-- Final binding -->
<service name="MDMEmployeeService">
<port name="MDMEmployeeHandlerPortTypePort" binding="tns:MDMEmployeeHandlerPortTypeSOAP11Binding">
<soap:address location="http://www.company.com/MDMEmployeeService"/>
</port>
</service>

<binding name="MDMEmployeeHandlerPortTypeSOAP12Binding" type="tns:MDMEmployeeHandlerPortType">
<soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="getEmployeeByID">
<soap12:operation style="document" soapAction="urn:MDMEmployee/getEmployeeByID"/>
<input>
<soap12:body use="literal" parts="ResourceID"/>
</input>
<output>
<soap12:body use="literal" parts="return"/>
</output>
</operation>
</binding>

</definitions>

Generating Java using JDeveloper

Now we are ready to generate a Web Service from the freshly constructed WSDL. Follow the JDeveloper screenshots below, Start from New…



… Then select WSDL location and the service type (how Java code will be implemented, more traditional and modular is EJB, I tried both)

And after clicking on “Next” I got a Validation error as shown below. That’s the reason why the entire WSDL has been is published above. I will appreciate any tips on what’s wrong with it.



Frankly, I fail to find any anomalies in declarations of port type or bindings (do not trust me, try the published WSDL yourself). Generation fails on separate Oracle environments (my and teammates). What we need is transportable java code (POJO or EJB) according to our contract definition. Why not try other candidates on designtime SDP? In addition to the JAXB tools already mentioned above, we have Red Hat JBoss Developer Studio (currently installed 8.1.0) with Eclipse as a workbench and JBoss FUSE as a runtime backbone.

Generating Java using JBoss FUSE Developer Studio

Please bear in mind that JAXB is a specification, and implementation can have some specific requirements, depending on vendor.



Thus, before using JBoss DevStudio for “Contract-first” development we must install and run FUSE server, which is the commercial version of quite cleverly combined Apache products, forming lightweight ESB. In fact it’s much easier and lighter than Oracle WLS/OSB combination.

The sequence is straight forward. In Eclipse, create a Java project and import all contract-related artefacts (XSD and our WSDL). As you see from screenshot above, it’s the same EmployeeWS project I created in JDeveloper. All objects have passed validation. Right-click on WSDL, and from Web Services select create Java Bean Skeleton. The configuration wizard steps are a bit different from what we have seen in JDeveloper, but very logical:

  • Top-down approach confirmed
  • WSDL definition selected for the service
  • Server runtime selected as JBoss Enterprise Application Platform (by default WLS is not in the list)
  • Web service runtime : JBossWS (No WLS either)
  • Two types of WS projects created (one for Java beans resources, one for JAX-WS handlers)

NB: it doesn’t really matter, whether we have WLS as a runtime platform, or not. What we expect is the Java code, which should be transportable.

Java skeleton construction took just a few moments and the result was very positive. Please see screenshot below. All associated java classes are in the correct place, and all qualified data objects have been accumulated in one package (qdo). There you will find all Currency and Location enumerators, language codes and so on.

Actually, in addition to the Java classes, we have (as expected) the WS implementation, which is very compact and elegant (pls see the code below), based on our WSDL and CXF implementation.

package mdmemployee;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.xml.bind.annotation.XmlSeeAlso;

/**
* This class was generated by Apache CXF 2.6.8.redhat-7
* Generated source version: 2.6.8.redhat-7
*
*/
@WebService(targetNamespace = "urn:MDMEmployee", name = "MDMEmployeeHandlerPortType")
@XmlSeeAlso({com.company.cdm.v01.company.ObjectFactory.class, com.company.cdm.v01.bankaccountrecord.ObjectFactory.class, com.company.cdm.v01.person.ObjectFactory.class, com.company.cdm.v01.payroll.ObjectFactory.class, com.company.cdm.v01.contract.ObjectFactory.class, com.company.cdm.v01.qdo.ObjectFactory.class, com.company.cdm.v01.employee.ObjectFactory.class})
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface MDMEmployeeHandlerPortType {

@WebResult(name = "Employee", targetNamespace = "http://cdm.company.com/v01/employee", partName = "return")
@WebMethod
public com.company.cdm.v01.employee.Employee getEmployeeByID(
@WebParam(partName = "ResourceID", name = "ResourceID", targetNamespace = "")
long resourceID
);
}

Check the server status (third tub at the bottom) – depending on your configuration after compilation you will see WebService installed and synchronized. But this is not a service we are ready to run – we have the JAXB part, but we still have to plug it to our database.

Back to Oracle

Another thing – my intention was to establish SDP as a framework, providing transportable code. Usually, it means that we should be able to run created code on different platforms. Here I would like to check the possibility to import generated Java Beans back to JDeveloper(maybe it sounds strange, this is the Oracle Blog after all). If I will be able to do it effortlessly, that would be another plus for JBoss FUSE. To do so in JDeveloper let’s go back to EmployeeWS project, where we started with WSDL and from File menu select import “Java Source”



In the next screen select source from JBoss WebServiceProject project. The import operation is almost instant. Packages have been compiled right after import. No problems whatsoever, see screenshot below:

  • All beans packages are in place according to the object model
  • WebService code is valid in JDeveloper
  • Each package has ObjectFactory class for supporting JAXB through the *RecordType.java implementation
  • Package-info.java comment file is added to support JavaDoc functionality


Further steps

All looks fine, but the service implementation is halfway done. Yes, with some effort we have implemented Java Beans using JAXB, but DB connection should be completed. Persistence shall be implemented, for instance using JPA/JDBC. Ideally, any SDP should provide an automated way to add DB persistence to our classes. Common steps could be described in the following steps

  • Step 1. Create table in database (already done using XSD).
  • Step 2. Update stateless EJB. Add methods to add records and get records from database via entity manager.

Implementation of these steps will be discussed in the next article.

Conclusion

We have completed construction of the Java skeleton for our Entity WebService. Again, as in the previous article I hit some problems using Oracle as a basis for SDP. It seems that not only the Adapter framework has weaknesses, but even basic Contract-First generation functionality can give you some funny moments. Luckily, some really good tools from Oracle competitors can help us in difficult moments. Frankly, I will be happy to receive comments from you regarding the flaws in the WSDL published above. Even so, it can hardly explain why JBoss Fuse Dev Studio (Eclipse based) could handle it so gracefully. (Actually, it is the same approach I used in the book [3], tackling the problem from different directions.) In fact, I also cannot explain why I am still trying to build a reliable SDP on the Oracle platform, not on JBoss Fuse, receiving the message shown below twenty times a day.




References

  1. SOA Principles of Service Design, by Thomas Erl, Prentice Hall; 1st edition (July 28, 2007)
  2. SOA. Concepts, Technology and Design, Thomas Erl, 2005, Prentice Hall
  3. Applied SOA Patterns on the Oracle Platform, Packt Publishing ( August 12, 2014) http://www.amazon.com/Applied-SOA-Patterns-Oracle-Platform/dp/1782170561
  4. Oracle SOA Suite 12c Sandbox http://www.acando.no/thedailypassion/200138/oracle-soa-suite-12c-sandbox) [3]
  5. Web Services Choreography Description Language Version 1.0 http://www.w3.org/TR/ws-cdl-10/#Purpose-of-WS-CDL
  6. JAXB Project Kenai https://jaxb.java.net/ 
  7. Google GSON API https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/Gson.html

 

Om bloggeren:
Sergey has a Master of Science degree in Engineering and is a Certified Trainer in SOA Architecture, Governance and Security. He has several publications in this field, including comprehensive practical guide “Applied SOA Patterns on the Oracle Platform”, Packt Publishing, 2014.

comments powered by Disqus