20. Integration with enterprise containers

Writing a web application is not just about producing a good layout and a bunch of “cool” pages. We must also integrate our presentation code with enterprise resources like data sources, message queues, business objects, etc…​

The first decade of 2000s has seen the rising of new frameworks (like Spring ) and new specifications (like EJB 3.1 ) aimed to simplify the management of enterprise resources and (among other things) their integration with presentation code.

All these new technologies are based on the concepts of container and dependency injection. Container is the environment where our enterprise resources are created and configured while dependency injection is a pattern implemented by containers to inject into an object the resources it depends on.

Wicket can be easily integrated with enterprise containers using component instantiation listeners. These entities are instances of interface org.apache.wicket.application.IComponentInstantiationListener and can be registered during application’s initialization. IComponentInstantiationListener defines callback method onInstantiation(Component component) which can be used to provide custom instantiation logic for Wicket components.

Wicket distribution and project WicketStuff already provide a set of built-in listeners to integrate our applications with EJB 3.1 compliant containers (like JBoss Seam) or with some of the most popular enterprise frameworks like Guice or Spring.

In this chapter we will see two basic examples of injecting a container-defined object into a page using first an implementation of the EJB 3.1 specifications (project OpenEJB ) and then using Spring.

20.1. Integrating Wicket with EJB

WicketStuff provides a module called wicketstuff-javaee-inject that contains component instantiation listener JavaEEComponentInjector. If we register this listener in our application we can use standard EJB annotations to inject dependencies into our Wicket components.

To register a component instantiation listener in Wicket we must use Application‘s method getComponentInstantiationListeners which returns a typed collection of IComponentInstantiationListeners.

The following initialization code is taken from project EjbInjectionExample:

  1. public class WicketApplication extends WebApplication
  2. {
  3. //Constructor...
  4. @Override
  5. public void init()
  6. {
  7. super.init();
  8. getComponentInstantiationListeners().add(new JavaEEComponentInjector(this));
  9. }
  10. }

In this example the object that we want to inject is a simple class containing a greeting message:

  1. @ManagedBean
  2. public class EnterpriseMessage {
  3. public String message = "Welcome to the EJB world!";
  4. }

Please note that we have used annotation ManagedBean to decorate our object. Now to inject it into the home page we must add a field of type EnterpriseMessage and annotate it with annotation EJB:

  1. public class HomePage extends WebPage {
  2. @EJB
  3. private EnterpriseMessage enterpriseMessage;
  4. //getter and setter for enterpriseMessage...
  5. public HomePage(final PageParameters parameters) {
  6. super(parameters);
  7. add(new Label("message", enterpriseMessage.message));
  8. }
  9. }

That is all. We can point the browser to the home page of the project and see the greeting message injected into the page:

EjbInjectionExample

20.2. Integrating Wicket with Spring

If we need to inject dependencies with Spring we can use listener org.apache.wicket.spring.injection.annot.SpringComponentInjector provided by module wicket-spring.

For the sake of simplicity in the example project SpringInjectionExample we have used Spring class AnnotationConfigApplicationContext to avoid any XML file and create a Spring context directly from code:

  1. public class WicketApplication extends WebApplication
  2. {
  3. //Constructor...
  4. @Override
  5. public void init()
  6. {
  7. super.init();
  8. AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
  9. //Scan package for annotated beans
  10. ctx.scan("org.wicketTutorial.ejbBean");
  11. ctx.refresh();
  12. getComponentInstantiationListeners().add(new SpringComponentInjector(this, ctx));
  13. }
  14. }

As we can see in the code above, the constructor of SpringComponentInjector takes in input also an instance of Spring context.

The injected object is the same used in the previous project EjbInjectionExample, it differs only for the greeting message:

  1. @ManagedBean
  2. public class EnterpriseMessage {
  3. public String message = "Welcome to the Spring world!";
  4. }

In the home page of the project the object is injected using Wicket annotation SpringBean:

  1. public class HomePage extends WebPage {
  2. @SpringBean
  3. private EnterpriseMessage enterpriseMessage;
  4. //getter and setter for enterpriseMessage...
  5. public HomePage(final PageParameters parameters) {
  6. super(parameters);
  7. add(new Label("message", enterpriseMessage.message));
  8. }
  9. }

By default SpringBean searches into Spring context for a bean having the same type of the annotated field. If we want we can specify also the name of the bean to use as injected object and we can declare if the dependency is required or not. By default dependencies are required and if they can not be resolved to a compatible bean, Wicket will throw an IllegalStateException:

  1. //set the dependency as not required, i.e the field can be left null
  2. @SpringBean(name="anotherName", required=false)
  3. private EnterpriseMessage enterpriseMessage;

20.3. JSR-330 annotations

Spring (and Guice) users can use standard JSR-330 annotations to wire their dependencies. This will make their code more interoperable with other containers that support this standard:

  1. //inject a bean specifying its name with JSR-330 annotations
  2. @Inject
  3. @Named("anotherName")
  4. private EnterpriseMessage enterpriseMessage;

20.4. Summary

In this chapter we have seen how to integrate Wicket applications with Spring and with an EJB container. Module wicket-examples contains also an example of integration with Guice (see application class org.apache.wicket.examples.guice.GuiceApplication).