jueves, 31 de julio de 2008

Sharing a property resolver between Spring contexts

A PropertyPlaceholderConfigurer is a well known tool in the Spring arena. It allows to externalize usually the most changing values of a given configuration to Java Properties files. In fact, Spring offers out-of-the-box implementations that can resolve property values from files, system properties, env properties or even web.xml context params. In addition, it's easy to create extensions to retrieve values from JNDI or database. For example, use the JNDITemplate to access the context and lookup properties:

public String resolveProperty(String property) {
   String value = null;
   try {
      value = (String) jndi.lookup("java:comp/env/" + property);
   } catch(Exception e) {
      try {
         value = (String) jndi.lookup(property);
      } catch(Exception ex) {}
   }
   return value;
}

The thing is once you have built your uber resolver chances are it will be used across all the different contexts. Unfortunately, even though the bean is inherited, BeanFactoryPostProcessors (and the PPC is one) are tightly coupled to the context where they're defined and won't do their magic in the outside world.

As a little side note, a bean factory postprocessor is a special kind of bean defined in an application context that is initialized and executed before any other bean. They can influence the behavior of the context loading. In our case it's modifying the declarations changing ${...} by an actual value. Of course, they're by definition closely coupled to Spring's life cycle.

So in Spring not being able to inherit PropertyPlaceholderConfigurers is considered a feature and it's by design. If you share a different vision and, for example, would like to share the same resolver between the contexts loaded by the ContextloaderListener and the DispatcherServlet, the good news is it can be done. We have to thank you Spring's configurability and the number of extension point it provides.

We will need two of them, the first is offered by DispatcherServlet and the second by ConfigurableListableBeanFactory. the servlet allow us (extending the class) to override the

void postProcessWebApplicationContext(ConfigurableWebApplicationContext wac);

method. This gives us a handler executed before the context is loaded (refreshed) for the first time. And it also gives us a reference to the context itself. In this situation we could add a new bean to this context easily but, better yet, we have a method to add a bean factory post-processor directly. The code is trivial, just get the previously defined bean from the (parent) context and add it. I'm using an anonymous inner class but it's not mandatory really.

wac.addBeanFactoryPostProcessor(new BeanFactoryPostProcessor() {
   public void postProcessBeanFactory(...beanFactory) throws ... {
      BeanFactoryPostProcessor resolver = beanFactory.getBean("resolver");
      resolver.postProcessBeanFactory(beanFactory);
   }
});

Basically that's all, change the web.xml (to point to the new class), remove the now redundant beans in the configuration files and redeploy.

miércoles, 23 de julio de 2008

Invoking Web Services via Spring

SOA SOA SOA...SOA everywhere. Right now it's difficult to work on an enterprise project and don't have the need to connect to a WebService. What would we be without these buzzwords...?

Unfortunately, for us developers that is, WebServices is not the easiest of technologies (understandable as the problem it solves is also complex) and Java's approach has always been guilty of not been the most intuitive. But the need is there so it has to be solved.

To call a Web Service there are several possibilities at the framework level. The first is to use JAX-RPC but this approach is in disuse today (for uber complexity). If we stick to the standard the next API would be JAX-WS. This is a much more polished API based heavily on annotations. JAX-WS is now part of the standard Java Standard Edition. Finally there are other alternatives in the Open Source scene. And better, Spring, in some form or another, supports all of them (Groovy also helps but not everybody has access to it).

It's important to notice that a developer has two ways to connect to a WS (I'll start talking about JAX-WS from now on), creating a SEI (Service Endpoint Interface) proxy or creating and sending a SOAP message. The first case allows the programmer to create a Java interface (mainly because actually it has to be annotated) and forget about the stub. The second (more powerful) alternative creates an XML structure from scratch. Spring facilitates the work with proxies. The later case requires the Spring Web Services subproject.

So how does Spring help? In two ways, it dynamically creates the proxy and injects it to the business beans seamlessly. For the most advanced use Spring, as of now, still requires the Java interface to be provided. All in all, it's not a big deal as there's a tool (wsimport) to generate it given a WSDL. Any good IDE will do it as well. Actually, wsimport generates more than one Java source because the parameters probably require a JAXB (read Java to XML) transformation.

