Friday, June 11, 2010

Implementing Apache Axis Webservices based on POJOs

In my last post I came up with the idea of generating a Webservice using dataclass generated from an actifsource model.

Have you ever wrote a wsdl from scratch? If you are used to the wsdl-schema, it seams to be really easy, even for beginners. Later on when you write the server-side implementation, you will soon find out that you always have to look out for inconsistencies. When you are done and start implementing the client-side, this task become more difficult, it's the third place where to keep consistency.

This week I started to explore how to generate an Apache axis webservice (http://ws.apache.org/axis/) with actifsource. First I looked at the eclipse web tool platform project (wtp), for common users point of views, it seems to be really straight forward. If the server-side project and the environment is set up correctly, the service classes are updated on the fly via hot code replacement and there is also the possibility to run the tomcat webserver in debug mode. In debug mode you can use breakpoints the same way in every other jdt project. That's fine.

One big disadvantage I found, was the way how dependencies are managed. There is an additional entry for the j2ee-dependencies in the preferences. This means you have to be careful where to set the dependencies, because only dependencies defined here, are automatically uploaded to the webserver.

If your project is also an osgi-bundle, then these dependencies are ignored. This is a thing you have to take care about, but it not really is a problem, since the server-side implementation should be in it's own project anyway. So what was really annoying? The wtp toolkit changed all projects , I added to the j2ee-dependencies. Now, I had dependencies to the eclipse builder of the wst-project in all library-projects I referred to. As that wasn't enough, the classpath was modified, to include the Apache Tomcat 6 Libraries.

The result is that when we are looking at the dependencies we now have to deliver all the tomcat libraries. Each developer working with these libraries has to install the eclipse wst, otherwise he gets an eclipse problem marker and the project won't compile. The solution I found, was to create a jar-file for each library directly in the webservice project. This means I have to keep them up to date by myself and they are duplicate for each webservice using them.

The alternative to this is either to find another toolkit, which behaves different or to create an actifsource solution. The actifsource solution should be able to create the dataclasses, the server-side implementation with protected regions and the client implementation directly from the model. Both the server implementation and the client implementation should have the same service interface. To be independent from the underlying webservice framework it should use a generic ServiceException instead, i.e. an AxisFault. The server implementation should be automatically packed in a service archive (.aar/.war) together with the required libraries. At the end it would be fine, if it also offers the possibility for automatic uploading to the webservice.

For this task I reuse the templates for the genericapp dataclasses and modified the model from service tutorial to fit my needs. I searched for a possibility to auto-generate the wsdl from the server implementation. Reusing the implementations from the wst-plugins was a good option, but failed by lack of information and doesn't seem to be easy and may be impossible.

Looking at the apache axis website I saw that they already used axis v2 and that there is no need to provide the wsdl in the ".aar" webservice archive. There is no longer the need for a deploy.wsdd and undeploy.wsdd, instead one has to put an "services.xml" to the META-INF directory of the webarchive. This file is really simple, it only needs the service name and some default handlers:



Since I want to use the actifsource namespace, I also defined the package-namespace mapping and a generated wsdl. One pitfall was generating a custom wsdl; it must be located in the META-INF directory (not in the wsld-directory as in axis 1) and in wsdl2 format, otherwise it will be ignored. Creating the server-side implementation including the templates costs me about four days. But not for writing the templates and the actifsource model. I spent most of the time reading documentation and discovering how the thing work in axis2. Thinking back, how to define the namespace-mapping and why my custom wsdl was ignored, was the hardest thing. Tcpmon was a really good helper. So basically, the main time I spent in learning how axis2 works.

The client implementation was much easier and compared to axis 1 which generates four classes for the implementation, in axis 2 there is only one implementation class needed and the interface definition can be shared between server and client.

Now after a week of work, I have a working generic app which has two part. A dataclass project, which defines the metamodel for the dataclasses and the service interfaces. And an axis-service-project to generate the axis-client and server implementation. Here is an example how the project dependencies in a simple setup will look like.



Note that the only actifsource model the user has to create is the dataclass. I think it is a good idea to provide a project generation buildconfig, which allows the creation of the target projects for client, server and dataclasses including an initial setup.

No comments:

Post a Comment