Java EE and .NET Interoperability: Integration Strategies, Patterns, and Best Practices

This section introduces an alternative to a bridging strategy, which is referred to as an adapter strategy and is designed with .NET Adapter and Java Adapter. The .NET Adapter strategy enables interoperability via custom .NET adapter libraries to access a JMS provider, and similarly Java Adapter libraries to access MSMQ.

Scope

It is often the case that in-house .NET expertise is used for building front-end applications, while the enterprise business logic and back-end integration rely on Java EE and JMS processing. Realizing the value of JMS as a standards-based solution, it may be advantageous to use a JMS provider to integrate a .NET client and a Java EE system. This would allow companies to preserve their .NET investment and leverage existing messaging infrastructure.

Aside from internal .NET and Java EE application integration, a common business scenario may require the following. A company's trading partners have to integrate business services using messaging. While a company's system may be based on .NET, their partners may favor Java EE. The .NET Adapter strategy offers an effective interoperability to Java and .NET.

A similar situation may require integration with MSMQ, in which case a Java Adapter strategy can be implemented to allow interoperability between Java and .NET MSMQ APIs.

Solution

The idea behind this strategy is to utilize .NET Runtime Libraries offered by commercial vendors or custom developed. A JMS-like messaging request can be initiated from within the .NET application. The .NET Runtime Libraries from vendors such as Sonic or Fiorano offer C#, C++, and C implementation of the JMS APIs. Please refer to [FioranoMQC#RTL], [SonicMQComClientGuide] and [SonicMQBridgesClients]. This solution allows .NET developers to leverage their skills in developing a seamless integration with the JMS message queue server.

Figure 9-4 shows how this strategy might fit in an architecture to realize a traditional Purchase Order scenario. In this case an ASP.NET Portal receives customer orders and submits them for processing to the Java EE-based Inventory system. The main means to exchange information between .NET and Java EE applications is via JMS Provider. The interoperability between .NET and JMS is resolved via the .NET Adapter Strategy that is realized via C# Runtime Libraries (RTLs).

Figure 9-4. .NET Adapter to the JMS provider

Using the .NET Adapter strategy the .NET client application can be seamlessly integrated with Java EE systems. To allow compliance with the JMS standard, all public C# APIs of the Sonic or Fiorano C# Runtime Libraries have similar signatures to the corresponding Java APIs defined by JMS. C# classes have a naming convention similar to JMS. Exception handling follows the same convention specified by JMS, with all APIs throwing a CJMSException with a specific error code and in some cases error description.

Alternatively, if a JMS provider does not supply its own .NET clients, .NET proxies can be created for JMS classes to access JMS provider using JNBBridgePro by JNBridge LLC or J-Integra for .NET by Intrinsyc Software products, see [JNBridgePro] and [JIntegraForDotNet].

Aside from commercial .NET Adapters, there is an open source project that has a free implementation of the ActiveX JMS client API, http://sourceforge.net/projects/active-jms, [ActiveXJmsClient]. This is useful when a Windows-based client application needs to send and receive messages to and from a JMS queue.

To achieve similar interoperability with MSMQ, it's necessary to create a Java Adapter. This can be accomplished by generating .NET proxies for related MSMQ assemblies, using third-party libraries, such as Intrinsyc J-Integra.

Benefits and Limitations

The .NET Adapter strategy is one to consider if one wants to leverage existing JMS infrastructure to integrate a .NET application with the Java EE application. The reason for that may be a standards-based messaging solution or it may already have been deployed by an in-house JMS provider. This way, you don't have to depend on MSMQ for achieving interoperability.

Security

For the .NET Adapter, C# Runtime Libraries from Fiorano supports secure TCP and HTTP connections on the Win32 platform for both point-to-point and publish-subscribe models.

Manageability

Managing this environment may be a bit trickythe .NET Adapter is either based on proprietary third-party runtime libraries or custom generated proxies. Any changes in the Runtime Library require an update to the code. Testing the integration flow is also involved.

Related Patterns

The main pattern that stands out here is the Adapter pattern defined in the GoF, [GoF], Design Patterns catalog. The .NET Adapter pattern is applied to adopt JMS interfaces in the .NET domain. Likewise, the Java Adapter is to adopt MSMQ APIs in the Java domain.

