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>
Comments