Spring & Restlet Integration: A complete example

[Photo]This morning I started writing a Restlet Application that will, when it is completed, supply a restful api for my web application. The web application is already mostly done (not yet public, however there is a landing page and a few screenshots available at http://rpgtracker.de). The web application is written in Wicket (1.5) and uses Spring (3) for dependency injection and Hibernate as persistence layer. I went to great lengths to make accessing my domain objects in the database easy and remove as much boring boiler-plate as possible. So when writing the rest api, of course I wanted to re-use all the effort that went into creating easy-to-use database access. I also got used to the comforts of dependency injection that Spring provides – especially since in Spring 3 it is all annotation based! I had worked with Restlet (2.1) on a previous project and so it was my go-to implementation for a restful web service.

So much for the bullshit bingo – meant to say basic premise … now on to the real examples, because I did have a bit of trouble stitching it all together and maybe this helps someone out there solve the same problem faster.

Note: you’ll need a bunch of dependencies from spring and restlet. If you use maven, restlet has its own repository, that you’ll need to configure. There are other articles on the web that do a nice job of showing which dependencies you need for restlet and spring. There is also an example for some of the xml configurations on the restlet site, but I only understood this after I finished here.

The web.xml

This file contains the container configuration. I am deploying my Restlet application inside a Tomcat (7) server as a servlet. The web.xml file contains the necessary configuration to do that. In my case it contains the location of the spring configuration for startup initialization, the “open session in view” filter that Spring supplies for easy database access and the servlet configuration for the actual Restlet app.

[code language=”xml”]
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">

<display-name>RpgRestApi</display-name>

<!– initialize context at startup –>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!– provide hibernate session per thread –>
<filter>
<filter-name>opensessioninview</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>opensessioninview</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!– Application class name –>
<context-param>
<param-name>org.restlet.application</param-name>
<!– bean name of your application –>
<param-value>application</param-value>
</context-param>

<!– Restlet adapter –>
<servlet>
<servlet-name>RpgletServlet</servlet-name>
<!– note: this is not the standard restlet servlet. this one looks up the application in the context –>
<servlet-class>org.restlet.ext.servlet.SpringServerServlet</servlet-class>
</servlet>

<!– Catch all requests –>
<servlet-mapping>
<servlet-name>RpgletServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
[/code]

The applicationContext.xml

Spring is famous for its xml configuration files. Well mine is quite short and that is thanks to the third incarnation of Spring which allows for two different types of configurations: annotations and java, both of which I am also using. So here is my minimalist xml configuration:

[code language=”xml”]
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

<context:component-scan base-package="de.delusions" />
<context:annotation-config />
<tx:annotation-driven />
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
</beans>
[/code]

This much is necessary to enable the annotations for both autowiring components and transactions. I am thinking there must be a way to get rid of this file …? Anyone?

The Java Code

Next there is some actual java code necessary. So here comes the tricky part, how to make sure that each instance of my restlet application does have access to the spring context.

[code language=”java”]
@Log4j
@Component("application")
public class RpgletApplication extends Application {

//give some love to project lombok for this nicety:
@Getter
@Setter
private ApplicationContext applicationContext;

@Autowired
private Verifier verifier;

public RpgletApplication() {
//show me a better way to configure logging inside restlet:
System.setProperty("java.util.logging.config.file", "classpath:log4j.properties");
log.debug("application created");
}

@Override
public Restlet createInboundRoot() {
final Router apiRouter = new Router(getContext());
apiRouter.attach("/", RootResource.class);
//I want simple basic auth against the users in my database
final ChallengeAuthenticator guard = new ChallengeAuthenticator(getContext(), ChallengeScheme.HTTP_BASIC, "rpglet auth");
guard.setVerifier(verifier);
guard.setNext(apiRouter);
return guard;
}
}
[/code]

Since we configured the servlet in the web.xml to be the SpringServerServlet (only available in the jee edition!!!) our application can be a component and use auto-wiring because the servlet will look up the application in the spring context instead of keeping creating new instances. This is the solution I kept looking for.

We now have a setup with a very basic application with a single resource attached to the root of my domain. The verifier is a Spring component and voilà we can finally use dependency injection:

[code language=”java”]
@Component("verifier")
@Log4j
public class RpgletVerifier extends LocalVerifier {

@Autowired
private IPersonDao personDao;

@Override
public char[] getLocalSecret(final String idString) {
final Person person = this.personDao.findByEMail(idString);
return person != null ? person.getEncodedPassword().toCharArray() : null;
}
}
[/code]

For completeness here’s the code to my RootResource

[code language=”java”]
public class RootResource extends ServerResource implements IRootResource {

@Override
@Get
public Representation represent() throws ResourceException {
return new StringRepresentation("’This is: " + getApplication().getName() + "’");
}
}
[/code]

You thought you were done? I sure did. Sadly there is something still missing.

Transactions, really?

So now that I finally got dependency injection working, I kept getting this error:

No Hibernate Session bound to thread,
and configuration does not allow creation of non-transactional one here

There is a rather primitive solution to this error. The findByEMail method above was not using the @Transactional annotation. I change the method by adding the annotation:

[code language=”java”]
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public Person findByEMail(final String email) {
try {
return (Person) getSession().createQuery("from Person where email = :email").setParameter("email", email).uniqueResult();
} catch (final NoResultException e) {
return null;
}
}
[/code]

I have no idea why this is necessary – found it at stackoverflow. I find it invasive and highly offensive, but it works. Since this is during basic auth it may turn out that I can stop using transactions in later read requests. It may also be that I can’t. I know for a fact that the open session in view filter is working as supposed, so why do I have to use transactions all of a sudden? I am using the same daos in my wicket application without transactions being necessary for read operations. In this case the transaction remains optional as per the Propagation.SUPPORTRS. Still I don’t like it.

Warning: there are quite a few people out there suggesting to fix this by setting a hibernate property called hibernate.current_session_context_class. Don’t! It opens a whole new can of worms because this effectively disables all Spring transaction management and unless you really want that, it’s not a good idea because the transaction management might just be one of the reasons you wanted to use Spring in the first place?

Using org.restlet.ext.spring

Next there is the Restlet Spring extension to consider. We need to change a few things in the applicationContext.xml to enable use of some of the classes from there:

I am still looking for the right way to do this in java, as I am not a fan of xml configurations:
[code language=”xml”]
<bean id="root" class="org.restlet.ext.spring.SpringRouter">
<property name="attachments">
<map>
<entry key="/{name}">
<bean class="org.restlet.ext.spring.SpringFinder">
<lookup-method name="create" bean="rootResource" />
</bean>
</entry>
</map>
</property>
</bean>
[/code]

So where’s the root resource? I added the @Component to my resource class:

[code language=”java”]
@Component("rootResource")
public class RootResource extends ServerResource implements IRootResource {

@Autowired
private IPersonDao personDao;

@Override
@Get
public Representation represent() throws ResourceException {
final String name = getRequest().getAttributes().get("name").toString();
final Person person = this.personDao.findByName(name);
return new StringRepresentation("’This is: " + person.getEmail() + "’");
}
}
[/code]

So this way I can use dependency injection on my resources which is a very important step because that is where most of the work of my application will be done. I have to add however that I did have to add the @Transactional method yet again, so it is not just an issue of the basic authentication.

Open Issues

@Transactional I am really unhappy that this should be the solution to the Hibernate session issue. There error message suggests that it is a “configuration issue” so I am still hunting for the configuration flag that tells hibernate/spring that all transactions are optional unless I say different.

So this one is also (I was missing the SpringServerServlet, too) fixed after I started using the jee variant of the spring extension instead of the jse one. Here’s the maven dependency you need to use if you experience any problems with that:

[code language=”xml”]
<dependency>
<groupId>org.restlet.jee</groupId>
<artifactId>org.restlet.ext.spring</artifactId>
<version>${restlet.version}</version>
</dependency>
[/code]

Now I am a happy developer 🙂 I am writing a restlet application leveraging full Spring and Hibernate support!

This entry was posted in development, java. Bookmark the permalink.

2 Responses to Spring & Restlet Integration: A complete example

  1. sbaronia says:

    Nice article. Do you have application code which we can have access to?

    • Sonja says:

      Thanks for the feedback, I am always glad, when an article is helpful. I do not have a sample application, I wrote this article based on one of my projects-in-the-works. I cannot give out the code for this publicly. And it takes a long time to put together a sample application.