Java EE 6 - Showcase Tutorial

Java EE 6 - Tutorial Introduction

This is a simple showcase tutorial of some of the Java Enterprise 6 technologies to build a Web Application. It uses a lot more stuff than necessary for what we're building, but the purpose is to show you what's available.
This tutorial includes:
  • ejb/entity beans for the DB model
  • ejb/session beans for business logic
  • cdi/managed beans for the MVC/controller
  • jsf2 and facelets for the MVC/view
  • bean validation
  • etc
In this tutorial we're using:
  • Eclipse Galileo (SR2)
  • JBoss Tools 3.1.1 (JBossTools-Update-3.1.1.v201006011046R-H111-GA.zip)
  • JBoss AS 6 M3 (jboss-as-distribution-6.0.0.20100429-M3.zip)
What we are building: A web page to list existing users (fig 1) and 2 other pages to create a user - one to receive the input (fig 2) and another confirm the user creation(fig 3).

fig 1

fig 2

fig 3

Hope you find it useful and please feel free to post your comments, suggestions or any mistakes you find.
You can download the tutorial source here.

Create the project

Now we are going to setup the project.
  1. Open Eclipse and create a "dynamic web project" called "jee6-example"
  2. Configure the application server
    1. Click Window -> show view -> other -> server -> Servers
    2. Go to Servers tab
    3. Right Click on the white screen -> New -> Server
    4. Choose "JBoss AS 6", configure it’s path and click finish
    5. Right click JBoss 6.0 Runtime Server -> Add and Remove
    6. On the "Add and Remove" screen, add the "jee6-example" project to the configured list and select finish
    7. Start the server
  3. Configure the project libraries
    1. Right click on the jee6-example project -> properties -> Java Build Path -> Libraries
    2. Click "Add Library"
    3. Click "Server Runtime" -> then Next
    4. Select "JBoss 6 runtime" -> then click finish
    5. Click Ok
  4. Create a package called "com.example"
  5. Create the project XML descriptors:
    • WebContent/WEB-INF/beans.xml
    • WebContent/WEB-INF/faces-config.xml
    • WebContent/WEB-INF/web.xml
    • WebContent/WEB-INF/classes/META-INF/persistence.xml (create the sub-directories if necessary)
  6. Create the datasource file and place it on the directory <JBOSS_HOME>/server/defaut/deploy/mysql-ds.xml
    In this tutorial, I used MySQL and the datasource is attached.
  7. Put the JDBC driver of your database in the <JBOSS_HOME>/server/defaut/lib directory.

Create the entity (EJB3+Bean validation)

