Wednesday, December 21, 2005

Part II:Using Spring to consume web services; advanced example using Google Web APIs doGoogleSearch

I should point out that what I am about to show is not necessarily the quickest way of getting the Google Web API doGoogleSearch up and running. In this particular case Google already provides a Google Web API Developer's Kit which you could use to do all of the functionality I am about to describe, indeed some of the precompiled Google Web API package will be interchangeable with what I am about to generate using the Axis WSDL2Java tool but I hope this example will give you some ideas that can be applied to web services in general and not just the Google Web API.

In my last blog entry, I showed how you can access doSpellingSuggestion with Spring and since this service only returns a String there was no particular complexity involved. doGoogleSearch returns a more complex response and so I am going to use Axis' WSDL2Java tool to generate the beans that I will need to capture this more complex response. Remember that WSDL2Java is intended to produce Axis specific code and since I'm using Spring to do the web service access I don't actually need all the generated Axis code. I downloaded Axis 1.3 and created an Ant script containing the relevant Axis WSDL2Java Ant task.


<?xml version="1.0" encoding="UTF-8"?>
<project name="googleApi" default="wsdl2java" basedir=".">

<path id="axis.classpath">
<fileset dir="./lib">
<include name="**/*.jar" />
</fileset>
</path>

<taskdef resource="axis-tasks.properties" classpathref=""axis.classpath" />

<target name="wsdl2java">
<mkdir dir="src"/>
<axis-wsdl2java
output="src"
testcase="false"
helpergen="true"
verbose="true"
serverside="false"
url="http://api.google.com/GoogleSearch.wsdl" >
<mapping
namespace="urn:GoogleSearch"
package="com.google" />
</axis-wsdl2java>
</target>


</project>

The important thing to notice about this is that I am using the helpergen="true" option by doing this I am asking WSDL2Java to store any Axis specific code away from the valuable beans that I actually want. After running this script I have a collection of generated classes, some of which I don't actually need. The following list shows the classes that are produced by running WSDL2Java against the Google WSDL with the classes I don't need indicated via a strikethrough.

  • DirectoryCategory.java
  • DirectoryCategory_Helper.java
  • GoogleSearchBindingStub.java
  • GoogleSearchPort.java
  • GoogleSearchResult.java
  • GoogleSearchResult_Helper.java
  • GoogleSearchService.java
  • GoogleSearchServiceLocator.java
  • ResultElement.java
  • ResultElement_Helper.java

After deleting all the helper classes, BindingStub and Locator I have removed all the Axis specific code. I am left with the beans I need to capture my responses to doGoogleSearch and also a convenient port interface class.

In this case we are expecting the web service to return something more complicated than a String so we need to extend JaxRpcPortProxyFactoryBean in order to map the service response given to our generated beans. Modifying the example given in the Chapter 16. Remoting and web services using Spring I get:


package fullgoogleapi;

import com.google.DirectoryCategory;
import com.google.GoogleSearchResult;
import com.google.ResultElement;
import javax.xml.namespace.QName;
import javax.xml.rpc.Service;
import javax.xml.rpc.encoding.TypeMapping;
import javax.xml.rpc.encoding.TypeMappingRegistry;
import org.apache.axis.encoding.ser.BeanDeserializerFactory;
import org.apache.axis.encoding.ser.BeanSerializerFactory;
import org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean;

public class GooglePortProxyFactoryBean extends JaxRpcPortProxyFactoryBean {

protected void postProcessJaxRpcService(Service service) {
TypeMappingRegistry registry = service.getTypeMappingRegistry();
TypeMapping mapping = registry.createTypeMapping();
registerBeanMapping(mapping, GoogleSearchResult.class, "GoogleSearchResult");
registerBeanMapping(mapping, ResultElement.class, "ResultElement");
registerBeanMapping(mapping, DirectoryCategory.class, "DirectoryCategory");
registry.register("http://schemas.xmlsoap.org/soap/encoding/", mapping);
}

protected void registerBeanMapping(TypeMapping mapping, Class type, String name) {
QName qName = new QName("urn:GoogleSearch", name);
mapping.register(type, qName,
new BeanSerializerFactory(type, qName),
new BeanDeserializerFactory(type, qName));
}

}

Now to add a service interface. This is essentially a slightly modified version of the generated class GoogleSearchPort.java but in the service interface we no longer throw RMI exceptions. Contrast this to the previous doSpellingSuggest example as I will define all the methods properly and not just to satisfy the endpoint matching so that I can now use all of the methods if I want to.


package fullgoogleapi;

public interface GoogleSearchService {

public byte[] doGetCachedPage(String key, String url);
public String doSpellingSuggestion(String key, String phrase);
public com.google.GoogleSearchResult doGoogleSearch(String key, String q, int start, int maxResults, boolean filter, String restrict, boolean safeSearch, String lr, String ie, String oe);

}

My new applicationContext.xml file incorporating the extended JaxRpcPortProxyFactoryBean, generated port interface class and the service interface above will look something like this:


<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="googleService" class="fullgoogleapi.GooglePortProxyFactoryBean">

<property name="serviceFactoryClass">
<value>org.apache.axis.client.ServiceFactory</value>
</property>