The .NET JMS Adapter

The purpose of this pattern is to use an adapter to implement JMS interfaces using .NET languages such as C#. This would enable the .NET application to send JMS messages to the JMS message queue. This .NET JMS Adapter resolves the incompatibility between Java and .NET in the scope of messaging. Figure 9-5 shows a simple class diagram of this pattern.

Figure 9-5. .NET JMS Adapter class diagram

The DotNetJmsAdapter represents a library of C# classes implementing JMS-like APIs. The .NET application uses the adapter to send and receive corresponding messages. This pattern should be very straightforward to use, given that the Adapter library can be available from your JMS message queue provider. Next is an example of how this strategy can be applied in development.

Example

In moving toward this example, there are no changes to be made on the Java Retailer system from the previous implementation. The .NET Manufacturer, however, uses the Fiorano C# Runtime Libraries to access the JMS message queue. To receive the message, this example explores the POValidator class that accesses the JMS provider to retrieve the incoming message. To initialize and access the message queue, one declares class variables including CsInitialContext, CsQueueConnectionFactory, CsQueue, CsQueuConnection, CsQueueSession, and CsQueueReceiver. As one can tell, those classes are quite similar to those in JMS. The constructor of POValidator class sets corresponding properties such as user name and password, initial context factory, and others, as shown in Listing 9-19:

Listing 9-19. Setting Queue Parameters

public POValidator() { m_qcfName = "primaryQCF"; m_queueName = "ReplenishStock"; m_usrName = "anonymous"; m_usrPasswd = "anonymous"; m_providerURL = "http://localhost:1856"; m_initialContextFactory = "fiorano.jms.runtime.naming.FioranoInitialContextFactory"; }

A property file can be used to specify these sorts of parameters to avoid hard-coding them into a program.

Prior to the message retrieval, the validatePO() method initializes corresponding queue connection values by creating a queue connection factory, accessing a queue, and creating a queue session and a receiver. The initialization process is nearly adequate to ones performed in Java, which were already discussed when creating a JMS-based message queue. This is shown in Listing 9-20:

Listing 9-20. Using C# CRL to Initialize Message Queue

// creating the initial context m_ic = new CsInitialContext(m_env); // look up connection factory. m_qcf =(CsQueueConnectionFactory)m_ic.Lookup(m_qcfName); // Look up queue m_queue =(CsQueue)m_ic.Lookup(m_queueName); // Create the connection m_qc = m_qcf.createQueueConnection(); m_qc.start(); //Create the session m_qs = m_qc.createQueueSession(false, 1);

The validatePO() method is invoked to receive the actual PO message:

CsTextMessage textMessage = CsTextMessage)m_receiver.receive(); string txtMsg = textMessage.getText();

Listing 9-21 shows the entire validatePO() method that encapsulates core C# CRL-based logic to access the JMS message queue.

Listing 9-21. Using C# CRL to Retrieve a Message from JMS Provider

public string validatePO(){ // Setting up environment for the Initial Context m_env = new CsHashTable(); m_env.Put("SECURITY_PRINCIPAL", m_usrName); m_env.Put("SECURITY_CREDENTIALS", m_usrPasswd); m_env.Put("PROVIDER_URL", m_providerURL); m_env.Put("INITIAL_CONTEXT_FACTORY",m_initialContextFactory); // creating the initial context m_ic = new CsInitialContext(m_env); // look up connection factory. m_qcf =(CsQueueConnectionFactory)m_ic.Lookup(m_qcfName); // Look up queue m_queue =(CsQueue)m_ic.Lookup(m_queueName); // Create the connection m_qc = m_qcf.createQueueConnection(); m_qc.start(); //Create the session m_qs = m_qc.createQueueSession(false, 1); // Receiving a message m_receiver = m_qs.createReceiver(m_queue); CsTextMessage textMessage =(CsTextMessage)m_receiver.receive(); string txtMsg = textMessage.getText(); return txtMsg; }

Sending out a message from a .NET application to the JMS provider is very similar. The ShipNotice.cs class shows how to accomplish this task. The process starts with initialization of the InitialContext environment shown in the previous diagram. To send a message, the following should be invoked:

CsTextMessage textMessage = m_qs.createTextMessage(); textMessage.setText(messageStr); m_sender.send(textMessage);

Категории