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.


Add to Technorati Favorites
Add to Digg

Thursday, April 12, 2007

Adempiere (Compiere) Web Services

I've been struggling for some time trying to come up with the right way to expose Adempiere (or Compiere) through SOAP-based web services (nothing against REST, but I'm still not convinced it's the way to go in an enterprise world, where security and vendor tool support are essential). A few months back, I wrote an Axis2 service wrapper that leveraged Compiere's model classes in a generic fashion. However, treating all Compiere/Adempiere documents using a single XML schema, while programatically simple, was less then elegant. Using this approach, I ended up with generic-looking XML that resembled:

<idal:mField idal:name="DatePrinted">
<idal:mField idal:name="Processed">
<idal:mField idal:name="DateAcct">
<idal:mField idal:name="IsPrinted">
<idal:mField idal:name="IsInvoiced">

This is really not ideal, as it's very verbose, and it circumvents the power of XML, which is it's self-describing vocabulary.

A more preferred approach to the above is something like:


Obviously, in addition to being more succinct, it's also more human readable, which is an important consideration.

Recently, after a taking a few months off on the project, I believe it is possible to relatively easily dynamically generate a SOAP WSDL that is fully expressive, and accomodates changes to the Compiere/Adempiere data dictionary. Further, by using XSD extension mechanisms, we can limit the number of operations, or verbs, to a reasonable number. So, under this scenario, we'd have operations (verbs) such as "Create", "Delete", "Update" and "Search", which can be applied to common documents (nouns) such as PO, Invoice etc.

Another key consideration is security. Passing username/password values, in clear text, even over SSL, is not sufficiently secure for most organizations. After all, the SOAP XML is probably littered throughout log files, leaving credentials easily exposed in clear text to any would-be hacker. Instead, the preferred approach is to use WS-Security, which through profiles, can support a variety of encryption solutions. For example, a binary hash token can be used that is highly secure. Further, WS-Security is one of the few WS-* standards that is actually more-or-less universally supported. For instance, the UsernameToken WS-Security standard is nicely supported by both .NET and Java (Axis Rampart), and presumably others as well.

Notwithstanding my earlier contention that SOAP is the best way to go in an enterprise environment, it's foolish to think everyone concurs with me on that. So, it also makes sense to expose the services through other protocols as well, including JMS and REST (or even email). My previous approach to using Axis2 really limited the solution to SOAP. What I'm proposing this time around is to use Servicemix as the integration broker, whereby it could receive the inbound messages in a variety of protocols. Thus, we're no longer just limited to SOAP.


From an architecture standpoint, what I had in mind was:

In the above scenario, Servicemix "binding components" are used to manage the inbound requests. From there, it's routed through a profile validation services (I'll explain more of this in a future posting), then ultimately to the implementation bean/service that will fulfill the request.


Obviously, this is a fairly ambitious undertaking. So, I propose the follwing phases:

Phase 1:
  • Authorization/Authentication via Profile service
  • Dynamic WSDL Generation
  • Core API set (Create, Delete, Update, Insert)
  • WS-I Basic Compatibility for SOAP.
Phase 2:
  • WS-Security Authentication using Mediator Service (Apache Synapse or Spring-WS, which has strong WS-Security support)
  • Additional API Calls.
  • Performance Improvements

I anticipate releasing the code under the same license as Adempiere, or even BSD, if appropriate. A Sourceforge project will be launched as soon as enough code exists to seed the project (nobody is interested in vaporware projects -- real code has to exist to excite the community). I have begun working on the code, an expect anticipate a May delivery timeframe for the first seed.

Add to Technorati Favorites
Add to Digg


Welcome to my new blog. I had one previously under TypePad, but it's hard to beat free, so I went over to Blogger.

This blog will mostly focus on the new technologies I've been working on lately. Hopefully you'll find some of my postings useful, and I'll always appreciate feedback.


jeff davis