Some adventures with ejb 3 and jax ws

You may recall some of my recent frustrated posts regarding the poor state of web services in java. While I still stand 100% behind these comments, I’ve found a somewhat more convenient way of implementing web services using JAX WS 2.0 now. I spent a few hours with jboss 4.0.4 AG to explore its implementation of some of the new JEE 5 (formerly known as J2EE) stuff. Up to now I’ve never bothered with J2EE 1.x since I consider it an overarchitected, complicated technology aimed at addressing what are (or should be) simple issues such as persisting an object to a database.

The nice thing with the latest incarnation of the specification is that it supposedly removes much of the burden of telling the application server to just do its thing. Using annotations you specify what it should do and then it actually goes about and does it without me editing hundreds of little xml files and googling an afternoon for the corresponding documentation; googling some more for stuff the documentation does not tell you and finally yet more googling to explain the obscure exceptions in the log. Well it turns out that some googling skills remain essential but it sort of works as advertised. Basically the process is to write some Pojos, add some annotations and hand the whole thing to the app server to have a magic layer of web services, persistence and transactional semantics generated automatically.
Lets be fair, jboss does not address all issues in J2EE 1.4 and the JEE 5 implementation is definately not complete. But overall it is a huge improvement over the way things used to be, provided you do it exactly as they want you to. The only other open source implementation of the latest specs is Sun’s glassfish so there is not exactly that much choice. Luckily, JBoss is pretty nice technology.
I had some issues which were related to various things not being deployed because of errors in (jboss specific) files, which actually cost me most of this morning. My original aim was to re-implement a hibernate+tomcat based web application I already had and which I am going to do some feature development on soon. This should be easy because jboss uses hibernate to implement ejb 3 persistence and tomcat to run web applications. Indeed I had some benefit since I could copy paste a bit of the more obscure things in the hibernate configuration, thus bypassing several hours of agonizing googling for issues with mysql (did that a few months ago).

