Archive

Archive for September, 2009

Spring can inject Servlets too!

September 28th, 2009 1 comment

In this article, I will show you that Spring dependency injection mechanism is not restricted solely to Spring-managed beans, that is Spring can inject its beans in objects created by the new keywords, servlets instantiated in the servlet container, and pretty anything you like. Spring classical mode is to be an object factory. That is, Spring creates anything in your application, using the provided constructor. Yet, some of the objects you use are outer Spring’s perimeter. Two simple examples:

  • servlets are instantiated by the servlet container. As such, they cannot be injected out-of-the-box
  • some business objects are not parameterized in Spring but rather created by your own code with the new keyword

Both these examples show you can’t delegate to Spring every object instantiation.

There was a time when I foolishly thought Spring was a closed container. Either your beans were managed by Spring, or they didn’t: if they were, you could inject them with other Spring-managed beans. If they weren’t, tough luck! Well, this is dead wrong. Spring can inject its beans into pretty much anything provided you’re okay to use AOP.

In order to do this, there are only 2 steps to take:

Use AOP

It is done in your Spring configuration file.

<?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"
  xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.0.xsd

http://www.springframework.org/schema/context

	http://www.springframework.org/schema/context/spring-context-2.5.xsd">

  <This does the magic />
  <context:spring-configured />

  <-- These are for classical annotation configuration -->
  <context:annotation-config />
  <context:component-scan base-package="ch.frankel.blog.spring.outcontainer" />

</beans>

You need also configure which aspect engine to use to weave the compiled bytecode. In this cas, it is AspectJ, which is the AOP component used by Spring. Since i’m using Maven as my build tool of choice, this is easily done in my POM. Ant users will have to do it in their build.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    http://maven.apache.org/maven-v4_0_0.xsd">
...
  <properties>
    <spring-version>2.5.6.SEC01</spring-version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${spring-version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>${spring-version}</version>
    </dependency>
    <dependency>
      <groupId>aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.5.4</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>aspectj-maven-plugin</artifactId>
        <configuration>
          <complianceLevel>1.5</complianceLevel>
          <aspectLibraries>
            <aspectLibrary>
              <groupId>org.springframework</groupId>
              <artifactId>spring-aspects</artifactId>
            </aspectLibrary>
          </aspectLibraries>
        </configuration>
        <executions>
          <execution>
            <goals>
              <goal>compile</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Configure which object creation to intercept

This is done with the @org.springframework.beans.factory.annotation.Configurable annotation on your injectable object.

@Configurable
public class DomainObject {

  /** The object to be injected by Spring. */
  private Injectable injectable;

  public Injectable getInjectable() {

    return injectable;
  }

  @Autowired
  public void setInjectable(Injectable injectable) {

    this.injectable = injectable;
  }
}

Now with only these few lines of configuration (no code!), I’m able to inject Spring-managed beans into my domain object. I leave to you to implement the same with regular servlets (which are much harder to display as unit test).

You can find the Maven project used for this article here. The unit test packaged shows the process described above.

To go further:

Tomcat’s Valve, an alternative to Filter

September 11th, 2009 1 comment

Tomcat's logoIn this article, I will show you how to replace filters declared in web.xml with unobtrusive mechanism in Tomcat.

I’m a big friend of Apache Tomcat. In many cases, even enterprise applications can run with a simple JSP – servlet container and Tomcat has passed through all the evolutions of the standards with flying colors. This is not to say that other containers are bad (Jetty for instance, is very good at being embedded), only that I know enough about Tomcat to know it’s stable and bugfixes are regularly available: a condition for using a product in the enterprise. I am always amazed at why so few Tomcat run in production, compared to big fat application servers. Is it because it is too simple? Yet, it can be very powerful, as I will show with the Valve concept.

Designers and architects know about the Intercepting Filter pattern: these filters intercept requests and responses and can be chained. The implementation of this pattern is the javax.servlet.Filter interface available since Servlet v2.3. Let’s take an example: suppose you have to get additional informations in a database (suche as name, ect.) when authentifying with a classical JAAS login. Since your application is not responsible for performing the check, it is impossible to get these infos at the right time. It is very simple when using a filter.

First problem: you do not want your developers to write the database access code with each new application. You create the filter once, put it in the JAR and tell your teams to use this filter in their web.xml once and for all. Now your enterprise evolve and put information relative to people in a LDAP server (not really a bad idea). For newly created applications, you create another filter that access LDAP and use it from now on.

Second problem: what do you do with your applications that use the legacy filter?

  1. You can run a batch that update the web.xml throughout your entire filesystem. Well, for me, that’s too risky… I wouldn’t want to get my production down in one big shot! And if the webapps run in non-exploded mode, it is impossible.
  2. You can still use the database and create a batch that synchronize data from the LDAP server to the database. Not risky at all. And 20 years latter, your information system is a big plate of spaghetti because information is duplicated everywhere. Not very urban.
  3. Finally, you can rely on our Tomcat friend from the beginning, remove the filter from applications at all and put a specific filter called a valve in Tomcat itself. A big disadvantage is that you now are coupled to Tomcat. This is not as bad as it sounds since the code is so isolated it can safely be migrated to another application server API real quick.

I suppose mad dogs would go with option 1 and managers that change every 2 years would go with option 2. Of course, from my clearly subjective presentation of the solutions, you can guess i would go with option 3.

“Valve is a request processing component associated with a particular Container. A series of Valves are generally associated with each other into a Pipeline.”

From Tomcat’s Javadoc

A valve is designed with a very generic interface org.apache.catalina.Valve. Tomcat also provides an abstract class org.apache.catalina.valves.ValveBase that can be safely extended. The main method of the latter is the invoke() method where you can access both request and response. Don’t forget to call the next valve in it or, like in filters, the chaining will stop.

From this point, you are free to do as you choose: access the LDAP server, put a cookie, log performances, etc.

You can find the Maven sources for 2 very simple examples here.

To go further:

Please note that the links point to the latest v6.0 version but the concepts exposed above are available in v5.5 and v4.1.

Categories: JEE Tags: , ,