The entity is mapped to a database table with the same name as the entity. The attributes of the class map to table columns.
  1. Create a class named “User” in the “com.example” package with the following code


    @Entity
    public class User implements Serializable {
      @Id
      @GeneratedValue
      private long id;
    
      @NotNull
      @Size(min = 5, max = 100)  		      
      private String fullName;
    
      @NotNull
      @Column(unique = true)
      @Pattern(regexp = ".+@.+\\..+", message = "{constraint.email}")
      private String email;
    
      @NotNull
      @Size(min = 6, max = 10)
      private String password; 		    

    Take a look at the EJB annotations:

    • @Entity – Means this class is to be mapped to a database table with the same name as the class. Every attribute with a getter/setter is mapped to a table column.
    • @Id – Means this is the table primary key attribute
    • @GeneratedValue – The primary key is generated by the database
    • @Column – Allows you to specify column attributes (e.g. column name, uniqueness, etc).

    Now the “Bean Validation” annotations:

    • @NotNull – Specifies a validator that does not allow empty(null) input.
    • @Size – Specifies a validator for the minimum/maximum size of the input of the attribute.
    • @Pattern – Validates the input against a regular expression. In the email attribute an error message is also specified if validation fails.
    Validation is done when a record is inserted in the database and when a form is submitted, e.g.,. if a form referencing a user entity is submitted and the size of the fullName attribute doesn't meet this criteria, an error is returned in the web page.

Create the "business logic" (EJB)

No we're building a session bean to implement the business logic. In this simple example, one could implement everything in the controller and avoid the extra indirection level, but this is a good example of how to structure a bigger project.
  1. Create UserFacade Interface in the “com.example” package

    NOTE: With EJB3.1 you shouldn’t need to create a interface for session bean (no interface view), but this feature is not yet working on this JBoss version.


    @Local
    public interface UserFacade {
      public User findById(final long id);
      public User findByEmail(final String email);
      public List<User> getAll();

    Some explanations:
    • @Local – Defines a local interface of a session bean

  2. Create a UserFacadeBean Class in the “com.example” package

    @Stateless
    public class UserFacadeBean implements UserFacade {
      @PersistenceContext(unitName = "exampleDS")
      private EntityManager entityManager;
      public void persist(final User u) {
        entityManager.persist(u);
      }
      public List<User> getAll() {
        Query q = entityManager.createQuery("select u from User u");
        return q.getResultList();
      }
      public void remove(final long id) {
        final User u = entityManager.find(User.class, id);
        entityManager.remove(u);
      }
      //....

    Here we defined the EJB annotations:
    • @Stateless – Makes the stateless session bean.
    • @PersistenceContext – Injects the entity manager with the correct datasource (connection to the database). The entity manager takes care of the interaction with the database.

Create the controller (CDI)

The next step is to create the controller of the web page. This class has the presentation logic and accesses the business logic to manage the users.
  1.   Create a UserService Class in the “com.example” package


    @Named
    @ConversationScoped
    public class UserService implements Serializable {
      private User user = new User();     
      @Inject private UserFacade uf;
      @Inject private Conversation conversation;
      public String registerSetup() {
        conversation.begin();
        return "register_confirm";
      }
      public String registerConfirm() {
        uf.persist(user);
        conversation.end();
        return "index?faces-redirect=true";
      }
      public String userDelete(User user) {
        uf.remove(user.getId());
        return "index?faces-redirect=true";
      }
    
      public List<User> getUserList() {
        List<User> userList = uf.getAll();
        return userList;
      }

    Take a look at the EJB annotations:
    • @Named – Specifies that this bean can be referenced on the web page by it's name using expression language (EL) - we'll see it later.
    • @ConversationScoped – This bean can be part of a long running conversation (see bellow).
    • @Inject – Injects the bean than implements the business logic and the bean that control the conversation.

    The registerSetup method is called from the web page (via EL) after the user form has been filled.
    The registerConfirm method is called after the user has confirmed the user creation. Since we want to pass the user creation data along several requests (register and confirm) we create a long running conversation to keep the user state.
    The long running conversation is created with conversation.begin() and terminated with conversation.end() after the user has been created.

    Note that the methods called by the web pages (registerSetup, registerConfirm and userDelete) return strings. The strings are the names of the pages to be displayed after the method returns (without the extension).

    The methods registerConfirm and userDelete also add the parameter "faces-redirect=true". This forces the browser to be redirected to the new page (http://blogs.sun.com/enterprisetechtips/entry/post_redirect_get_and_jsf).

    Why use @Named annotation instead of @ManagedBean ? See http://stackoverflow.com/questions/2930889/are-managedbeans-obsolete-in-javaee6-because-of-named-in-cdi-weld

Create the view (JSF2+Facelets)

Now we build the view part, by creating a file with the site layout, then the 3 web pages.
A few notes on the file contents:
  • The <ui:insert> tag defines a placeholder in the layout (template).
  • The <ui:define> tag instantiates the placeholder in a concrete web page.
  • The controller attributes can be accessed via expression language e.g., #{userService.user.fullName}
  • The controller methods can also be accessed via expression language e.g., #{userService.userDelete(user)}
  • The <h:dataTable> tag creates a table filled with the contents of a list.
  • The <h:inputText> tag creates a text box.
  • The <h:commandButton> tag creates a submit button.
  • The <h:link> tag creates a link to another page.
  • The form validation failed messages can be specified via the <h:message> tag.

  1. Create a XHTML file called layout.xhtml in the WebContent directory. This has the layout of your pages.


    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml"
           xmlns:ui="http://java.sun.com/jsf/facelets"
           xmlns:h="http://java.sun.com/jsf/html"
           xmlns:f="http://java.sun.com/jsf/core">
    <h:head>
      <title><ui:insert name="title">Default Title</ui:insert></title>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    </h:head>
    <h:body>
      <div id="content"><ui:insert name="content" /></div>
    </h:body>
    </html>

  2. Create a XHTML file called index.xhtml in the WebContent directory.


    <ui:composition template="./layout.xhtml">
      <ui:define name="title">Main Page</ui:define>
      <ui:define name="content">
        <h:form>
          <h:dataTable value="#{userService.userList}" var="user" border="1">
            <h:column>
              <f:facet name="header">User name</f:facet>
              #{user.fullName}
            </h:column>
            <h:column>
              <f:facet name="header"></f:facet>
              <h:commandLink value="delete" action="#{userService.userDelete(user)}" />
            </h:column>
          </h:dataTable>
          <hr />
          <h:link value="register new user" outcome="register" />    </h:form>
      </ui:define>
    </ui:composition>

  3. Create a XHTML file called register.xhtml in the WebContent directory.


    <ui:composition template="./layout.xhtml">
      <ui:define name="title">Register</ui:define>
      <ui:define name="content">    <h:form>
        Name: <h:inputText id="name" value="#{userService.user.fullName}" />
        <h:message for="name" style="color:red" />
        <br />
        Email: <h:inputText id="email" value="#{userService.user.email}" />
        <h:message for="email" style="color:red" />
        <br />
        Password: <h:inputText id="password" value="#{userService.user.password}" />
        <h:message for="password" style="color:red" />
        <br />
        <h:commandButton action="#{userService.registerSetup}" value="Register" />    </h:form>
      </ui:define>
    </ui:composition>

  4. Create a XHTML file called register_confirm.xhtml in the WebContent directory.


    <ui:composition template="./layout.xhtml">
      <ui:define name="title">Main Page</ui:define>
      <ui:define name="content">
        <h:form>
          Name: #{userService.user.fullName}
          <br />
          Email: #{userService.user.email}
          <br />
          Password: #{userService.user.password}
          <br />
          <h:commandButton action="#{userService.registerConfirm}" value="Confirm" />    </h:form>
      </ui:define>
    </ui:composition>

Build, deploy and test

  1. Click Project -> Build Project Click the "touch descriptors" button on the eclipse toolbar to refresh the application server.
  2. Go to http://localhost:8080/jee6-example/index.jsf
  3. Try to register a new user and insert an email without the @ and see the validation failed message.
  4. Register a new user inserting a valid email and check the result in the main page.

Conclusions

Java EE has made a long journey in terms of simplicity and integration since version 1.4 or even version 5. Java EE Version 6 makes development significantly less painfull, by reducing boilerplate code, by using anotations instead of XML configuration and by improving the integration between tiers.
With this tutorial we've seen a little bit of these inovations, but this is just the tip of the iceberg. There's a lot more out there.
This tutorial also hasn't covered many other technologies, like Servlet 3, JAX-WS2.2, JAX-RS1.1, MDBeans, singleton beans, etc. I hope I can cover them in a future post.
Please feel free to leave your comments!

11 comments:

  1. Great Article..

    ReplyDelete
  2. simple and accurate :) thanks

    ReplyDelete
  3. Simple, it just works. Nice starting point for people interested in JEE.

    ReplyDelete
  4. The controller has the statement: "uf.persist(user);". "uf" is of type UserFacade, and type UserFacade does not declare a persist() method. How can the persist() method be called on type UserFacade when type UserFacade does not declare this method?

    It would be more helpful if source code were included so I could try it.

    Thanks!

    ReplyDelete
  5. Hi Ken,
    Thanks for the feedback.
    There's a link to the source code on the first section.
    Regarding the persist, well to avoid polluting the page with the full source code, I deleted "uninteresting" parts, but the "persist" method was too much - should be there.

    ReplyDelete
  6. Thanks for helpful posting.

    Deployed it on Glassfish v3 and used PostgreSQL instead of MySQL. Had to avoid calling the table "user", so added @Table(name="users") to User.java.

    ReplyDelete
  7. I get the following error when i try to register an user:

    "/register.xhtml @14,71 value="#{userService.user.fullName}": Target Unreachable, identifier 'userService' resolved to null"

    What can it be?
    The index page works fine, but i can't register the user...

    ReplyDelete
  8. xhtml is a very interesting language to be used and contain the data object model or abbreviated DOM.tutorial very good and hopefully can help me in building a web application thanks

    ReplyDelete
  9. Where can i find the source code with required jar libraries to build and run this example. Please advise

    ReplyDelete
    Replies
    1. Hi, you have the link above - on the introduction.

      Delete
  10. HI can you please provide the DB scema for this application

    ReplyDelete