Showing posts with label annotations. Show all posts
Showing posts with label annotations. Show all posts

Monday, May 11, 2009

A quick note on intercepting annotations with Spring AOP

Spring AOP is incredibly powerful. One of the most powerful features of the framework is that it lets you intercept methods that are decorated with particular annotations using the following AOP expression :

@annotation(my.package.MyAnnotation)


This can be used in place of :

execution(public * my.package.MyService.serviceMethod(*))


...or in combination with it. But one important point : the annotation being intercepted must be in service method implementations (ie concrete class implementations), not on the service method interface declarations! Otherwise Spring AOP will not be able to read and intercept the annotated methods / classes

Thursday, June 05, 2008

JAXB schemagen - Finally got it working

For those not in the know, schemagen is a program that comes as part of the Java Web Services Developer Pack and it's used to generated XML schemas from JAXB annotations on Java beans. It so happens that the creators of the JAXB reference implementation also made a Maven 2 plugin for this program. I had previously attempted to use it to generate schemas in my initial attempts with JAXB, but had been presented with a slough of unfriendly exceptions being thrown at me whenever I ran the plugin. Not having the time back then to really play around with it and being considerably less experienced with JAXB, I had to shelve it and find other, less satisfying solutions to my problems with generating documentation.


Recently, I've had to come back to using JAXB because I'm making a RESTful Web Services API that leverages the power of both JAXB and Hibernate to do all my heavy lifting for me. This time around, I wasn't willing to tolerate a lack of schema to give to our users of the API, because it would mean a lot more work for them, and a lot more work for me. This time, I decided to be persistent and dig around the jaxb-schemagen plugin to make sure I could get it working. I'm proud to say that my perseverance paid off, and I now have my RESTful API schema being automatically generated for my application. Here are the problems and the solutions I ran into when I was trying to get going on this:



NullPointerException

I came across persistent NullPointerExceptions while trying to run the plugin at first. The stack trace indicated that the problem was with apt, the Java annotation processing tool. I later discovered that in order to properly map your classes into XSD schema types, you must specify an @XmlType annotation on *all* of the classes you wish to map (at least with JAXB 2.0, which is the version I'm currently using)

ClassCastException

After I resolved the first problem, I came across another pesky exception that likewise did not provide any useful debugging information. The plugin output indicated that it was finding annotations that it didn't know how to deal with, specifically the Java Persistence API annotations that I was using for Hibernate. After much digging around on Google and some detective work, I discovered that any annotations encountered by the jaxb-schemagen plugin had to be on the Maven runtime classpath. I double checked my POM to find that I had specified the scope of the JPA / Hibernate annotations as 'provided', which instructs Maven not to load them into either the compile or runtime classpaths. The initial reason I had for specifying the dependency scope as 'provided' was so that they would not needlessly get included with my project WAR files. I changed their scope to 'compile' (which also includes 'runtime') and voila, apt could now properly detect the unknown annotations, and get past them to deal with the JAXB annotations it needs to create the XML schema.



If anybody else encounters similar errors with JAXB-schemagen, I hope they find this page and find it useful.

Monday, May 26, 2008

RESTful web services with JAXB 2.0

In case you're not familiar, JAXB (Java API for Xml Binding) is an API developed by Sun for binding between XML and Java beans. The first incarnation, 1.x, was interface+implementation based like XMLBeans from the Apache Project. The second incarnation, 2.x, is annotation+pojo based. It's a very useful API, especially when combining it with Hibernate (and the Java Persistence API) to make restful web services. But, that's not really the point of this post. The point is that I've been using JAXB 2.0 for web services much in the past, but this is the first time where I've had to map the "class hierarchy per-table" pattern used by Hibernate into XML. As it turns out, JAXB 2 has very good support for this pattern. You can read more on this at the java.net project page for JAXB.

Wednesday, October 31, 2007

Maven 2 quirks and the "bandwagon"

I recently found myself developing (and using) a lot of small tag libraries to make my life easier when it comes to developing my web applications. The only thing that really gets me is that when I write these tag libraries, I have to manually update all of the TLD (tag library descriptor) files that are necessary for using the tags in JSPs. This irks me and it occurs to me that there's no reason I can't have Maven generate the TLDs for me based on annotations I place on the tag classes. The only problem with this is that no such plugin exists, so I figured that as a foray into Maven plugin development, I'd try making such a plugin as my first try. It is then that I ran across a rather large and bothersome quirk with Maven : it's not entirely ready for Java 5 and up. In fact, rather than using proper Java 5 annotations, it uses XDoclet comment annotations to provide metadata for building plugins, but that's not the quirk. The real quirk is that it can't handle having Java 5 annotations in the same project as the plugin. It can handle Java 5 enums just fine, but not annotations, which seems rather strange to me.

This is all part of the bigger problem of companies not keeping themselves up to date with the latest Java technology and staying with Java 1.4.2 and earlier. Sun has done a great job of maintaining backward compatibility, and there's (almost) no reason that companies shouldn't be upgrading the JVMs on their servers to the latest and greatest versions. The only real reason I can think of is that somewhere in their code, they've used variables named 'enum' which becomes a Java keyword in Java 5 and up (aka Java 1.5, 1.6, etc), and this can be mitigated by refactoring the code. Hell, Eclipse makes that job quick and easy, especially when you really know your keyboard shortcuts. I'm fortunate enough to be able to use Java 6 (and very quickly upgrade to Java 7 as soon as it's released and stable). As much as this is going to make me a snob, I'm getting really tired of being dragged down by other people's need for backward compatibility (and hence also tool developers' appeasement of these people which then affects me). Seriously people, get your act together.

Wednesday, August 22, 2007

Moar (sic) hibernate !

Yet more hibernate fun facts that I wish I'd had before I started any projects : Hibernate has the ability to persist instances of java.util.Locale, java.util.Currency, and java.util.TimeZone. A sprinkling of a few bits of these pieces of code and their corresponding hibernate annotations could have saved me an assload of time spent on doing my own design, development and testing.

On a small side note, I found I've actually managed to come up with a much better and more appropriate solution for dealing with currencies than the java.util.Currency class, as it's woefully inadequate to the task of dealing with currencies in an enterprise system. I refer specifically to the way it deals with floating point arithmetic in its number of decimal places, rather than adering more closely to the ISO 4217 specification whereby currencies should have a base and an exponent when calculating a multiplier to go between base currency units and major currency units.