I haven't talked about registries yet. JAXR is the Java API to connect to WSDL containers. They basically provide a level of indirection to a WSDL. JAXR is complicated (to some extent) and if possible I like the REST API better (but not all registries provide it!). IBM Service Registry does, for example (so you can just use Dom4J with some security). Anyway, JaxWsPortProxyFactoryBean (with minor tweaks) supports this kind of access.

That should be all for the gross of the situations. Recall that JAX-WS supports WS-I Basic Profile, MTOM and other such advanced protocols by default. That's not true for all of them though! For example, it requires some work to allow for message level security. This is overcome by the use of LogicalHandlers or SOAPHandlers (you can mix and match). In Spring or AOP jargon they would be called interceptors. They allow to modify the message prior to being wired. Another common and interesting use, for example, is logging. Spring allows handler injection grouped as HandlerResolvers.

So here's the final code:

<bean id="loggingHandler" class="mypkg.LoggingHandler" />

<bean id="defaultHandlerResolver" class="mypkg.ConfiguredHandlerResolver">
   <property name="handlers">
      <list>
         <ref bean="loggingHandler" />
      </list>
   </property>
</bean>

<bean id="wsdlRetriever" abstract="true" class="...JaxWsPortProxyFactoryBean">
   <property name="lookupServiceOnStartup" value="false" />
   <property name="handlerResolver" ref="defaultHandlerResolver" />
</bean>

<bean id="aSample" parent="wsdlRetriever">
   <property name="serviceInterface" value="..Sample" />
   <property name="wsdlDocumentUrl" value="http://...Sample?wsdl" />
   <property name="serviceName" value="Sample" />
   <property name="portName" value="SampleSOAP" />
   <property name="namespaceUri" value="..." />
</bean>

Get the logging handler source code along a good explanation from here.

martes, 8 de julio de 2008

Working with DWR sources

By now there's no doubt inside the software industry that the Open Source movement is here to stay. And the most valuable asset it provides is *hint* full access to the source code! And it's a shame that not that many people share this perception as for the majority of developers OSS just means free (read gratis) software.

Of course, being free (gratis) is handy characteristic but it should not be one that bothers much to the gross of us, as we work for companies that can afford it anyway. On the contrary, source code should be of interest for you. Let me just list some of the most useful perks:
  • It enables debugging
    Otherwise it becomes a blind and unproductive task. And believe me, the time spent debugging will be worth it.
  • It's the best learning tool any programmer can access
    It's code written by very proficient hackers revolving common but hard to solve problems.
  • It allows customizations
    And I include bug fixes here!
  • It makes you part of a community
    Share your code, discuss problems, hear other viewpoints, propose solutions et al!
IMHO fear is the main reason that prevents many programmers to contribute to the scene. But if you're by now convinced of the utility let me demystify the myths! Just follow with me this step by step tutorial to work with DWR source code :-)

Our first task is gaining access to the source code. DWR as many other projects stores the code in a repository. Beware that repositories are not like open wikis and people have different access rights. Anonymous access is the best we can hope for by now. There are many different server types (SCM), DWR has used CVS in the past but right now uses Subversion. We need to have a client installed to access a SVN repository and I can recommend Tortoise.

The repository is available at http://svn.directwebremoting.org/dwr/. It's huge as it includes all the versions ever released so it's probably better to point to the trunk folder (the latest code is available there) or, may be, branches/Branch_2_0/ (where the the code for the previous version lies).

To download the code to our machine we use the checkout command. The export command can be an option if there's no interest in having later updates. DWR has a page with detailed explanations for this step at their site.

Once we have it there we can explore it a little bit further. There are three important subfolders: core (DWR), serverside (different plugins) and ui (client side code).

There's also there a folder named etc that contains project files for different IDEs (netbeans, eclipse, IDEA). Opening DWR inside an IDE is as easy as navigating to the correct folder and opening the matching project. Opening the project in an IDE has the added benefit of allowing quick debugging of changes and their influence in your application.

Alternatively, DWR can be compiled using Ant (by just typing ant at the top of the hierarchy!). Regardless of the method, the compiled classes are always put in the (automatically) created target folder.

Some projects have an extensive documentation available. DWR does not particularly shine in this area (intentionally many times!) but, at least, things are organized so finding something should be manageable. For example, all the Spring integration classes are available inside the serverside/spring folder and are bound to just one package.

And that's all basically. Some simple steps that have configured DWR inside your workspace and facilitate your development needs. And once it's there nothing prevents you to dive a little and improve the tool ;-)

Happy hacking!