Monday, January 12, 2015

Injecting EJBs into JAX-RS Resources using CDI

If you've ever tried to inject an EJB into a JAX-RS v1.x resource using the @EJB annotation, you know it doesn't work.  There are some implementations of JAX-RS that have provided this functionality, but it is implementation specific, not necessarily part of the JAX-RS specification.  It can be over come though by using Contexts and Dependency Injection (CDI).  The steps below are the bare minimum for CDI to inject an EJB into a JAX-RS resource running on the WebSphere Liberty profile.  The steps use the project structure I outlined in a previous post that can be found here.

Enabling CDI


The first step is to enable CDI for the JAX-RS and EJB projects.  This can be accomplished by adding a file called beans.xml to both projects in the standard locations.  For JAR projects (the EJB project in this case), the file is added to the META-INF folder.  In an Eclipse Maven project, this is located in src/main/resources.  For the JAX-RS project (or any WAR project) the file goes in to the WEB-INF directory.  In an Eclipse Maven project, this folder can be found in src/main/webapp.  The file can be left empty, but I like to add the basic CDI XML which is:


Annotating the JAX-RS Resource


The next step is to add the CDI @Inject annotation to the JAX-RS resource.  For example, lets assume we have a simple EJB that provides a single method that returns a String that represents a message.  The EJB interface and implementation may look something like this:



The EJB can then be injected into the JAX-RS resource using the @Inject annotation.  Lets assume the JAX-RS resource look like this:


Build and deploy the code to Liberty and at runtime, CDI will retrieve the EJB from JNDI and inject the EJB into the resource after it's created.

Saturday, January 10, 2015

Common Project Structure for WebSphere Liberty using Maven and Eclipse

I find myself creating a lot of Java EE projects that focus on JAX-RS running on WebSphere Liberty.  I've created a common project structure that works well for me and helps me to get new development efforts up and running quickly.  I've documented the initial Eclipse / Maven / Liberty setup in this post and this post.  Below is an overview of the project structure and how to create each sub-project.

Overview


I always start with five basic Maven projects:
  1. project-parent -> This is the parent project that contains the parent Maven pom.xml.  In Eclipse this is a simple Maven project (i.e. using no archetype).
  2. project-ejb -> This is a Maven project that represents the Enterprise Java Bean (EJB) project.  In Eclipse, this project is created using the IBM provided Maven archetype for EJB projects running on the Liberty profile.
  3. project-view -> This is a Maven project that contains the "view" of the Model View Controller (MVC) pattern.  In Eclipse, this project is a simple Maven project (i.e. using no archetype).
  4. project-rest -> This is a Maven project that represents the JAX-RS project.  In Eclipse, this project is also created using the IBM provided Maven archetype for web applications running on the Liberty profile.
  5. project-ear -> This project is a Maven project that represents the Enterprise Archive (EAR).  In Eclipse, this project is an Enterprise Application Project that has been converted to a Maven project.
I replace the word project in the name of each Eclipse project to better reflect the development effort's goal or scope.  I use project here just for demonstration purposes.  For example, if the development effort's goal was to persist user data, I may name the projects user-parent, user-ejb, user-view, user-rest and user-ear.

Why this Structure?


Why do I use this structure?  Why is the EJB project separate from the JAX-RS project?  Wouldn't the EAR project be unnecessary if the EJB, JAX-RS and view projects were combined?   These are good questions.  I've found this structure to be simple but also very adaptable to expanding the scope of the overall development effort.  

For example, if a new requirement calls out the need for web services or message queues for asynchronous processing, I can quickly add a new project to the list above that deals specifically with the implementation of JAX-WS and / or JMS as an additional access point to the business logic.  Since all of the business logic is contained in the EJB project, my components are already separated and I can quickly respond to this requirement.  If the EJBs and JAX-RS code were combined into a single project, then I would be forced to either refactor the project into two projects or add the new logic to the existing project.  Keeping each project focused on a specific aspect of the overall implementation is a cleaner approach in my view.


Step by Step Setup


The rest of this post goes through the step by step setup for each project and how to link each project to the parent project and each other in some cases.  The resulting projects are available in GitHub.  I'm continually tweaking the base projects as I run into issues or new feature become available.  Check GitHub for the most recent version of the file demonstrated below.

project-parent


As stated above, this project is a simple Maven project that contains the parent pom.xml.  This project is used to facilitate a single place to store common Maven configurations are well as providing a Maven reactor build.  To create this project in Eclipse:

  1. Go to New > Project and select Maven > Maven Project from the options provided and click the Next button.


  2. Select the Create a simple project (skip archetype selection) checkbox and click the Next button.


  3. Provide the required Maven parameters in the dialog.  Make sure the Packaging selection is set to pom.


  4. Click the Finish button.
