Tuesday, March 17, 2009

Wicket Patterns and Pitfalls #2

This is the second episode in a series of articles (see
here for the first article) about common patterns and pitfalls when using Wicket (http://wicket.apache.org). Most of these patterns apply only when using Wicket in conjunction with Spring and Hibernate and these might be very specific, but others are more general. This article illustrates how Wicket's SpringBean-Annotation can lead to subtle problems.

Be Aware of Spring Bean Proxies


This article shows a Hibernate example where Wicket's SpringBean-Dependency-Injection can have subtle side effects, but it can also have side effects in many other scenarios.

Environment: Wicket, Spring
Example Environment: Wicket, Spring, Hibernate, OpenSessionInView


The Example
When using Wicket in a Spring container the most common way to use Spring's dependency injection is to annotate fields to be injected with the @SpringBean annotation. As a simple example let's take a Hibernate entity Person ...

@Entity
public class Person {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String lastName;
private String firstName;
...
}

... and a page that displays the details of a person:

public class PersonPage extends WebPage {
public PersonPage(Long personId) {
Person person = getPerson(personId);
add(new Label("firstName",
new PropertyModel(person, "firstName")));
add(new Label("lastName",
new PropertyModel(person, "lastName")));
}
...
}

For the moment let's don't mind using an inappropriate Model for the person entity (we could use a LoadableDetachableModel instead). Now assume that we have configured an OpenSessionInViewFilter that cares about opening a Hibernate session at the beginning of a request and closing it after rendering the response on our behalf. In this case, one way to implement getPerson(personId) would be to use the recommended way of calling SessionFactoryUtils.getSession(sessionFactory, allowCreate) to get a Hibernate session and call get(personId) on it. We'll let Wicket inject a SessionFactory by @SpringBean for that purpose:

@SpringBean
private SessionFactory sessionFactory;

private Person getPerson(Long personId) {
return (Person) SessionFactoryUtils
.getSession(sessionFactory, true)
.get(Person.class, personId);
}

The Problem
As we know that the OpenSessionInViewFilter opened a session on our behalf, we can be sure that the call to SessionFactoryUtils.getSession() returns that session. But this is not the case and we won't recognize it immediately! The code works well at first look and the person will be displayed. So what's wrong with this code then?

In order to open a Hibernate session the OpenSessionInViewFilter pulls the session factory out of the Spring application context, then opens a session on it and basically puts it into a Map of registered open sessions which is held in a ThreadLocal. The session factory instance is used as the key for that map. The other way round, SessionFactoryUtils.getSession(sessionFactory, allowCreate) looks up a session in the same map with the sessionFactory provided to getSession(sessionFactory, allowCreate) as the key. So in this map the session, which was opened by the OpenSessionInView before, should obviously be found, because the OSIF has put it there under the same key, see the following figure.



What breaks this in the case above is that the sessionFactory object, that was injected into the page, is really a proxy of the sessionFactory.* The OSIF on the other hand pulled the sessionFactory directly from the application context, which is not a proxy. So consequently we tried to lookup the session opened by the OSIF in the map with an instance of a proxy of the sessionFactory as the key instead of the real sessionFactory. As these objects are not equal, the session opened by the OSIF is not found, see figure.


* Wicket injects proxies of Spring Beans instead of the beans themselves, because these would get serialized as parts of Wicket components and along with these beans the whole application context might get serialized.


The Consequences
Primarily this article is just aimed at showing that one should be aware of Wicket's @SpringBean injection. But just out of curiosity, let's have a deeper look at the consequences in this particular Hibernate scenario.

At first look the code just works fine. But what really happens in this example is that a new Hibernate session is created, because we called getSession(sessionFactory, allowCreate) with true as second argument. We could just don't care that a new session is opened, but actually this session is not closed after the request. The OSIF only closes sessions it opened itself, so our manually opened session just stays open (forever). We could turn on Hibernate statistics to see that each request adds one more open session, which is something you really wouldn't want.

What happens if we call SessionFactoryUtils.getSession(sessionFactory, false) (false as second argument) telling SessionFactoryUtils not to open a new session if none exists already? In this case an exception is thrown, telling us that no open session is available, which is quite healthier than silently opening more and more new sessions, which aren't closed afterwards. And after reading this article you even won't have to scratch your head why the session opened by the OSIF is not found and an exception is thrown.

The Solution
Actually, I think the example above is not quite common, as in most cases one would probably not call SessionFactoryUtils from a Wicket component directly. Instead I'd suggest to call a DAO method or another Spring Bean to load the person. These objects could be injected using @SpringBean. The fact, that these are really proxies of the Spring Beans as well does not matter in this case. It's just important, that these will have access to the session factory directly instead of through a proxy.

To close this article, I'd like to mention a kind of funny side effect of the example above. The nice (not really) thing about it is, that one wouldn't even get LazyInitializationExceptions accessing the person on post backs, because the session that loaded the person is not closed, so the person instance is not detached. And that even without using a LoadableDetachableModel ;-).