<property name="wsdlDocumentUrl">
<value>http://api.google.com/GoogleSearch.wsdl</value>
</property>

<property name="namespaceUri">
<value>urn:GoogleSearch</value>
</property>

<property name="serviceName">
<value>GoogleSearchService</value>
</property>

<property name="portName">
<value>GoogleSearchPort</value>
</property>

<property name="portInterface">
<value>com.google.GoogleSearchPort</value>
</property>

<property name="serviceInterface">
<value>fullgoogleapi.GoogleSearchService</value>
</property>

</bean>
</beans>

The test class will now look something like this:


package fullgoogleapi;

import com.google.GoogleSearchResult;
import org.apache.commons.collections.BeanMap;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApplication {

private static ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
private static GoogleSearchService service = (GoogleSearchService) context.getBean("googleService");

public static void main(String [] args) throws Exception {
String key="<Insert Google Web API key here>";
String test = "webservie";
System.out.println(service.doSpellingSuggestion(key,test));

String q ="shrdlu winograd maclisp teletype";
int start = 0;
int maxResults = 10;
boolean filter = true;
String restrict = "";
boolean safeSearch = true;
String lr = "";
String ie = "latin1";
String oe = "latin1";
GoogleSearchResult gsr = service.doGoogleSearch(key, q, start, maxResults, filter, restrict, safeSearch, lr, ie, oe);

BeanMap googleResults = new BeanMap(gsr);
System.out.println(googleResults.toString());
}
}

If you have used Axis before I hope you'll agree that this is considerably simpler than wiring together all the generated BindingStubs and Locators. In this example I've reduced the role of WSDL2Java from an Axis code generator to a simple WSDL aware bean generator. The minute you run into problems you will probably have to go away and learn how to use Axis's TCP Monitor etc. Using this method, if you are lucky, you may get away with not even having to look through a WSDL or even browse a SOAP message. It would be nice if you knew all the intricacies of SOAP, Axis and web services but with this method I think it becomes slightly less important than it was before. I would expect you to be more productive at consuming web services using the Spring enabled web services approach than the method that Axis previously offered.

Part I:Using Spring to consume web services; simple example using Google Web APIs doSpellingSuggestion

I have recently been investigating the Spring Framework and turned my attention towards Spring's offerings in the field of web services. I have had several previous encounters with web services and have even tried hand coding SOAP messages (an experience not to be recommended). The Jakarta IO-taglib is very useful for knocking up simple stuff (like XML-RPC pings) and Apache Axis has come a long way since Apache SOAP in making things much simpler especially with its JWS instant web services. As you would expect from Spring there is also a nice way to create web services (ServletEndpointSupport) but as the Axis method is so simple already it probably doesn't really add that much to this area.

Almost paradoxically it seems to me that since Axis introduced JWS it has always been much easier to produce web services than it is to consume them. The real effort is needed on the client side rather than at the server. Granted Axis has some great tools like WSDL2Java that can generate most of the Java I need to talk to a web service but despite peoples best efforts to persuade me that this is all quite simple, once I've actually looked at the source code produced it makes me recoil in horror. SoapBindings, Stubs, Skeletons and ServiceLocators, yuck! I know my horror is based on a fundamental lack of understanding but I don't really want to be bothered dealing with stuff like that, I'd rather things like that were done by someone or something else. WSDL2Java wouldn't exist at all if this stuff was easy to produce now would it?

Enter Spring...

It isn't the simplest thing in the world to consume web services with Spring but IMHO it is much easier than wiring the WSDL2Java generated Axis code together.

Now let us look a example, I am using the Google Web API which gives me enough functionality to play with (simple and more advanced) and hopefully there are enough examples of its use already out there for you to make a good comparison. It has been my experience that although Spring seems to provide tools for many diverse areas it can be quite difficult to find good explanatory documentation with examples, such was my finding in the area of web services (I know I should go out and buy Spring in Action). Granted there is the Spring Documentation chapter Chapter 16. Remoting and web services using Spring but initially I found that I had to resort to finding an example on a blog. The blog example I found first was on Petrik de Heus's blog. I downloaded the code, added the necessary libraries and an Ant build script and dug out my Google Web API key and got it working. However, I couldn't understand the example, the code went to great effort to create a GoogleMessageBean and register this bean in some mapping gizmo but at no point did I actually see the bean being used, I found the example quite confusing but at least I was now armed with the right class name (JaxRpcPortProxyFactoryBean). Petrik's example all seemed a little too magic and although Spring does magic sometimes, I felt that something was not right about this. I found my answer after a little Googling around, browsing the Spring's API docs and especially in Bill Siggelkow's Weblog and ultimately I found a great example using Babelfish from the Spring in Action source code (available for free from the Manning site, I know I'm a cheapskate for downloading the source code for a book I haven't yet bought but as they say Talent Borrows, Genius Steals). For something as simple as the Google Spelling Suggestion that returns a String it turns out that you do not need even need to extend JaxRpcPortProxyFactoryBean, you just need to create port and service interfaces (and even the service interface is optional).

applicationContext.xml


<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="googleService" class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">

<property name="serviceFactoryClass">
<value>org.apache.axis.client.ServiceFactory</value>
</property>

<property name="wsdlDocumentUrl">
<value>http://api.google.com/GoogleSearch.wsdl</value>
</property>

