Version 11

    Wicket's support for Java EE 6

     

    The Wicket framework supports integration with EJB through the WicketStuff project's Java EE Inject.

     

    It allows you to use these annotations:

     

    @Resource ... //  Check your container's docs for info on what it injects.
    
    @PersistenceContext EntityManager em;  // For JPA.
    
    @Inject ... // CDI injections.
    
    @EJB ...  // Injection of @Stateless, @Stateful, etc. beans from their defined scope.
    

     

    The preferred way to inject EJBs is @Inject.

     

    How to

    First, add this component instantiation listener - it will handle the above annotations for every created page or component:

     

    public class WicketApplication extends WebApplication {        
    
        @Override
        public void init() {
            super.init();
    
            getComponentInstantiationListeners().add(
                   new org.wicketstuff.javaee.injection.JavaEEComponentInjector(this, new ModuleJndiNamingStrategy()));
        }
    }
    

     

    In order to use CDI's @Inject, some more code is necessary - with help of 42lines' Wicket-CDI library:

     

    @Override
    protected void init() {
        getComponentInstantiationListeners().add(new JavaEEComponentInjector(this, new AppJndiNamingStrategy("as7-quickstart-wicket-ear-ejb")));
        super.init();
    
        // Get BeanManager.
        BeanManager bm;
        try {
            bm = (BeanManager) new InitialContext().lookup("java:comp/BeanManager");
        } catch (NamingException e) {
            throw new IllegalStateException("Unable to obtain CDI BeanManager", e);
        }
    
        // Configure CDI, disabling Conversations as we aren't using them
        new CdiConfiguration(bm).setPropagation(NONE).configure(this);
    
        // Mount the InsertContact page at /insert
        mountPage("/insert", InsertContact.class);
    }
    

     

    JNDI naming strategy

    The JavaEEComponentInjector may use various JNDI naming strategies. WicketStuff JavaEE Inject project comes with few implementations of IJndiNamingStrategy, of which these are useful with JBoss AS 7:

     

    getComponentInstantiationListeners().add(new JavaEEComponentInjector(this, new ModuleJndiNamingStrategy()));
    

    Use this if your app only consists of a single WAR.

     

    getComponentInstantiationListeners().add(new JavaEEComponentInjector(this, new AppJndiNamingStrategy("my-module-name")));
    

    Use this if your app is an EAR, Wicket is in bundled WAR, and the EJBs are in JAR outside (next to) the WAR.

     

    getComponentInstantiationListeners().add(new JavaEEComponentInjector(this, new GlobalJndiNamingStrategy("my-module-name")));  // or,
    getComponentInstantiationListeners().add(new JavaEEComponentInjector(this, new GlobalJndiNamingStrategy("my-app-name", "my-module-name")));
    

    Use this to access EJBs in other EAR's than where Wicket application is, or if the JAR with EJB's is deployed as a standalone JAR.

    The strings are, by default, created from EAR and JAR names, like this:

    • my-app-name.ear
      • my-module-name.jar

     

    Injection examples

    Let's create an Stateless EJB with an EntityManager.

    The @PersistenceContext is injected by the container as per your app's WEB-INF/persistence.xml .

    Which means - you can either use container's datasource or your

     

    @Stateless
    public class UserDao {
    
         @PersistenceContext private EntityManager em;
    
         public User getUserById( int id ){
             return em.find(User.class, id);
         }
    }
    

     

    Now, we can use this statefull bean in a Wicket page:

     

    public class UserPage extends WebPage {
    
        @Resource(name="messageOfTheDay") String motd;  // Injected e.g. from web.xml's <env-entry>
    
        @EJB private UserDao userDao;
    
        public UserPage(){
             this.add( new Label("id_motd", this.motd) );
    
             this.add( new Label("id_name", new PropertyModel(this, "name"));
             this.add( new Label("id_email", new PropertyModel(this, "email"));
        }
    }
    

     

    For components, it works the same.

     

    As you can see, adding Java EE functionality to Wicket pages is pretty easy and straightforward - just as you'd expect in Java EE 6.

    What might get a bit difficult are the dependencies.

     

    Dependencies (with Maven)

     

    Of course, you need Wicket:

     

    <!-- Wicket -->
    
    <dependency>
        <groupId>org.apache.wicket</groupId>
        <artifactId>wicket-core</artifactId>
        <version>${wicket.version}</version>
    </dependency>
    <!-- Optional - extensions.
    <dependency>
        <groupId>org.apache.wicket</groupId>
        <artifactId>wicket-extensions</artifactId>
        <version>${wicket.version}</version>
    </dependency>
    -->
    

     

    This is where Wicket + Java EE 6 integration is:

     

    <dependency>
        <groupId>org.wicketstuff</groupId>
        <artifactId>wicketstuff-javaee-inject</artifactId>
        <version>${wicket.version}</version>
    </dependency>
    

     

     

    And the rest is various Java EE 6 API - CDI for @Inject, org.jboss.spec.javax.annotation for @Resource, and jboss-ejb-api_3.1_spec for @Stateless, @Stateful, @EJB, etc.

     

    <!-- CDI API. -->
    <dependency>
        <groupId>javax.enterprise</groupId>
        <artifactId>cdi-api</artifactId>
        <scope>provided</scope>
    </dependency>
    
    <!-- Common Annotations API (JSR-250). -->
    <dependency>
        <groupId>org.jboss.spec.javax.annotation</groupId>
        <artifactId>jboss-annotations-api_1.1_spec</artifactId>
        <scope>provided</scope>
    </dependency>
    
    <!-- EJB API. -->
    <dependency>
        <groupId>org.jboss.spec.javax.ejb</groupId>
        <artifactId>jboss-ejb-api_3.1_spec</artifactId>
        <scope>provided</scope>
    </dependency>
    

     

    Vigilant reader noticed lack of versions. It's better to use a BOM for version management as JBoss will keep it in sync for you - see the comment.

     

    <dependencyManagement>
        <dependencies>
            <!-- Define the version of JBoss' Java EE 6 APIs we want to import.
                Any dependencies from org.jboss.spec will have their version defined by this BOM. -->
            <!-- JBoss distributes a complete set of Java EE 6 APIs including a Bill of Materials (BOM).
                A BOM specifies the versions of a "stack" (or a collection) of artifacts.
                We use this here so that we always get the correct versions of artifacts.
                Here we use the jboss-javaee-6.0 stack (you can read this as the JBoss stack of the Java EE 6 APIs).
                You can actually use this stack with any version of JBoss AS that implements Java EE 6, not just JBoss AS 7. -->
            <dependency>
                <groupId>org.jboss.spec</groupId>
                <artifactId>jboss-javaee-6.0</artifactId>
                <version>3.0.0.Beta1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>