Java Interoperability Using Service Interface and DTO Architecture Patterns - Code Project
Java Interoperability Using Service Interface and DTO Architecture Patterns - Code Project
You may want to try: Benchmark start-up and system performance for .Net, Mono, Java, C++ and their respective UI Mobile Game Programming for Beginners: Part 1 of 4
7,889,327 members and growing! (34,037 online) highlights off claudiu.popirlan 130
Sign out
Home
Articles
Learning Zones
Features
Help!
The Lounge
Development Lifecycle Design and Architecture Patterns and Practices Licence First Posted Views Downloads Bookmarked C POL 8 Feb 2011 5,057 34 9 times
See Also
More like this More by this author
This article shows you how to build a simple cross-platform interoperation solution between .net and Java using the Service Interface and Data Transfer Object (DTO) architecture patterns
Article Browse Code Stats Revisions (19)
4.57 (5 votes) 9
Sponsored Links
Introduction
Interoperability between custom-developed distributed systems running on Java/Linux platform and .net/windows remains a challenge even to this day. RPC based solutions like the COM-CORBA bridge address it but introduce a major liability in terms of brittle coupling. Several propriety and open source solutions based on web services, database integration and remoting bridges also attempt to address this problem. However such solutions often comprise of deep and (in some cases expensive) software stacks introducing accidental complexity, large resource footprint, steep learning curve and performance degradation. In this article I present an architectural solution for cross-platform interoperation. The architecturally significant aspect of this solution is to surface, define and govern the structure and exchange of data across the two platforms. The architecture is based on ServiceInterface and Data Transfer Object (DTO) patterns. The reference implementation demonstrates using this architecture to integrate two business systems, Fulfillment Center running on Java/Linux tier and CustomerOrderProcessing running on .net/Windows.
See Also...
Background
Service Interface The service interface implements the contract between the consumer and provider. This contract allows them to exchange information even if they are on different systems. The service interface is responsible for all of the implementation details needed to perform this communication.
Data transfer object is a distribution pattern where you create a serializable object to transfer state between two systems. DTO has no behavior and its serialization/deserialization is handled by an assembler object
XSD XML Schema or XSD provide constructs to express data types in a platform/language agnostic format. For example a data type to define Customer Address information in XSD will look like
C ollapse
<xs:complexType name="Address"> <xs:sequence> <xs:element name="name" type="xs:string" /> <xs:element name="zip" type="xs:integer" /> <xs:element name="city" type="xs:string" /> <xs:element name="country" type="xs:string" /> </xs:sequence> </xs:complexType>
XXsd2Code XXsd2Code is an open source code generator to generate serializable Java, C#, C++ and C++/CLI classes from XSD.
Problem
Fulfillment Center application is part of a warehouse management system that is written in java and runs on RHEL. CustomerOrderProcessing is a part of a POS system written in .net and running on MS Windows 2008 server. Use Case Any new order processed by the CustomerOrderProcessing system need to be sent to the "Fulfillment Center". Once the fulfillment system ships the order it in turn notifies CustomerOrderProcessing.
Solution Outline
Based on the DTO pattern create a schema that represents the structure of the data interchange between the two systems. This is the interface contract. Model this contract as an XSD. Use XXsd2Code to code generate platform specific contracts in C# and Java. Create a service interface for the Fulfillment Center application using TCP/IP as transport. Create a service gateway for the CustomerOrderProcessing that connects to this service interface. Structure (Class Diagram) design.pdf - 179.75 KB
Solution Implementation
Service Contract 1. Defining the Contract
Using any XSD editor create the following data contract. I created this XSD using MS VS 2005
2. Code generate C# classes Assuming the XXsd2Code.exe is in the same folder as the .xsd file, execute the following command. XXsd2Code.exe .\/.\/C# This will code generate C# bindings for the xsd contract.
C ollapse
namespace CustomerOrderAndFulfillment { { namespace Contract [Serializable] public class FulfillmentRecord : ICloneable { public string FulfillmentRecordID; public bool IsBackOrder; public FuzzyCondition StorageTemperature; ... } [Serializable] public class CustomerOrder : ICloneable { public string OrderNumber; public CreditRating Rating; public Address AddressInfo; public List<OrderItem> Orders; public CreditCardDetails CcInfo; ... } }
3. Code generate Java classes Execute the following command. XXsd2Code.exe .\/.\/Java
This will code generate java bindings for the xsd contract.
C ollapse
package CustomerOrderAndFulfillment.Contract; public class FulfillmentRecord implements Cloneable { public String FulfillmentRecordID; public boolean IsBackOrder; public FuzzyCondition StorageTemperature; ... } package CustomerOrderAndFulfillment.Contract; public class CustomerOrder implements Cloneable { public String OrderNumber; public CreditRating Rating; public Address AddressInfo; public java.util.List<OrderItem> Orders; public CreditCardDetails CcInfo; ... }
Transport 4. net TCP/IP Client Use the TcpClient and NetworkStream to write a simple Tcp/Ip client
C ollapse
TcpClient client = new TcpClient(server,port); NetworkStream stream = client.GetStream(); //Send Message Byte[] data = System.Text.Encoding.UTF8.GetBytes(message); stream.Write(data, 0, data.Length) //Receive response blocking call byte[] buffer = new byte[1024]; stream.Read(buffer, 0, buffer.Length); return buffer;
5. Java TCP/IP Server Using ServerSocket, BufferedReader and DataOutputStream write a simple TCP/IP deamon on port 1111
C ollapse
<span>ServerSocket welcomeSocket = new ServerSocket(1111); Socket connectionSocket = welcomeSocket.accept(); BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream())); DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream()); //get request message String request = inFromClient.readLine(); //Send response outToClient.writeBytes(response);</span>
Data Transfer Object 6. Write an assembler class to Serialize and DeSerialize .net service interface contract classes using XMLSerializer. Serialize method transforms the CustomerOrder object into a stream of bytes so that it sent to the FulfillmentCenter server.
C ollapse
static string SerializeCustomerOrder(CustomerOrder order) { XmlSerializer serializer = new XmlSerializer(typeof(CustomerOrder)); using (MemoryStream memoryStream = new MemoryStream()) { serializer.Serialize(memoryStream, order); return Encoding.UTF8.GetString(memoryStream.ToArray()); } }
DeSerialize converts the response from the FulfillmentCenter server into a strongly typed FulfillmentRecord object
C ollapse
static FulfillmentRecord DeSerializeFulfillmentRecord(byte[] stream) { XmlSerializer serializer = new XmlSerializer(typeof(FulfillmentRecord)); using (MemoryStream memoryStream = new MemoryStream(stream)) { return serializer.Deserialize(memoryStream) as FulfillmentRecord; } }
7. Write an assembler class to Serialize and DeSerialize java service interface contract classes using xstream DeSerialize converts the request from the CustomerOrderProcessing into a strongly typed
CustomerOrder object .
C ollapse
static CustomerOrder DeSerializeCustomerOrder(String request) { XStream serializer = new XStream(); RegisterXstreamConverters(serializer); return (CustomerOrder) serializer.fromXML(request); }
Serialize transforms the FulfillmentRecord object into a stream of bytes so that it can be sent back to the CustomerOrderProcessing system.
C ollapse
static String SerializeFulfillmentRecord(FulfillmentRecord fulfillmentRecord) { XStream serializer = new XStream(); RegisterXstreamConverters(serializer); return serializer.toXML(fulfillmentRecord); }
XMLSerializer and xstream XML compatibility. To make sure xstream generates xml that is compatible with XMLSerializer use the following code
C ollapse
XStream Emun Serialization To force xstream serialize enums correctly write an Enum Converter
C ollapse
public class EnumSingleValueConverter< T extends Enum<T> > extends EnumConverter implements SingleValueConverter { private Class<T> enumType; public static <V extends Enum<V>> SingleValueConverter create(Class<V> enumClass) { return new EnumSingleValueConverter<V>(enumClass); } private EnumSingleValueConverter(Class<T> newEnumType) { this.enumType = newEnumType; } public boolean canConvert(Class type) { return type == enumType; } public Object fromString(String str) { Object r = null; Method m = enumType.getMethod("fromValue", String.class); r = m.invoke(null, str); } public String toString(Object obj) { return obj.toString(); } }
Note : If you modify the xsd (interface contract) then make sure to run the GenerateCrossPlatformDataBindings.bat again.
Integration Test
I used Eclipse Ganymede to create a runnable jar. To test my Fulfillment Center server application I used Ubuntu 10.10 running as a VirtualBox guest on windows 7 host. Make sure to add a bridge network adaptor for the VM so that the windows .net app can reach the java server running on the Ubuntu guest. Now run Java/Linux Fulfillment Center server application
Now run the CustomerOrderProcessing .net application. Make sure you point to the IPAddress of the Linux Virtual machine.
Conclusion
The architectural solution described in the article enable you to Decouple interoperation/communication plumbing from the business applications using the Service Interface pattern. Minimize number of calls between the two systems using the Data Transfer Object pattern. Surface, define, govern and ensure compile time enforcement of the service contract by Creating platform agnostic data types using XSD. Then code generating platform specific data types using XXS2Code.
License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)
Article Top
Poor
Excellent Vote
Use C trl+Left/Right to switch messages, C trl+Up/Down to switch threads, C trl+PgUp/PgDown to switch pages.
P ermalink | A dvertis e | P rivac y | M obile | Web2 2 | 2 .3 .1 1 0 6 1 7 .1 L ayout: fixed | fluid A rtic le C opyright 2 0 1 1 by as hees h goja E verything els e C opyright C odeP rojec t, 1 9 9 9 - 2 0 1 1 T erms of U s e