<property name="namespaceUri">
<value>urn:GoogleSearch</value>
</property>

<property name="serviceName">
<value>GoogleSearchService</value>
</property>

<property name="portName">
<value>GoogleSearchPort</value>
</property>

<property name="portInterface">
<value>spellsuggest.SpellingSuggestRemote</value>
</property>

<property name="serviceInterface">
<value>spellsuggest.SpellingSuggestService</value>
</property>

</bean>
</beans>

SpellingSuggestRemote interface


package spellsuggest;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface SpellingSuggestRemote extends Remote {

public String doSpellingSuggestion(String key, String input) throws RemoteException;

/* The following methods are here but are not to be used.
* They only here in order to match the endpoint methods in the WSDL.
*/


public String doGoogleSearch() throws RemoteException;
public String doGetCachedPage() throws RemoteException;

}

SpellingSuggestService interface


package spellsuggest;

public interface SpellingSuggestService {
public String doSpellingSuggestion(String key, String input);
}

Test class


package spellsuggest;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {

private static ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
private static SpellingSuggestService service = (SpellingSuggestService) context.getBean("googleService");

public static void main(String[] args) {
String key = "<Insert Google Web API key here>";
String test = "webservie";
System.out.println(service.doSpellingSuggestion(key,test));
}

}

...and that is all there is to it. In my next blog entry I will explain how to access everything that the Google Web API has to offer in a Spring enabled way.

Tuesday, December 20, 2005

Transaction Management with iBATIS and Spring

For Othon Sanchez, who wrote:

I'm trying to implement ibatis, spring and JSF. Not so hard until now but I have a special requirement, I need to handle the transaction in a EXTERNAL way, like the documentation of iBatis suggests. My question is, do you know how I can implement iBatis and Spring handling by my own the transaction?. Do I need to configure something else in the applicationContext.xml or dataAccessContext-xxx.xml?.

I have to admit that I know very little about transaction management as I have only recently learnt about Spring and iBATIS myself. Since I haven't actually done this yet, what follows is completely guess work (comments from the more experienced and learned are always very welcome).

Spring apparently provides it's own transaction management capability which looks to me like it works with iBATIS. In the API docs for SqlMapClientFactoryBean there are several mentions of transaction management. There is a method setUseTransactionAwareDataSource() where it says something about using Spring's managed transactions by default.

It also says it uses iBATIS EXTERNAL style transaction management by default (com.ibatis.sqlmap.engine.transaction.external.ExternalTransactionConfig). Incidentally, there are also methods available that can be used to set transactionConfigClass and transactionConfigProperties (see also here).

To actually use transaction management the following is what I would think you need to do (this is complete guess work on my part). This is based upon the synthesis of Spring Chapter 8. Transaction management and Faster, Lighter, Better?: Spring time for J2EE by Björn Beskow [PDF]).

In your applicationContext.xml you would define your datasource, datasource proxy, transaction manager as well as all your other DAO bits and pieces (as I showed previously in an iBATIS related entry). Additionally, I would now also expect that you would inject the transactionManager bean into the DAO implementation. So the XML configuration file might look something like this:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<bean id="dataSourceImpl" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>org.apache.derby.jdbc.EmbeddedDriver</value>
</property>
<property name="url">
<value>jdbc:derby:build/derby/simpledb</value>
</property>
</bean>

<bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
<property name="targetDataSource">
<ref local="dataSourceImpl"/>
</property>
</bean>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource"><ref bean="dataSourceImpl"/></property>
</bean>

<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation"><value>sqlmap-config.xml</value></property>
</bean>

<bean id="itemDAO" class="mypackage.sqlmapdao.SqlMapItemDao">
<property name="dataSource"><ref local="dataSource"/></property>
<property name="sqlMapClient"><ref local="sqlMapClient"/></property>
<property name="transactionManager"><ref local="transactionManager"/></property>
</bean>

<bean id="facade" class="mypackage.domain.logic.FacadeImpl">
<property name="itemDao"><ref local="itemDAO"/></property>
</bean>

</beans>

Then in order to do programmatic transaction management in your DAO implementation you could create transaction managed methods using Spring's TransactionTemplates. There are other ways that you can do transaction management more directly using the PlatformTransactionManager or even less directly using AOP for declarative transaction management, further instructions can be found in Spring Chapter 8: Transaction management:


TransactionTemplate txTemplate =
new TransactionTemplate(txManager);
Object result = txTemplate.execute(
new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
// Do some work on a transactional resource
// Return some result object or throw an unchecked exception
}
);

Monday, December 19, 2005

Initial impressions after my first contact with Spring AOP

I have been looking into Aspect Oriented Programming(AOP) and following some HelloWorld AOP examples from OnJava. My interest stems from my current investigations into using the Spring Framework.

AOP suffers from being very densely populated with specialised terminology. Often times the terms are defined using further dense terminology which has the effect of placing an impenetrable barrier in front of the precise meaning. For example, I found the following definition typical in a AOP glossary of terms:

Weaving
The process of coordinating aspects and non-aspects. In a language like AspectJ, one part of weaving is ensuring that advice executes at the appropriate dynamic join points. Weaving can be done explicitly or implicitly, and can be done at a variety of times ranging from by-hand weaving when code is written, through compile-time, post-compile time and load time, up to runtime.

