Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Friday, May 4, 2007

Adempiere Integration Framework: Part 1

Adempiere, an open-source ERP system who's heritage is from Compiere, offers several convenient mechanisms for integrating with external services. Perhaps the most flexible and powerful are Adempiere's Service Processes (we'll call them Processes for short). They essentially represent callouts that you can invoke from within Adempiere. They can be triggered by user actions, such as clicking on a button, or programmatically through workflows. What's particularly enticing about them is how simple they are to develop -- A topic I will cover at a future time. My focus on this article is how they can be used, in conjunction with a integration bus, or ESB, to effectively integrate with external services.

External services can be any system that Adempiere needs to communicate with. For example, integrating with a shipper or credit card processor comes to mind. Or, synchronizing data with popular CRM systems such as Salesforce.com or SugarCRM. While people have been doing this sort of thing with Compiere/Adempiere for a long time, more often than not, it's a point-to-point integration. The disadvantage to this approach is that it can quickly become unmanageable, and tightly couples the integration code into Adempiere. This limits flexibility, and can be fragile and difficult to maintain.

The increasing popularity of Enterprise Service Buses (ESB) has occurred because of the recognized limitations and issues surrounding point-to-point integrations. In addition, ESB's generally provide a bevy of reusable adapters, such as SOAP, HTTP, Email, FTP etc., that eliminate the need to recode these solutions over-and-over again. Often, they also have sophisticated business process orchestration features such as BPEL, built-in, to help design and manage complex workflows. Popular open-source ESB's include Mule, Apache Servicemix, OpenESB , PetalsESB and Celtix.

In the scenario for today's topic I want to discuss a framework that can be use invoking external services from within Adempiere using a Process. The Process, in turn, publishes the outbound request into a JMS queue or topic. From there, it is lifted for processing by an ESB. The ESB, using it's rich set of pre-built adapters, transforms the request to the destination format, and submits it for processing. This process can be asynchronous or synchronous, depending up the client's requirements.

Why not just invoke the ESB directly from within the Adempiere Process. Again, it's about keeping things loosely coupled. We might want to change ESB's at some future point, and hardwiring specific ESB code (most likely proprietary in nature, using it's APIs) into the Adempiere Process callout limits such flexibility.

Using JMS, however, we can define a standard XML schema for the data transfer. As long as the request/response adheres to the proper format, the Adempiere Process could really care less about the implementation details.

Below is a diagram of what I'm describing:



As you can see, in this diagram, I'm using the Servicemix ESB (which I do have a preference for, given it's JBI-compliance, maturity, breadth, and Spring-based architecture). A Servicemix JMS component (in JBI parlance, that's a "Binding Component") lifts the JMS message sent by the Adempiere Process, then performs some transformation and business rule processing using pre-built components designed for that purpose ("Service Engines", in JBI). Then, when the XML is in the appropriate format/schema, a SOAP adapter is used to call the external web service that's providing the service desired.

This architecture is highly flexible, and allows for a wide variety of implementations. For example, the JMS and Servicemix instances can be running in a distributed fashion on one more services (both ActiveMQ and Servicemix provide clustering capabilities as well).

In my next article, I'll describe how an ESB can be used to receive inbound request generated externally from Adempiere. For example, a sales order that is received from an external channel, such as an ecommerce web site.

As always, I welcome your thoughts/comments.

jeff

Add to Technorati Favorites
Add to Digg

Tuesday, April 17, 2007

Using Adempiere's Data Dictionary

One of the most powerful aspects of Adempiere (and, by virtue, Compiere), is its robust and comprehensive data dictionary. Virtually the entire application is defined within it, thus making modifications and enhancements a very straightforward (in many respects, it's a true model-driven architecture, MDA).

As part of the Web Services initiative I'm working on, it's necessary to dynamically generate the XML schemas for those objects that are required to be exposed as web services. This can be done easily by using the org.compiere.model.MTable and org.compiere.model.MColumn classes. The combination of these provides you the properties ofa particular Adempiere/Compiere object, including such relevant information as: column name; column type, column length; default values; and reference information.

Let's take a specific example -- the C_Invoice object, and determine it's columns and associated properties. Here's some Java pseudo-code that illustrates how this can be done:

MTable mTable = MTable.get(Env.getCtx(), "C_Invoice");
MColumn mcolumn[] = mTable.getColumns(true);

for (int i = 0; i < mcolumn.length; i++) {

   System.out.println("Column is: " + mcolumn[i].getName())

   System.out.println(" Desc is: " + mcolumn[i].getName());
   System.out.println(" Length is: " + mcolumn[i].getName());
}


As you can see, it's very easy to interrogate what fields and properties belong to a given object, and it's completely dynamic, driven by the current configuration specified in the data dictionary.

For the web services initiative, I'm using this data to dynamically generate the WSDL schema.

jeff

Add to Technorati Favorites
Add to Digg