The object relational mappings were of course reusable but the whole point of ejb3 is that these are now replaced with much less verbose annotations. Adding the annotations was pretty straight forward. Next step was convincing jboss to do something with them. This is as easy as embedding a persistence.xml file in the jar file with the classes. The main purpose of this file seems to be to tell the appcontainer to hook up a database resource to the entitybeans inside the jar. Additionally some database specific configuration is embedded as well. IMHO mixing configuration with deployment artifacts is not a good idea but I guess we’re stuck with this for a while since it is part of the standard now.
The next step was less easy: dependency injection. It turns out that jboss, or rather tomcat, is not quite ready for the new servlet specification that comes with JEE 5. In other words, any annotations in a servlet are ignored. If you want to use your persistent objects you need to create a so called entitymanager manually. Some googling delivered various code fragments of which one seemed to do the trick. The omnipresent fragments depending on an annotation only work inside an ejb.
Next on the agenda was creating a stateless session bean to encapsulate the business logic. Again some simple annotations do the trick and supposedly dependency injection does work here so getting the entitymanager injected actually works (with the added advantage that the app container is a lot smarter about figuring out transactional semantics). The only problem: it wasn’t getting deployed :-(. Entity beans in a war (web application archive) file are no problem but session beans are.

So I figured I should create a nice ear file (enterprise application archive). This step btw is missing in action from the nice JBoss tutorial I had been glancing through. OK it’s just a zip file with some stuff in it and a pretty straightforward. Essential is the application.xml which you shouldn’t need but which JBoss needs anyway and crucial is the little jboss-app.xml which only needs to contain a few lines to trick it into deploying the session beans with the ejb3 deployer. Similarly the war file with my servlet needs a jboss-web.xml. Anyway, the whole point of an ear is tricking jboss into deploying jar files with the right deployer. None of the info in application.xml and jboss-app.xml actually tell jboss something it couldn’t figure out itself.
The above took quite a few hours of trial and error. I wrote all java code in under 5 minutes however. The rest of this time was spent googling for the right bits and pieces. Any mistake leads to obscure errors such as a null pointer error when using the entity manager which should have been injected but wasn’t. Anyway it now works and I managed to JAX WS 2.0 enable my code with a mere two annotations. Two simple annotations to expose a session bean as a webservice is way more cool than generating wsdl + crappy stub code using axis and hooking up your code to it. I’m definately going to use this some more.
The good:

  • It actually all works as advertised.
  • Writing the java code is considerably easier when you don’t have to worry about boilerplate stuff for setting up database connections, transactions, etc.
  • I will be able to do all of the above in ten minutes in future projects.
  • JAX WS is getting quite close to how I want to work with web services: i.e. keep the stinking WSDL out of my sight.

The bad

  • Plenty of container specific gotchas left but much less than there used to be.
  • Still some pointless configuration files that I want to get rid off. Application.xml; jboss-*.xml; persistence.xml; web.xml all could be simplified or removed entirely. IMHO the jboss-* files are there because the specs omit important features related to deployment. If the spec were improved there would be no need for these files.
  • There’s likely to be a few issues I just have not ran into yet.
  • Documentation is sketchy, misleading and incomplete. The tutorial not explaining how to hook an ejb up to a servlet (kind of essential) without annotation support has cost me quite a bit of time. Since I first had to figure out why the ejb wasn’t being deployed and then how to fix that.

Overall, I’m positive and will continue to use this stuff.

Axis2 – 1.0 First impressions

I’ve had some opportunity to play around with the newly released Axis2, apaches web service framework and container. Essentially this is a complete rewrite of Axis 1.x which is why it is called Axis2 – 1.0.

This brings me to the first point of criticism: This is needlessly confusing. It is really a completely separate product and the two products sharing, for example, a mailinglist makes no sense at all (just annoys users of either browsing through the messages). It should have a different name and its own mailinglist.
Then the 1.0 status. Traditionally 1.0 is associated with a certain level of quality and feature completeness. With axis2 – 1.0 this is undeniably not a 1.0 by any standards. A few points of criticism:

  • It contains obvious flaws. For example, generated client stubs throw Exception instances rather than something a bit more specific. In my book that is a bug, not a feature. Lots of things can go wrong in a SOAP clientstub, I require more detailed feedback.
  • Documentation is plentyful but inacurate; incomplete and downright misleading and does not address the obvious use cases. For example, using anything else but RPC style SOAP requires you to provide manually written WSDL. The provided non RPC examples work but the server is unable to generate WSDL for them. This makes them rather useless. Second of all, it is not actually documented how to do an RPC style SOAP service.
  • Error feedback is non existent. For example, a classnotfoundexception I know occured because my buildfile was not including something never made it to the tomcat console. This means that deep down in the axis code this exception occured, was caught and not logged or rethrown. If I sound annoyed, the reason is that I just spend a frustrating couple of hours getting a simple web service to work. Sure I made mistakes and in none of the cases I managed to get meaningful exceptions or log feedback. I must have triggered a few dozen common failure points and axis was just sitting there pretending everything was alright while it definately was not.
  • The default dependency on log4j messes up my usual logging configuration (and might actually be the cause for the previous). I am of the opinion that log4j is a legacy component that should never be depended on directly.
  • The aar concept is poorly thought out and poorly documented (none of the documentation explains that contained jar files have to be in a lib directory, failure to put them there will result in unlogged classnotfound exceptions). Any non trivial service will have library dependencies and will require external configuration. For example, I use hibernate which requires me to modify the service container and break encapsulation to add a jndi ref to the database. How many meaningful services without at least a database connection are likely to be created? The point is that aar’s do not encapsulate the web service and its dependencies fully. On top of that hot deployment is broken in tomcat (release notes say this). A cold start sometimes runs into trouble with apparently cached stuff left in various directories (this might be a tomcat problem). Solution: remove work directory and subdirectory of conf.
  • The generated client stub code is crap. For a start, it doesn’t seem to respect code conventions; contains newlines in weird places and seems to be a container for several nested clasess. On top of that error handling is poorly implemented: this generated code will cause its users lots of misery. And then as mentioned above, there is actually this fragment “throws Exception” in several methods. Inexcusable.
  • The client stub when used complains about log4j not being configured. That is correct, I never use it and have no desire to use it. As stated above, the dependency on log4j is a bug and not a feature. Apache commons.logging, which is used in many other apache projects is included as well and fully prevents the need for log4j. Removal of the log4j jar file actually breaks axis currently!

Does this mean it is a bad product? Yes and no. If you regard this as a middleware component to be integrated by e.g. geronimo, it’s current state is probably acceptable since the integrator can fix things; provide documentation and provide proper tooling. If on the other hand you expect the thousands of axis 1.x users to migrate to axis 2 at this point then no way. I’m sure things will get better from here on but there is a lot of work to do before I would recommend anyone to migrate. Production usage of axis2 at this point will be causing a lot of people a lot of headaches at this point.
At this point I am willing to deal with the issues above and will continue using it (mainly because I’m interested in using some of its features). However, this is in my book an alpha release, not even a beta. I’m used to more quality from apache and am honestly wondering what the hell happened there.