Yeah, that makes lots more sense now... obvious really, what was I thinking? Thanks for clearing that up for me... ;>)
Roll on, AOP for Dummies.

It seems that Spring concentrates on implementing a single aspect of AOP (pardon the pun), the method interceptor (which implements org.aopalliance.intercept.MethodInterceptor) . Spring advocates the use of full-blown AOP frameworks such as AspectJ to conduct more complex AOP if this becomes necessary.

Spring performs method interception in a way that is analogous to a Servlet filter. You can even specify regular expressions in order to filter which methods to match. There is also something of the Listener/Observer design pattern about method interception, if you assume that the "event" it listens out for is a method call.

It seems you can add AOP enabled method interception in a way that is transparent to the rest of the logic. This seems fine if you are doing something that is not really integral to the primary aims of the code where it makes sense to do things in parallel such as logging, tracing and profiling. I am slightly concerned at the appropriateness of using AOP methods to do things that probably should be part of the natural flow of the program, like transaction support and to some extent caching. Running these aspects in parallel means you can turn them on and off for debugging purposes but because they are running in parallel to the core code it may be more difficult to trace what is actually going on.

In many ways Caching seems an ideal candidate for the AOP approach. It is interesting to see members of the Spring community providing plugin support for several alternate caching mechanisms (such as Memory HashMap, EHCache, OSCache (which is clusterable), SwarmCache and potentially Prevayler). I must admit I found it a little confusing that Spring implements a EHCache factory bean to make EHCache configuration easier and this is completely unconnected with the use of Caching in an AOP context. In an AOP context, what you are essentially caching is the responses to method calls and this *could* easily be subtly different to caching specific content and therefore may not be want you really want.

Spring's BeanFactory enables me to write loosely coupled code and I'm starting to see why this might be a good thing. However, I'm still waiting for the AOP penny to drop, I expect I need a bit more weaving practice.

Friday, December 16, 2005

Derby embedded into Firefox: another guise of browser embedded web server

There is an imminent possibility of being able to embed databases directly into the web browser environment as David Van Couvering has recently demonstrated using Apache Derby.

A short while ago I made a mad suggestion that future browsers should directly integrate web server software (like Apache or Tomcat). Although I didn't expect something like this could be happening so soon, integrating a database is in many ways as good as having integrated web server software. My initial thoughts were partly prompted by thinking about the direction that tools like Google Desktop are taking us. From a certain perspective, although not actually a browser, Konfabulator and Apple's Dashboard are similar JavaScript engine driven concepts.

There are almost endless possibilities for AJAX style applications written directly against local content (be that search engine style or local database storage).

I think it would be great if you could power up your web browser and immediately in a similar way to instant messenging you would have a web server that was online when you were, a true web presence. You could use it to share transient web site content and you'd no longer need to experience the slow end of ADSL, no more ftp or even WebDAV uploads! You could share social bookmarking, todo lists, wikis, blogs, forums, webcams etc. It would almost be like the P2P revolution all over again but for "web" content with much less of the controversy, think Napster or BitTorrent but for personal web content and without the same level of copyright issues provided people agreed to share content freely.

A web browser with some scripting capability, say JavaScript, Python or Perl could mean integration of local services such as format (e.g. XML/RSS/XHTML/CSS) validators and other online services such as accessibility checkers directly into the local browser server installation.

This would not really be a revolution as all these things are possible now, with a little effort, but a standard mechanism for doing so would mean that a wider audience could enjoy these freedoms.

I know people that scoff at the thought of contributing to a Wiki, helping other users on mailing lists, discussion forums or keeping a blog and I expect they would scoff at this suggestion too. I find my activities in these areas to be very enjoyable and rewarding. I would no more shun these than I would accept the stereotype that IT people are boring, I love IT, I feel very fortunate to be around at a time when I am able to enjoy open source software and ideas freely, it regularly excites me and I make no apologies for that.

Wednesday, December 14, 2005

How to use the Middlegen generated iBATIS/DAO/Spring code