Stay tuned. More posts are coming soon. Leave a comment!

Wednesday, March 11, 2009

Wicket Patterns and Pitfalls #1

This is the first article in a series of articles about common patterns and pitfalls when using Wicket (http://wicket.apache.org). Most of these patterns apply only when using Wicket in conjunction with Spring and Hibernate and some might be very specific, but others apply for more general cases.


Hibernate IDataProvider and LoadableDetachableModel



Environment: Wicket, Hibernate, Spring, (OpenSessionInView)

Wicket and the HttpSession
When Wicket processes a request to a page, the page including the hierarchy of components and models that make up the page is constructed. Then the page including all its components and models is put into the PageMap, which in turn is put into the Wicket session, which is put into the HttpSession (it is actually put into a SessionStore, but basically it's put into the HttpSession by default). As the HttpSession is a critical resource, care has to be taken of the size of the page. Especially the size of the models, that are used by the components, can be of critical size (imagine huge amounts of table data). For this case, Wicket provides a LoadableDetachableModel - a model that holds a reference to the model object in a transient field, which is set to null after the request, so the model object is not put into the session. When the model object is needed/attached again later, LoadableDetachableModel updates the reference to its model object.

The following sections show a way to implement LoadableDetachableModel in a Spring/Hibernate environment. Along with this, an implementation of IDataProvider is presented.

The Example
Lets take, for instance, a table that displays a list of Person objects. Here's the Person class as a Hibernate entity. DomainObject is an interface for all the domain classes, which provides a method getId(), which returns the Hibernate id of the entity.

@Entity
public class Person implements DomainObject {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String lastName;
private String firstName;
...
}

The page that displays the persons uses a DataTable:

public PersonListPage() {
IDataProvider personDataProvider = ...
List<IColumn> columns = new ArrayList<IColumn>();
list.add(new PersonNameColumn());
... // more columns
add(new DataTable("table", columns.toArray(
new IColumn[0]), personDataProvider, 20));
}

DataTable requires an IDataProvider, which delivers the data. Lets first have a look at how to implement this in a reusable way.

A generic IDataProvider implementation
The following implementation of an IDataProvider assumes the existence of a generic DAO IGenericDao, which provides methods for retrieving lists of different classes of entities from the database (the implementation of this generic DAO is out of the scope of this article).

public class GenericDataProvider<T extends DomainObject>
implements IDataProvider {

@SpringBean
private IGenericDao dao;
private Class<T> entityClass;

public GenericDataProvider(Class<T> entityClass) {
this.entityClass = entityClass;
InjectorHolder.getInjector().inject(this);
}

public Iterator iterator(int first, int count) {
return dao.findAll(entityClass, first, count).iterator();
}

public IModel model(Object object) {
return new GenericLoadableDetachableModel<T>((T) object);
}

public int size() {
return dao.count(entityClass);
}

public void detach() {}
}

The type T of GenericDataProvider specifies the type of domain objects this data provider retrieves. In the example, this would be Person. GenericDataProvider gets access to the generic DAO by dependency injection (@SpringBean). By default, Spring Beans can only be injected into Wicket components (IDataProvider is not a component), but we can inject Spring Beans exactly the same way that Wicket uses for components by calling InjectorHolder.getInjector().inject(this) from the constructor.

There's not much more to say about this IDataProvider implementation, but that it uses a generic LoadableDetachableModel, which is described in the next section. This basic version of a generic LoadableDetachableModel works for all of the domain objects. A more elaborate version could provide ways to restrict the result set by applying additional criteria, but I'll leave this up to you.

A generic LoadableDetachableModel implementation
For the implementation of a Hibernate LoadableDetachableModel we again make use of the generic DAO as well as of the interface DomainObject mentioned above.

public class GenericLoadableDetachableModel<T extends
DomainObject> extends LoadableDetachableModel {

@SpringBean
private IGenericDao dao;
private Class<T> entityClass;
private Long entityId;

public GenericLoadableDetachableModel(T entity) {
super(entity);
entityId = entity.getId();
entityClass = (Class<T>) entity.getClass();
InjectorHolder.getInjector().inject(this);
}

public GenericLoadableDetachableModel(Class<T> entityClass,
Long entityId) {
super();
this.entityClass = entityClass;
this.entityId = entityId;
InjectorHolder.getInjector().inject(this);
}

protected T load() {
return dao.get(clazz, entityId);
}

}

There's nothing special about this code, but this is a LoadableDetachableModel which is applicable to any domain object. It uses the same way to inject Spring Beans as the GenericDataProvider above.

There's one thing, though, to be aware of when the first constructor is used. The entity passed as an argument might be an instance of a Hibernate proxy in some cases. For example, suppose you've retrieved the entity by calling session.load(id) before. In this case Hibernate really returns a proxy instead of the entity itself. When this proxy is passed to the constructor, entity.getClass() will return the proxy class instead of the entity class. But there's a way around this. Lets change the constructor to make it aware of Hibernate proxies:

public GenericLoadableDetachableModel(T entity) {
super(entity);
entityId = entity.getId();

if (entity instanceof HibernateProxy) {
HibernateProxy proxy = (HibernateProxy) entity;
clazz = (Class<T>) proxy.getHibernateLazyInitializer()
.getPersistentClass();
} else {
clazz = (Class<T>) entity.getClass();
}

InjectorHolder.getInjector().inject(this);
}

This code checks for a HibernateProxy and eventually determines the persistentClass, which is what we want. This way the GenericLoadableDetachableModel can even be used with Hibernate proxies.

OpenSessionInView and GenericLoadableDetachableModel
The nice thing about the GenericLoadableDetachableModel is that it is applicable to all of our domain objects in a generic way, and in general LoadableDetachableModels keep the session size small. But in addition, there's another nice side effect when using GenericLoadableDetachableModel in combination with the OpenSessionInView pattern.

To show this, suppose we use GenericLoadableDetachableModel without an OpenSessionInViewFilter/Interceptor. When a component that uses a GenericLoadableDetachableModel is attached along with its model, the load() method of the GenericLoadableDetachableModel is called, which calls the generic DAO. The DAO opens a Hibernate session, retrieves the entity from the database and then closes the session. After that, the entity is detached (in a Hibernate sense) because the session is closed and LazyInitializationExceptions might eventually be thrown when we try to navigate an uninitialized association. Additionally, if we did not use a LoadableDetachableModel (with or without OSIV), but a non-detachable model, the model object would also be detached (Hibernate detached) on postbacks, because the model was put into the session including its model object (the entity).

This changes when we use an OpenSessionInViewFilter, which opens a session at the beginning of a request and closes it at the end of a request (details about the OSIV pattern is out of the scope of this article). This in combination with a LoadableDetachableModel leads to model objects, which are actually never detached (in a Hibernate sense). On the one hand, this is a consequence of the fact that the session is kept open after the call to load(), so that the entity is not detached. On the other hand, this is a consequence of the fact, that model objects are detached in a Wicket sense by the LoadableDetachableModel after the request, so that they will not be put into the Wicket session. So on postbacks the model object is not pulled from the session, but it is retrieved freshly from the database instead, because model.getObject() calls load() on LoadableDetachableModel. So, as a client you will actually never see any detached model objects and, as a result, no more LazyInitializationExceptions.

Note: The OpenSessionInView pattern needs special attention regarding transactions. This will be topic of a subsequent article in this series.


That's it for now. The next article will be about a pitfall using the @SpringBean annotation, so stay tuned.

Wednesday, October 8, 2008

Getting Started With OSGi

starting a new project at work we discussed the use of OSGi. i had read some articles about OSGi before but never got deep into it. but with gaining inside, i'm pretty amazed about OSGi now, as it makes it possible to write modular, flexible and dynamic applications in a way that wasn't possible before.

at work, the new project is a set of different collaborating web application using our usual stack of spring, hibernate and wicket. so we had a look at different platforms that supports this kind of apps, and we found that springsource dm server fitted our needs best. unfortunately some of our customers require us to run the apps on a websphere application server, so we had to drop springsource dm server and with it the whole OSGi solution was dropped. we all weren't happy, as all other solutions were so far behind OSGi.

anyway, i decided to learn more about OSGi for personal interest. currently i'm reading Neil Bartlett's free book OSGi in Practice. There aren't that many sources about OSGi at the moment, but although Neil's book is currently in draft state, it's quite worth a read. Thanks Neil.

Monday, September 15, 2008

sources of information

to stay up to date of what's going on mainly in the java space, different developers have different strategies. in this post i'll describe mine. my strategy consists of two parts. one part is keeping track of news and information coming from different sources, the other part is storing the important bits and pieces of information for personal use.


my primary source of information is reading news and blogs from the internet. i collect these news as feeds (rss or atom) with google reader. currently i have registered about 20 feeds, which i group in the first place by categories as 'daily feeds' and 'none daily feeds'. i try to read all the incoming 'daily feeds' every day, while i read the others when i get the time to. some of my favorite daily feeds are from dzone, theserverside, javalobby, slashdot, ibm developerworks and sun developer center. many of these news i mainly skip through - probably about 80 percent. of the remaining 20% there are sometimes some items which are especially interesting to me. i store these in google reader by marking them with a star. some posts on special topics (currently for example javafx or scala) i store in separate categories.


another information store is my google mail account. whenever i find any special articles outside of my news feeds or other documents/tutorials (e.g. in pdf format) i store links to these or the documents themselves in my google mail account. sometimes i also create link collections on a special topic. i store a set of keywords with each mail. currently i'm also trying out a personal wiki(mediawiki) for a better structuring of these collected information than it is possible with emails.


another source of information is, of course, books. i don't read books on a regular basis, but i read about three or four books a year. the latest were 'effective java', 'hibernate in action' and 'pojos in action'.


last but not least i listen to the java posse podcast, which is really great.


so all inall this might seem a lot of information. but actually i have a lot of time driving to work and home again by train.

Tuesday, September 2, 2008

Maven Integration Tests with Jetty and Selenium

in this post i'll describe how to configure maven to run integration tests with selenium and the maven-jetty-plugin. although this solution works, there surely are some points where it could be optimized (leave comments!). this solution assumes you have a maven-project configured for a web-application that can be run with the jetty plugin for maven. also, i assume that you have selenium/junit tests set up.

overview
this solution works in the following way:

  1. create two maven modules: one for the webapp, one for the integration tests

  2. install the war-file of the webapp to your maven repository

  3. in the integration test project set up the selenium/junit tests

  4. configure the surefire plugin to run the tests only in the integration-test phase

  5. use the maven-dependency plugin to download and unpack the war-file to the target directory of the integration-test project

  6. run the unpacked webapp with the jetty plugin

  7. start the selenium server with the selenium plugin

  8. run the integration tests



the details



set up the multi-module project

first of all, make your maven project a multi-module project in order to run the integration tests in a separate module apart from you ordinary junit tests. so you'll have three projects: a webapp-parent project, a webapp (war) project and a webapp-integration-tests (jar) project. for more information on setting up a multi-module project see the definitive guide to maven. here are excertps of the projects' poms:

webapp-parent pom.xml:

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>de.foo.webapp</groupId>
<artifactId>webapp-parent</artifactId>
<packaging>pom</packaging>
<name>WebApp Parent</name>
<version>1.0</version>
<modules>
<module>../webapp</module>
<module>../webapp-integration-tests</module>
</modules>
...


webapp pom.xml. the webapp-integration-tests is like this but packaging is jar:

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>de.foo.webapp</groupId>
<artifactId>webapp</artifactId>
<packaging>war</packaging>
<name>WebApp</name>
<parent>
<groupId>de.foo.webapp</groupId>
<artifactId>webapp-parent</artifactId>
<version>1.0</version>
</parent>
...


unpack the war file

in most cases the maven jetty plugin is used to run the the project it is configured for as a webapp. in this case we'll configure the jetty plugin in the integration-tests project to run the webapp project's generated war-file. to do so, the web app war has to be installed to your local repository (run mvn install). this war file can be fetched and unpacked in the integration-tests project with the maven dependency plugin:


<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>dependency-maven-plugin</artifactId>
<executions>
<execution>
<id>get war</id>
<phase>generate-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>de.foo.webapp</groupId>
<artifactId>webapp</artifactId>
<version>1.0</version>
<type>war</type>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/webapp/webapp</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
...


set up the jetty plugin

first, tell the jetty plugin to run the unpacked war-file by placing a jetty.xml file in the src/test/resources folder of the integration-tests project which defines the webapp directory. you can use the default jetty.xml and set the webAppDir parameter to point to the target directory:
<Set name="webAppDir">target/webapp</Set>
. then in the pom.xml configure the jetty plugin to run in the pre-integration-test phase.


<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<configuration>
<daemon>true</daemon>
<webApp>target</webApp>
<jettyConfig>target/test-classes/jetty.xml</jettyConfig>
</configuration>
<executions>
<execution>
<id>start jetty server</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run-war</goal>
</goals>
</execution>
</executions>
</plugin>
...


you can try maven integration-test or maven jetty:run-war to see if this works as expected (set the daemon parameter to false before trying this).




set up the selenium plugin

the selenium plugin then starts a selenium server in the pre-integration-test phase, too. keep in mind that the configured maven goals run in the order they were defined in the pom.

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>selenium-maven-plugin</artifactId>
<executions>
<execution>
<phase>pre-integration-test</phase>
<goals>
<goal>start-server</goal>
</goals>
<configuration>
<background>true</background>
</configuration>
</execution>
<execution>
<id>stop selenium server</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop-server</goal>
</goals>
</execution>
</executions>
</plugin>


set up the tests

next, move your integration tests to src/test/java in the integration-tests project. these can be run with the maven surefire plugin. this has to be configured to run the tests only in the integration-test phase.


<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<skipTests>false</skipTests>
</configuration>
</execution>
</executions>
</plugin>


that's it. call maven integration-test to run the tests.

Tuesday, August 12, 2008

effective java

recently i've put my scala sessions aside for a while, because i've had the chance to get the second editition of 'Effective Java' by Josh Bloch into my hands. Although i had read the first edition, the second edition struck me again. it contains some of the items already in the first edition, but also many (about 20 or so) new items, some of them regarding especially the new features of Java 5 and 6.

this book is still great.

won an eclipse t-shirt

for its latest release (ganymede) the eclipse foundation started a contest. they gave away eclipse t-shirts for the first reviews of the new release and i've won one for my post in this blog.

thanks to eclipse. this is my first developer t-shirt.