Seasar DI Container with AOP  

Quickstart

Seasar2 is a light weight container for Dependency Injection (DI) operations, and also implements EJB3.

First Step

Let us give this a try. The following objects will be used.

  • Greeting class
    • Returns a greeting string.
  • Greeting Client Class
    • Outputs string obtained from the greeting class to console.
  • Greeting Main Class
    • Startup Class.
Greeting.java

Greeting interface.

package examples.ejb3;

public interface Greeting {

    String greet();
}
GreetingImpl.java

Implementation of the greeting. We can make a stateless session bean using the Stateless annotation.

package examples.ejb3.impl;

import javax.ejb.Stateless;

import examples.ejb3.Greeting;

@Stateless
public class GreetingImpl implements Greeting {

    public String greet() {
        return "Hello World!";
    }
}
GreetingClient.java

Client interface to use the greeting.

package examples.ejb3;

public interface GreetingClient {

    void execute();
}
GreetingClientImpl.java

Client implementation to use the greeting. We can refer the session bean implementing the greeting interface using the EJB annotation.

package examples.ejb3.impl;

import javax.ejb.EJB;
import javax.ejb.Stateless;

import examples.ejb3.Greeting;
import examples.ejb3.GreetingClient;

@Stateless
public class GreetingClientImpl implements GreetingClient {

    @EJB
    private Greeting greeting;
    
    public void execute() {
        System.out.println(greeting.greet());
    }
}
GreetingMain.dicon

Configration file for EJB3. If we define this content from the beginning, it's not necessary to add any information to the configuration file, even if the number of EJB increases. Please refer component auto-registration in the details.

<components>
<include path="ejb3tx.dicon"/>
<component
class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister">
<initMethod name="addClassPattern">
<arg>"examples.ejb3.impl"</arg>
<arg>".*Impl"</arg>
</initMethod>
</component>
</components>
GreetingMain.java

The source code to run Seasar2 EJB3 is as follows. Please refer S2Container creation about SingletonS2ContainerFactory. Please refer DefaultAutoNaming about the naming rule in case we don't specify the name property of @EJB.

package examples.ejb3.main;

import javax.naming.Context;
import javax.naming.InitialContext;

import org.seasar.framework.container.factory.SingletonS2ContainerFactory;

import examples.ejb3.GreetingClient;

public class GreetingMain {

    private static final String PATH = "examples/ejb3/dicon/GreetingMain.dicon";

    public static void main(String[] args) throws Exception {
        SingletonS2ContainerFactory.setConfigPath(PATH);
        SingletonS2ContainerFactory.init();
        try {
            doMain(args);
        } finally {
            SingletonS2ContainerFactory.destroy();
        }
    }

    public static void doMain(String[] args) throws Exception {
        Context ctx = new InitialContext();
        GreetingClient greetingClient = (GreetingClient)
            ctx.lookup("greetingClient");
        greetingClient.execute();
    }
}

The result will be as follows:

DEBUG 2006-03-25 18:38:47,892 [main] Transaction began
Hello World!
DEBUG 2006-03-25 18:38:47,922 [main] Transaction committed

EJB3 Annotation Reference

S2Container supports EJB 3.0 Simplified API. We need Java5 in order to use the EJB3 annotation.

Stateless Annotaion

We can define a stateless session bean using Stateless annnotaion.

Tiger annotation is as follows.

@Stateless(name="xxx")
public class Xxx {
    ...
}

When we don't specify the name property, the implementation class of AutoNaming interface which we use the automatic registration of components will automatically deside the name.

Stateful Annotaion

We can define a stateful session bean using Stateful annnotaion.

Tiger annotation is as follows.

@Stateful(name="xxx")
public class Xxx {
    ...
}

When we don't specify the name property, the implementation class of AutoNaming interface which we use the automatic registration of components will automatically deside the name.

EJB Annotation

The EJB annotation denotes a reference to a session bean. The beanName property references the value of the name property of the Stateful or Stateless annotation. The beanName property allows disambiguation if multiple session beans implement the same interface.

Tiger annotation is as follows.

@EJB
public void setAaa(Aaa aaa) {
    ...
}

@EJB(beanName="bbb2")
public void setBbb(Bbb bbb) {
    ...
}

TransactionManagement Annotation

We can use "Container Management Transaction(CMT)" and "Bean Management Transaction(BMT)" using the TransactionManagement annotation. The default is CMT, therefore we don't need to specify the TransactionManagement annotation using CMT.

Tiger annotation is as follows.

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class Xxx {
    ...
}

TransactionAttribute Annotation

If we use CMT, we can specify transaction attribute for business method using the TransactionAttribute annotation. The default is REQUIRED. If we sepcify the TransactionAttribute annotation for a class, we can specify its annotation for all the business methods of the class. If we sepcify the TransactionAttribute annotation for a method, we can specify its annotation for the business method.

Tiger annotation is as follows.

@Stateless
@TransactionAttribute(TransactionAttributeType.MANDATRY)
public class Xxx {
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void someMethod() {
        ...
    }
}

Interceptors Annotation

We can specify several interceptors for the invocation of business methods and the lifecycle methods using the Interceptors annotation.
We can specify interceptors annotation for class or method.

@Stateless
@Interceptors({foo.bar.HogeInterceptor.class, foo.bar.SomeInterceptor})
public class Xxx {
    ...
    @Interceptors(foo.bar.MethodInterceptor)
    private void hogehoge() {
        ...
    }
}

ExcludeClassInterceptors Annotation

When the ExcludeDefaultInterceptors annotation applied to a business method, it excludes the invocation of default interceptors for that method.

@Stateless
@Interceptors(foo.bar.HogeInterceptor.class)
public class Xxx {
    ...
    @ExcludeClassInterceptos
    @Interceptors(foo.bar.MethodInterceptor)
    private void hogehoge() {
        ...
    }
}

PostConstruct Annotation

We can specify the method invoked after an instance creation and DI using the PostConstruct annotation. We can specify the PostConstruct annotation for a sesssion bean or a method of a interceptor. Lifecycle callback methods defined on a bean class have the following signature: public void <METHOD>()
Lifecycle callback methods defined on an interceptor class have the following signature: public void <METHOD>(InvocationContext)

Tiger annotation is as follows.

@Stateless
@Interceptors(Yyy.class)
public class Xxx {
    ...
    @PostConstruct
    public void initialize() {
        ...
    }
}

public class Yyy {
    ...
    @PostConstruct
    public void initialize(InvocationContext context) {
        ...
    }
}

AroundInvoke Annotation

We can intercept invocations of business method using the AroundInvoke annotation. We can specify AroundInvoke annotation for a session bean and the method of interceptor. The method with the AroundInvoke annotation must be no static, no final, and the type of argument must be javax.interceptor.InvocationContext, and the type of return must be Object. We can specify the AroundInvoke annotation for only one method.

Tiger annotation is as follows.

@Stateless
@Interceptors(Yyy.class)
public class Xxx {
    ...
    @AroundInvoke
    Object invoke(InvocationContext context) throws Exception {
        ...
    }
}

public class Yyy {
    ...
    @AroundInvoke
    private Object invoke(InvocationContext context) throws Exception {
        ...
    }
}