If you were following my previous entry, iBATIS, DAO, Spring and Middlegen code generation, you will recall I had used the development version of the Middlegen iBATIS plugin (available from the Middlegen CVS or you can download a version of it here) to generate the iBATIS XML SqlMapping file and the transparent domain objects. I had also extended this plugin by adding additional Velocity template files to additionally produce simple versions of the DAO interface, DAO implementation (using Spring's SqlMapClientTemplate), Facade interface and Facade implementation. So now you have all the config and classes you need to actually get something working. To provide some closure for the previous blog entry this entry will describe the final steps you need to do in order to use the generated code.

You will need a sqlmap-config.xml file, this could probably also be generated. In this simple example with only one table in the database it will only refer to a single SQLMapping file but essentially this file serves to collate the various SQLMapping files together.


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig PUBLIC
"-//iBATIS.com//DTD SQL Map Config 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-config-2.dtd"
>

<sqlMapConfig>
<sqlMap resource="Item.xml"/>
</sqlMapConfig>

With the ApplicationContext.xml we finally see where Spring does its magic. Here we define all the beans we need and actually perform the "injections" to which the phrase dependency injection actually refers. So we define our datasource, SqlMapClientFactoryBean and inject these into our iBATIS/Spring enabled ItemDao implementation (SqlMapItemDao). In turn our SqlMapItemDao is then injected into our Facade implementation.


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>org.apache.derby.jdbc.EmbeddedDriver</value>
</property>
<property name="url">
<value>jdbc:derby:build/derby/simpledb</value>
</property>
</bean>

<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation"><value>sqlmap-config.xml</value></property>
</bean>

<bean id="itemDAO" class="mypackage.sqlmapdao.SqlMapItemDao">
<property name="dataSource"><ref local="dataSource"/></property>
<property name="sqlMapClient"><ref local="sqlMapClient"/></property>
</bean>

<bean id="facade" class="mypackage.domain.logic.FacadeImpl">
<property name="itemDao"><ref local="itemDAO"/></property>
</bean>

</beans>

My first steps with Spring were following David Caruana's Spring Start - "Where do I Start?" For Developers. This is a getting started guide and tutorial with a collection of concise codeexamples that step you through the basic Spring Framework capabilities.

Modifiying one of David's examples to work with my generated code I get the following Main.java. Essentially this class initialises Spring to use the ApplicationContext.xml configuration file. I can then use the Spring factory to obtain instances of the defined beans. This class shows how I can create an instance of my domain object and then pass it to and from the datasource using the facade I have established. Notice how there is no need to import the implementation packages as the actual implementation classes have already been defined in the ApplicationContext.xml file. Granted I still have to do a little exception handling to help maintain referential integrity (so that I don't try and add mutliple Items with the same primary key etc.) but all in all this is very simple and it feels like I am at last doing DAO right!


import mypackage.domain.Item;
import mypackage.domain.logic.Facade;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class Main {

public static void main(String[] args)
throws Exception {
// Manually create the Spring Bean Factory
// Note: The factory is driven by the Bean definitions held in ApplicationContext
// Note: There are also other implementations of Resource and Factory, but
// the following combination work well for standalone apps.

ClassPathResource res = new ClassPathResource("ApplicationContext.xml");
XmlBeanFactory factory = new XmlBeanFactory(res);

{
Facade facade = (Facade) factory.getBean("facade");
Item item = new Item();
item.setItemId("item1");
facade.insertItem(item);
Item item2 = facade.getItem("item1");
System.out.println(item2.getItemId());
facade.deleteItem(item);
}

System.out.println("Done");
}

}

Following my iBATIS/Middlegen blog entry, Olivier Ziller brought my attention to an alternative way of generating iBATIS and DAO code using iBATIS Abator. After a preliminary look at Abator I have come to the conclusion that I would still prefer to use Middlegen. I found that it was quite easy to modify the generated code that Middlegen produces by simply editing Velocity template files. However, it is great to know that there are alternative tools out there covering the same ground as it adds further weight to my growing belief that this is the right way to go.

Monday, December 12, 2005

Wizards, Warlocks, Sorcerers and Mages

Over the last couple of weeks I have been writing a multi-page wizard application with a database backend. This has been a learning opportunity for me to look into technologies like Spring and iBATIS to see what they could offer me in this and future endeavours. The next few blog entries will discuss what I have learned so far about Wizards, Spring and finally iBATIS. Firstly a very quick look at the Wizard solutions I found and eventually discarded.

I wanted to write a simple multi-page wizard and decided to see what was available to make my life easier. There is a subtle difference between a web wizard and full workflow. I found that solutions that were designed for proper workflow that include support for state, events, versioning and resource management were too heavyweight for a simple web wizard application.

Struts Flow

Struts flow uses JSON to define the flow between web pages. On this occasion I didn't like the idea of having to define functionality in server side JavaScript. I decided against this approach because I want a simple solution and I want my colleagues to understand it. My colleagues are happy enough for me to wax lyrical about the pleasures of AJAX, BSF, Rhino, E4X etc. as long as they don't have to use it.

EasyWizard

I then looked at using EasyWizard (See also these articles [1], [2]). I liked the basic approach. I saw merit in the fact you can test the state transition in isolation. However, I didn't like the idea of hard coding the flow into Java classes something about this just felt wrong.

Spring Web Flow

I looked at Spring Web Flow, I liked the idea of being able to define the flow in a separate XML file. Although it seemed you couldn't easily get the same flexibility into the flows as you could with EasyWizard. It was promising but still not the simple solution I was hoping to find.

Spring's AbstractWizardFormController

Spring has a built in mechanism called AbstractWizardFormController. I found one very simple example of its usage, I couldn't find any further examples or documentation so I abandoned using it.

Decision

My final decision was not to use any special wizard framework. I wanted to keep it simple and none of the above solutions were that simple or for my needs justified the extra effort to seem worthwhile. It seemed simpler to me to implement my wizard in Struts.

Spring: How to use it without understanding IoC

Subliminally I have been drawn towards looking at Spring. The attraction has reached critical mass and I have finally succumbed. It is not surprising that I should want to look at Spring as I have been constantly drip fed snippets about how magical Spring is in the many disparate Java related articles that I have been browsing through over the last few months.