The resulting project will be crest in the Eclipse workspace. I usually delete the src folder since it serves no purpose at the moment, but this is optional.

The next step is to update the pom.xml file in this project.  This pom will contain common build configurations, dependencies and properties as well as a list of modules representing the Maven sub-projects that should be built with this project.  At the bare minimum, this file should look like this (notice the Maven dependency for the Liberty runtime and the Java version settings in the compiler plugin):


Notice the Maven dependency for the Liberty runtime and the Java version settings in the compiler plugin.  These settings will automatically be applied to all of the sub projects linked to this parent.

project-ejb


The next project is the EJB project.  This project is created using an IBM provided Maven archetype for EJB projects running on the Liberty profile.  To create this project:
  1. Go to New > Project and select Maven > Maven Project from the options provided and click the Next button


  2. Click the Next button.


  3. Filter the list of archetypes to just those provided by IBM using the selection box at the top of the dialog.  Select the ejb-jee6-liberty archetype from the list.  Click the Next button.


  4. Provide the required Maven parameters in the dialog.  Click the Finish button.


A new project will be created in your workspace ready for EJB development with a Maven pom geared toward the building and packaging of EJBs.  Some changes are required to the project pom.xml to link to the parent project and remove the redundant configurations.  The EJB project's pom.xml should look like this initially and then can be further customized as development proceeds:


project-view


As stated above, this project is also simple Maven project.  This project will contain the view provided by the JAX-RS project. To create this project in Eclipse:
  1. Go to New > Project and select Maven > Maven Project from the options provided and click the Next button.

  2. Select the Create a simple project (skip archetype selection) checkbox and click the Next button.

  3. Provide the required Maven parameters in the dialog.  Make sure the Packaging selection is set to jar.


  4. Click the Finish button.
A new project will be created in your workspace ready for development.  Some changes are required to the project pom.xml to link to the parent project and remove the redundant configurations.  The project's pom.xml should look like this initially and then can be further customized as development proceeds:


project-rest


The JAX-RS project is also created using an IBM provided Maven archetype.  To create this project:
  1. Go to New > Project and select Maven > Maven Project from the options provided and click the Next button


  2. Click the Next button



  3. Filter the list of archetypes to just those provided by IBM using the selection box at the top of the dialog.  Select the webapp-jee6-liberty archetype from the list.  Click the Next button.




  4. Provide the required Maven data to the dialog.  Click the Finish button.



A new project will be created in your workspace setup in Eclipse for dynamic web development with a Maven pom geared toward the building and packaging of WAR files.  Some changes are required to the project pom.xml to link to the parent parent, remove the redundant configurations, configure the build of a skinny WAR file and link the EJB and view projects as dependencies.  Initially the JAX-RS project's pom.xml should look like this:


project-ear


The final project is the EAR project.  This project is created using the Enterprise Application Project provided by Eclipse and then it is converted to a Maven project using the Maven plugin.
  1. Go to New > Project and select Java JEE > Enterprise Application Project from the options provided. Click the Next button


  2. Provide the project details.  Make sure you choose Liberty for both the Target runtime and Configuration options. Click the Finish button.


  3. Once the project is created and available in the workspace, right click the project and select Configure > Convert to Maven Project.
  4. Provide the required Maven details.  Make sure the Packaging is set to ear.  Click the Finish button.


This process will create a Maven pom.xml for the project that is geared toward building and packaging EAR files.  This pom.xml file needs to be modified to link it to the parent project, remove redundant configurations, include the EJB, JAX-RS and view projects and dependencies.  Initially the resulting pom.xml should look like this:


Clean up


Eclipse might be reporting errors on the projects.  The most common error usually states that the Maven project configuration is out of date.  To fix this, right click on each project and select Maven > Update project...  Choose the project(s) reporting the error in the list at the top of the dialog and then click the OK button.

The other error you might see is from the EJB project reporting that it must contain at least 1 EJB.  This error will disappear once you start development.

Building


The final step is to run a test build.  This can be run from within Eclipse or using the Maven command line tool.  From within Eclipse, right click on the parent project and select Run As... > Maven Build...  This will open a dialog.  For the Maven goals enter clean install and then click the Run button.

From the Maven command line, open a command prompt or terminal window and make sure the current directory is the root folder of the parent project (project-parent in this example).  Execute mvn clean install.

The result of either method should be a successful build.  You should see the Maven Reactor Summary of the bottom of the build report stating that all 5 projects were build successfully