I've heard much hype about Spring and was hoping to find a breathtaking and spectacular innovation, I didn't find exactly what I expected. Some of the stuff I found looked to be very useful, other bits simply left me bewildered.

Spring at its essence consists of two core parts, BeanFactory and Aspect Oriented Programming (AOP). From what I can tell the most widely used part is the BeanFactory. The only AOP examples I've seen seem to concentrate on how logging could be transparently integrated into Spring applications, I'm certain this is selling AOP short but jumping to Aspect oriented programming is not a paradigm shift I am comfortable about making at the moment.

There is something of a paradigm shift required to understand the principles behind the BeanFactory. Almost every Spring tutorial I have read will start with attempting to explain Inversion of Control (IoC) (aka "The Hollywood Principle" aka "don't call us, we call you" aka "Dependency Injection" [coined by Martin Fowler]). I tend to find that this has the immediate effect of sending me running for the hills but take heart as I have found that I have so far managed to successfully use Spring without actually understanding this particular concept fully. I suppose I am saying don't let the "IoC" explanations prevent you from using Spring!

There is a rumour going about that Spring frees you from writing web specific code, there looks to be some truth to this argument but I have certainly seen plenty of familiar and reassuring web specific stuff inside Spring.

It seems to me that Spring is more of a toolbox rather than a framework. I don't want to get into a semantic argument about what a framework is or isn't but to my mind Spring seems to be less about providing structure and more about providing tools. Spring interfaces well to existing technologies with which you may already be very familiar for example: caching (EHCache), scheduling (Quartz), MVC (Struts, JSF) and O/RM (Hibernate, iBATIS, Toplink). As you might expect from a general toolbox that deals with Beans there are also many other generically useful features that in places bare more than a passing resemblance to Bean and web related offerings from Jakarta Commons and elsewhere.

Spring and Struts

An "optional" component of Spring is its very own web based MVC architecture framework. Instead of writing Controllers, Struts Actions and ActionForms in the Spring MVC architecture everything is a bean. I'm not a MVC purist and I'm sure that there is theoretical merit in this, it is probably closer to true MVC etc.etc. I don't feel comfortable about moving to using Spring MVC as yet although this may change as I learn more about it and see more examples. The thing I like about Struts (and I expect JSF is similar) is the rigid structure it brings to a web applications. Since Spring removes some of these rules I would worry that you could lose some of the beneficial structure. I like the fact that I can hand my Struts application to a colleague with some Struts experience and they pretty much know what to expect without needing to reverse engineer anything or make a careful study of any of my configuration files.

It is also stated that Spring is not prescriptive about what technologies you should use. The Spring community are happy to talk to you even if you are sticking with Struts or JSF or whatever for your MVC implementation. Now you might see what I mean about Spring being more like a toolbox than a framework? There is inherent freedom of choice when using Spring, it provides some very useful tools, used with care it can create fantasically elegant solutions but it does nothing to prevent you from creating bad solutions.

Spring MVC has no apparent Dynabean support, granted real concrete beans aren't difficult to generate if you can find the right options in your IDE. Netbeans carefully hides it getter/setter generation behind a right click on the variable you'd like getter/setters for, click on "Refactor" and then choose to "Encapsulate Fields", obvious really!!!

Spring has a SpringBindingActionForm that looks like it could be used in a DynaActionForm like way but I could find no example documentation beyond the API itself about this class.

What I want to use Spring for

Spring contains some cool looking features but it seems that in several places you are hard pressed to find any example code or tutorials about them. I thought it might be safer to stick with the well documented and hopefully well worn and tested parts of Spring. After having briefly looked at Spring's JDBCTemplate and the other Spring O/RM interfaces to Hibernate, iBATIS, Toplink etc I decided that I wanted to use Spring in my Data Access Object (DAO) layer. I am currently more interested in getting the DAO architecture right (for once) rather than the actual technologies involved. At first glance it seemed to me that Spring would be a very useful and simple DAO implementation technology. I have also seen that Spring contains support for Oracle's perculiar BLOBs and CLOBs implementation which could be very useful for one of my other projects.

Integrating Struts and Spring

Having seen that is quite acceptable to use Struts with Spring I started investigating the various approaches of integrating the two. The first article I read about integrating Struts and Spring, Get a better handle on Struts actions, with Spring, sent me off in what I now consider to be completely the wrong direction.

This article talks about three approaches to incorporating access to Spring beans into Struts Actions. All very impressive but something doesn't feel right to me. I have decided to use Spring in the DAO layer and I feel that unless I start using Spring in some other way it should be confined to the DAO layer therefore I don't need a Spring bean aware Struts Action. After some research I had decided my Struts Action should communicate with my DAO layer via a façade. The DAO implementation may well be using Spring but my Struts Action does not need to know that.

iBATIS, DAO, Spring and Middlegen code generation

I've previously written a small del.icio.us clone using Hibernate where some of the code was generated using Middlegen. I like the Hibernate approach but it sometimes feels like a heavyweight approach for a simple application (e.g. sledgehammer to crack a walnut).

I have looked at using Spring and the JDBCTemplate looks like a nice way to handle JDBC access without the need to write all that tedious connection code and exception handling stuff. However, unless I go to great effort I'd probably end up with SQL hard coded in my Java classes and I'd need to do all the resultset to object mapping by hand.

I discovered iBATIS recently almost by accident. iBATIS used to be a commercial product but has now been donated to the Apache Foundation. iBATIS is an O/RM-like approach. Clinton Begin, iBATIS creator, says that "iBATIS is not an O/RM. It does not bind classes to tables, nor does is it limited to OO languages and/or relational databases" and elsewhere iBATIS has been described as a convenience framework for JDBC. iBATIS does not offer some of the benefits that Hibernate does (database independence etc) but on the plus side it is very simple to use and even more so if you choose to use Spring's SqlMapClientTemplate.

I came across iBATIS as it was one of the technologies included as an example Jetspeed2 Portlet. iBATIS distribute JPetstore as an example of using Struts, DAO layer and iBATIS together. The Jetspeed2 version of the application uses the Struts bridge to convert the application into a portlet. The idea behind iBATIS is that all your SQL is kept in an external XML SQLMapping file. iBATIS then maps the returned result into a domain object.

Spring includes support for iBATIS interaction. I spent a little time studying the iBATIS JPetstore example and a version of this which actually uses Spring is further explored in Bruce Tate and Justin Gehtland's book Better, Faster, Lighter Java (excerpts of which can be found on the OnJava web site [Demonstrating Spring's Finesse, Persistence in Spring]).

There is a Perl script which can be used to generate java-beans sources and sql-map config files generator. There is now also some iBATIS support inside Middlegen tool for the generation of iBATIS SQLMapping XML files and associated domain object POJOs. Looking at the DAO approach used in Better, Faster, Lighter Java and similarly using Spring's iBATIS support it seemed very possible to me that I could extend the existing iBATIS Middlegen Plugin so that it would generate the required DAO classes to implement the architecture shown in the diagram below.

The default iBATIS Middlegen plugin generates the CRUD actions needed for the SQL mapping and creates the definition of each domain object. It was relatively straight forward to modify these basic examples to create DAO interfaces, DAO implementation (using Spring SQLMapClientTemplates) and also a Façade interface / implementation.

To do this I had to learn a to use the Velocity Templating Language (VTL) to extend Middlegen code but since I have some shell scripting and XSL experience this is not that daunting a task.

Using the default Middlegen iBATIS plugin you can create an SQL Mapping file and domain object POJO class. For this example I have created a single Table called ITEM with one column containing an ITEM_ID. The generated iBATIS XML SQLMapping file is shown below. Notice how this contains the full range of CRUD operations.


<?xml version='1.0'?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-2.dtd"
>

<!-- WARNING: This is an autogenerated file -->

<sqlMap>
<typeAlias alias="Item" type="mypackage.domain.Item"/>
<!--
<cacheModel id="$table.destinationClassName-cache" type="MEMORY">
<flushInterval hours="24"/>
<flushOnExecute statement="insertItem"/>
<flushOnExecute statement="updateItem"/>
<flushOnExecute statement="deleteItem"/>
<property name="reference-type" value="WEAK" />
</cacheModel>
-->

<resultMap class="Item" id="Item-result" >
<result
property="itemId"
javaType="java.lang.String"
column="ITEM_ID"
/>
</resultMap>

<select id="getItem"
resultClass="Item"
parameterClass="Item"
resultMap="Item-result" >
<![CDATA[
select
ITEM_ID
from
ITEM
where
ITEM_ID = #itemId#

]]>
</select>

<update id="updateItem"
parameterClass="Item" >
<![CDATA[
update
ITEM
set

where
ITEM_ID = #itemId#
]]>
</update>

<insert id="insertItem"
parameterClass="Item" >
<![CDATA[
insert into ITEM
(ITEM_ID )
values
(#itemId# )
]]
>
</insert>

<delete id="deleteItem" parameterClass="Item" >
<![CDATA[
delete from ITEM where ITEM_ID = #itemId#
]]>
</delete>

</sqlMap>

The default Middlegen iBATIS plugin will generate corresponding transparent domain object class (business objects), one per table. The domain should capture the relationships between the various system entities much as an Entity Relationship Diagram does and this is why we can generate this from the database directly. The generated classes are a "bare" platform into which you should expect to add more sophisticated behaviours. These really should contain behaviour as you'll probably recall from object oriented programming first principles a class should contain data and methods. Obviously the precise behaviour cannot be generically generated as it is likely to be domain object specific. If you do not add additional behaviour at this point you may be guilty of using an Anemic Domain Model.


package mypackage.domain;

import java.io.Serializable;
import java.sql.Timestamp;
import java.math.BigDecimal;
import org.apache.commons.lang.builder.HashCodeBuilder;

/**
* @author <a href="http://boss.bekk.no/boss/middlegen/">Middlegen</a>
*
*/

public class Item implements Serializable
{
// fields
/**
* The itemId field
*/

private java.lang.String itemId;

// getters/setters
/**
* Returns the itemId
*
* @return the itemId
*/

public java.lang.String getItemId()
{
return itemId;
}

/**
* Sets the itemId
*
* @param newItemId the new itemId
*/

public void setItemId(java.lang.String newItemId) {
this.itemId = newItemId;
}


/**
* Implementation of equals method.
*/

public boolean equals(Object object)
{
if (this == object)
{
return true;
}
if (!(object instanceof Item))
{
return false;
}
Item other = (Item)object;
return
this.itemId.equals(other.itemId); }

/**
* Implementation of hashCode method that supports the
* equals-hashCode contract.
*/

/*
public int hashCode()
{
return
hashCode(this.itemId); }
*/

/**
* Implementation of hashCode method that supports the
* equals-hashCode contract.
*/

public int hashCode()
{
// TODO generate random number following the contract
HashCodeBuilder builder = new HashCodeBuilder(17,37);
return builder
.append(itemId)
.toHashCode();
}

/**
* Implementation of toString that outputs this object id's
* primary key values.
*/

public String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append("itemId=");
buffer.append(this.itemId);
return buffer.toString();
/*
return
this.itemId; */

}
}

I created Middlegen iBATIS Plugin extensions to generate the next few classes. This is an example of a generated DAO interface class. There will be one DAO interface class per domain object (i.e. one per table).


package mypackage.iface;

import mypackage.domain.Item;

public interface ItemDao
{
public Item getItem( java.lang.String itemId);
public void insertItem(Item item);
public void updateItem(Item item);
public void deleteItem(Item item);

}

This is DAO implementation of the above interface using Spring's SqlMappingClientTemplate, again there will be one of these per domain object (i.e. one per table):


package mypackage.sqlmapdao;

import mypackage.domain.Item;
import mypackage.iface.ItemDao;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;

public class SqlMapItemDao extends SqlMapClientDaoSupport implements ItemDao
{
public Item getItem(java.lang.String itemId){
Item item = new Item();
item.setItemId(itemId);
return (Item) getSqlMapClientTemplate().queryForObject("getItem",item);
}

public void insertItem(Item item) {
getSqlMapClientTemplate().insert("insertItem",item);
}

public void updateItem(Item item){
getSqlMapClientTemplate().update("updateItem",item);
}

public void deleteItem(Item item){
getSqlMapClientTemplate().delete("deleteItem",item);
}

}

In this most simple example the usage of a façade seems fairly pointless. The idea comes into it's own when you start to have more than one table of data represented in your domain. A façade collects all the publicly accessible DAO methods into a single interface. It also serves as an attachment point for other services, such as transaction support.In writing a Struts Action you would query against the façade rather than trying to obtain a DAO method directly.There will be only one instance of the façade layer interface and implementation it will likely contain references to all the DAO interfaces for every publicly accessible domain object.

See Persistence in Spring for more details about why we might want to generate a façade interface and implementation.

Façade interface:


package mypackage.domain.logic;

import mypackage.domain.Item;

public interface Façade
{

public Item getItem( java.lang.String itemId);
public void insertItem(Item item);
public void updateItem(Item item);
public void deleteItem(Item item);

}

Façade implementation:


package mypackage.domain.logic;

import mypackage.iface.ItemDao;
import mypackage.domain.Item;

public class FaçadeImpl implements Façade
{

private ItemDao itemDao;

//-------------------------------------------------------------------------
// Setter methods for dependency injection
//-------------------------------------------------------------------------


public void setItemDao(ItemDao itemDao) {
this.itemDao = itemDao;
}

//-------------------------------------------------------------------------
// Operation methods, implementing the Façade interface
//-------------------------------------------------------------------------



public Item getItem( java.lang.String itemId){
return this.itemDao.getItem(itemId);
}

public void insertItem(Item item){
this.itemDao.insertItem(item);
}

public void updateItem(Item item){
this.itemDao.updateItem(item);
}

public void deleteItem(Item item){
this.itemDao.deleteItem(item);
}

}

As you can see from the above examples, I have now extended the Middlegen iBATIS Plugin to create a simple version of the entire Spring based DAO layer code. I'm currently looking into generating more complex domain relationship behaviour but this has so far only been slightly hampered by my limited VTL scripting skills but it is certainly possible to do this with Middlegen as the Hibernate and EJB plugins produce something similar. I am hoping to better capture one-to-many relationships in the domain model so that I can detect these and generate appropriate SQLMapping and Java code. For example if we added a new domain object called CATEGORY it might contain many ITEMS and could therefore our Category domain object might contain:


private List items;

public List getItems()
{
return items;
}

public void setItems(List items)
{
this.items = items;
}

The following could be generated inside an appropriate XML SQL Mapping file:


<select
id="getItemsByCategoryCode"
parameterClass="java.lang.String"
resultMap="itemMap">
select
item_id,
item_name,
category_code
from
items
where
category_code = #value#;
</select>

* where itemMap is already defined someplace.

The Spring DAO implementation of this could then look something like:


public List findItems(Category category){
getSqlMapClientTemplate().queryForList("getItemsByCategoryCode",category);
}

public void createCategoryWithItems(Category category){
getSqlMapClientTemplate().execute(new SqlMapClientCallback() {
public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
executor.startBatch();
for (Iterator it=category.getItems().iterator(); it.hasNext(); ) {
Item item = (Item) it.next();
executor.insert("insertItem", item);
}
executor.executeBatch();
return null;
}
});
}

Nothing that I have generated so far is especially complicated but it is still nice to be able to generate basic business objects and a working DAO layer without much effort. I'd be happy to share the Velocity templates that I used to create these classes.