Using JSF 2.2 features to develop ajax, scrollable, lazy-loading data table

November 17, 2013 2 comments

This time around, I thought I’ll share with you what I recently learnt of JSF 2.2 features. To do that, I decided to create a simple ajax, scrollable, lazy-loading data table.

Note that in NO WAY this is comparable to major libraries such as Primefaces, Richfaces or ICEFaces. This is only to show you what I have learnt. (Of course, no one can stop you from using it if you so wish to).

The Concept

Allow me to first tell you the concept, or the scenario if you like to call it so. It is actually very simple.

We have a list of Customer entity, and basically we are going to implement a data table, which is scrollable, lazy-loads the list and makes use of ajax.

Note: I assume you are comfortable with JPA and EJB, so while I might mention them here and there, I shall not discuss them in this post.

Using template

Just like any JSF application, I also started by using template. It is very easy to use template with Netbeans. Just select the option Facelets Template and choose your layout.

Notice that Netbeans also generate the two stylesheets, cssLayout.css and default.css. Also notice that in the newly generated template, they are located using the file location, as follows:

<h:head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link href="./../resources/css/default.css" rel="stylesheet" type="text/css" />
    <link href="./../resources/css/cssLayout.css" rel="stylesheet" type="text/css" />
    <title>Facelets Template</title>
</h:head>

I made a number of modifications to the default template.

Firstly, I encountered an issue when I started the application server, that the stylesheets were not loaded properly. So, to fix that, I use JSF Resource Locator (Lubke 2008).

I also create each of the sub pages, i.e. header, menu, and footer. They act as the default if none is specified.

So, the collection of my pages are as follows:

template.xhtml

<?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">
    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <h:outputStylesheet library="css" name="default.css" />
        <h:outputStylesheet library="css" name="cssLayout.css" />
        <title>Facelets Template</title>
    </h:head>
    <h:body>
        <div id="top">
            <ui:insert name="header">
                <ui:include src="header.xhtml" />
            </ui:insert>
        </div>
        <div>
            <div id="left">
                <ui:insert name="menu">
                    <ui:include src="menu.xhtml" />
                </ui:insert>
            </div>
            <div id="content" class="left_content">
                <ui:insert name="content">
                    <!-- empty content goes here -->
                </ui:insert>
            </div>
        </div>
        <div id="bottom">
            <ui:insert name="bottom">                
                <ui:include src="footer.xhtml" />
            </ui:insert>
        </div>
    </h:body>
</html>

Notice that instead of using the file locator ./../resources/css/default.css, i use h:outputStylesheet. With this approach, just put all your resources in the resources directory and point it by referring to the folder containing your resource via the attribute library. So, for example <h:outputStylesheet library="css" name="default.css" /> is really looking at the file at the location resources/css/default.css.

header.xhtml, footer.xhtml, menu.xhtml

<?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">
    <body>
        <ui:composition>
            <!--
            I created each file for header, footer and menu, but I simply list
            them here just to show you
            -->
            <h1>Default Header</h1>
            <!-- h1>Default Menu</h1 -->
            <!-- h1>Default Footer</h1 -->
        </ui:composition>	
    </body>
</html>

Next, is using the template. So, let’s create a file called customers.xhtml to use it.

customers.xhtml

<?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">
    <body>
        <ui:composition template="./common/template.xhtml">
            <ui:define name="content">
                <h:outputText value="List of customers goes here!!!" />
            </ui:define>
        </ui:composition>
    </body>
</html>

You can then run the application server and accessed the page via http://<the path to your application>/customers.jsf. The output should look like the following illustration.

template

Add the facility to create a customer

Firstly, in a template, let us add a facility to add customers in the customers.xhtml. We can simply use JSF ManagedBean to do this. However, Core Javaserver Faces, 3rd recommends:

It is a historical accident that there are two separate mechanisms, CDI beans and JSF managed beans, for beans that can be used in JSF pages. We suggest that you use CDI beans unless your application must work on a plain servlet runner such as Tomcat.

(Geary, Horstmann 2010)

Going along with the suggestion, I will use CDI beans from now on.

In real application, I am sure there are a lot more data to capture. In this example, however, let us only capture the customer’s name.

Basically we need a Model and a Controller. So, let us first create these classes.

CustomerData.java

package id.co.dwuysan.customer;

import javax.enterprise.inject.Model;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

@Model
public class CustomerData {
    
    @NotNull
    @Size(min = 1, max = 50)
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    void clear() {
        setName(null);
    }
}

CustomerData.java

package id.co.dwuysan.customer;

import id.co.dwuysan.service.CustomerService;
import javax.ejb.EJBException;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.inject.Inject;
import javax.inject.Named;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

@Named
public class CustomerRegistationAction {

    @Inject
    private CustomerData customer;
    
    @Inject
    private CustomerService customerService;
    
    public void register(ActionEvent event) {
        try {
            // calls EJB and do registration here
        } catch (EJBException e) {
            FacesContext.getCurrentInstance().addMessage(event.getComponent().getClientId(), new FacesMessage(e.getMessage()));
            throw new AbortProcessingException(e.getMessage());
        }
        this.customer.clear();
    }
}

Notice that in this case we use @Named annotation. Since we did not give it any scope annotation, it defaults to @RequestScoped (BalusC 2011a).

The next step is to modify our customers.xhtml to make use of these classes so that we can register customers.

customers.xhtml

<?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:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ez="http://java.sun.com/jsf/composite/ezcomp">
    <body>
        <ui:composition template="./common/template.xhtml">
            <ui:define name="content">
                <f:view transient="true">
                    <h:form>
                        <h:panelGrid columns="3">
                            <h:outputLabel for="txtCustomerName" value="Customer name" />
                            <h:inputText id="txtCustomerName" value="#{customerData.name}" />
                            <h:message for="txtCustomerName" styleClass="error" />
                            <div />
                            <h:commandButton id="cmdRegisterCustomer" value="Submit" action="customers" actionListener="#{customerRegistationAction.register}" />
                            <h:message for="cmdRegisterCustomer" styleClass="error" />
                        </h:panelGrid>
                    </h:form>
                </f:view>
            </ui:define>
        </ui:composition>
    </body>
</html>

Okay, once that’s done, you can register the customer. The screen should look like this.

createCust

Define the ‘Contract’

This part is the real deal. What I refer to the ‘contract’ is not the actual contract per-se. Rather I am referring to how we start by designing the Facelet xhtml first, which will drive the actual backing bean class.

So let’s first outline out requirement:

  • The records should be paginated in a table, lazy-loaded from the database
  • The user should be able to select how many records to be displayed in a page
  • The user should be able to see what the current page is, total pages and records
  • The user should be able to scroll through records, next and previous
  • Use AJAX

In an application, there bound to be a lot of listing. Therefore, the best way to move forward is to create a component which we can reuse easily. Since the component itself is comprised of a number of other components, I believe this feature is officially referred as composite component. In the era of JSF 1.x, this was quite painful. A developer needs to write a lot of classes/files. With JSF 2.x, this is very easy (and quite elegant, I must say).

Let us start by creating the component.

Creating composite component

I am going to name this component as paginator.

I am sure you can find a lot of explanation on how to do this, so I shall skip the ‘explanation’ part and simply show you what I did.

I created a file paginator.xhtml under the directory resources/ezcomp. Hence, I refer to this component later on with namespace xmlns:ez="http://java.sun.com/jsf/composite/ezcomp.

paginatorFile

Let us move on to the actual implementation of the paginator.xhtml. Please refer to the following source, and then I will take you through step-by-step.

paginator.xhtml

<?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:cc="http://java.sun.com/jsf/composite"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">

    <!-- INTERFACE -->
    <cc:interface>
        <cc:attribute name="paginateModel" /> <!-- 01 -->
    </cc:interface>

    <!-- IMPLEMENTATION -->
    <cc:implementation>
        <!-- 02 -->
        <h:inputHidden value="#{cc.attrs.paginateModel.sortField}" />
        <h:inputHidden value="#{cc.attrs.paginateModel.ascending}" />
        <h:inputHidden value="#{cc.attrs.paginateModel.page}" />

        <!-- 03 -->
        <h:panelGrid columns="2" cellpadding="5" cellspacing="5">
            <h:outputLabel value="Rows-per-page" />
            <h:selectOneRadio value="#{cc.attrs.paginateModel.rowsPerPage}">
                <f:selectItem itemValue="5" itemLabel="5" />
                <f:selectItem itemValue="10" itemLabel="10" />
                <f:selectItem itemValue="20" itemLabel="20" />
                <f:selectItem itemValue="100" itemLabel="100" />
                <f:ajax execute="@form" render="@form" listener="#{cc.attrs.paginateModel.updateRowsPerPage}" />
            </h:selectOneRadio>
        </h:panelGrid>

        <!-- pagination -->
        <h:panelGrid columns="3" cellpadding="5" cellspacing="5">
            <!-- 04 -->
            <h:commandLink value="&lt;&lt;" actionListener="#{cc.attrs.paginateModel.navigatePage(false)}" style="display: #{cc.attrs.paginateModel.page gt 1 ? 'block' : 'none'}">
                <f:ajax execute="@form" render="@form" />
            </h:commandLink>
            <!-- 05 -->
            <h:outputLabel value="#{cc.attrs.paginateModel.page} &frasl; #{cc.attrs.paginateModel.totalPages} " />
            <!-- 06 -->
            <h:commandLink value="&gt;&gt;" actionListener="#{cc.attrs.paginateModel.navigatePage(true)}" style="display: #{cc.attrs.paginateModel.page lt cc.attrs.paginateModel.totalPages ? 'block' : 'none'}">
                <f:ajax execute="@form" render="@form" />
            </h:commandLink>
        </h:panelGrid>
        <cc:insertChildren /><!-- 07 -->
        <br />
        <!-- 08 -->
        <h:outputFormat value="There are {0} record(s).">
            <f:param value="#{cc.attrs.paginateModel.recordCount}" />
        </h:outputFormat>
    </cc:implementation>
</html>

The following section explains each numbered point I have made in the customers.xhtml.

01. cc:attribute and paginatedModel

This part is the 'interface' between the implementation in this xhtml as well as the client/user of this component later. To put it in the plain words, think of it as a param that must be supplied when using this component.

02. Hidden parameters

Now this part has a lot of explanation.

Firstly, I need to fast-forward a little bit to tell you that I am using RequestScoped bean to backed the record listing. Another important thing to notice that I actually use the <f:view transient="true">, which is the feature available in JSF 2.2 and therefore making this page stateless. If you open-source in your browser, the state is now:

<input type="hidden" name="javax.faces.ViewState" id="j_id1:javax.faces.ViewState:0" value="stateless" autocomplete="off" />

Because this page is stateless, you need to manage your own state, between invocations (Riem 2013). Hence the use of hidden parameters. So imagine, suppose you were displaying page 4 of the 100 pages, and the user decided to navigate to the next page, since it is stateless, you would need to know what page is now, whether the current display is being listed ascending or descending and by what it is currently sorted.

03. Rows-per-page selection

This part is quite self-explanatory, except one part. Basically, we are listing the choice for the user to select on how many records to be displayed per page. When the user selects though, we need to re-execute the query and update the page, using AJAX. Hence, the use of this section:

<f:ajax execute="@form" render="@form" listener="#{cc.attrs.paginateModel.updateRowsPerPage}" />

What this section is saying is basically on user selection, execute the method updateRowsPerPage and update this form. The 'execute' also implies that we are taking into account all of the params in this form, as mentioned in section 02.

04/06. Navigate ‘back’ and ‘forward’

I will explain part 04 and 06 together in this section because they are quite similar.

Let us start with part 04. This will basically render a link to allow the user to navigate 'Back'. I simply play around with the display attribute to conditional render only if the current page is not the first page (otherwise, it would not be possible to navigate back on the first page, would it?). Part 06 is quite similar, with condition to only render if the current page is not the last one.

The next part I would like to explain is the actionListener on clicking that page. Basically we know at the moment what the current page is because of h:inputHidden (See section 02). So, with the two command links in part 04 and 06, we need to flag what kind of navigation is that. For that I simply use boolean value.

Last, because we want to do the navigation using AJAX, we also need to use the <f:ajax>. Also, the same reason as previous sections regarding the execute and render on @form.

05 Current page and total pages

This part is simply rendering what the current page is and the total pages available. Quite self-explanatory

06 See section 04

See section 04

07 insertChildren

Whilst we can re-use the paginator, I thought it would be very difficult to create a component that would auto-render your data model into a table. At the very least, the page designer would need to determine what columns to render (I am sure there must be a magical way to auto-render everything in a tabular manner. Maybe Oracle ADF Faces does that for you. In any case, I couldn’t be bother finding out about it).

When using this tag, basically later on when we use <ezcomp:paginator>...</ezcomp:paginator>, whatever we put in between will be rendered on part 07. Think about it a little bit like <ui:decorate>.

08 Displaying the total records

For this section we simply display the total records. Quite self-explanatory.

Using the composite component

Now we basically need to use this composite component. So we need to modify our customers.xhtml as follows:

customers.xhtml

<?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:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ez="http://java.sun.com/jsf/composite/ezcomp"> <!-- 01 -->
    <body>
        <ui:composition template="./common/template.xhtml">
            <ui:define name="content">
                <f:view transient="true">
                    <h:form id="frmCreateCustomer">
                        <h:panelGrid columns="3">
                            <h:outputLabel for="txtCustomerName" value="Customer name" />
                            <h:inputText id="txtCustomerName" value="#{customerData.name}" />
                            <h:message for="txtCustomerName" styleClass="error" />
                            <div />
                            <h:commandButton id="cmdRegisterCustomer" value="Submit" action="customers" actionListener="#{customerRegistationAction.register}">
                                <f:actionListener binding="#{listCustomers.sortByDefault}" />
                                <f:ajax execute="@form" render="@form :frmListCustomers" /> <!-- 03 -->
                            </h:commandButton>
                            <h:message for="cmdRegisterCustomer" styleClass="error" />
                        </h:panelGrid>
                    </h:form>
                    <br />
                    <h:form id="frmListCustomers"> <!-- 02 -->
                        <ez:paginator paginateModel="#{listCustomers}"> <!-- 04 -->
                            <h:dataTable value="#{listCustomers.data}" var="cust"> <!-- 05 -->
                                <h:column>
                                    <f:facet name="header">
                                        <h:commandLink value="Name" actionListener="#{listCustomers.sort('name')}">
                                            <f:ajax execute="@form" render="@form" /> <!-- 06-->
                                        </h:commandLink>
                                    </f:facet>
                                    <h:outputText value="#{cust.name}" />
                                </h:column>
                            </h:dataTable>
                        </ez:paginator>
                    </h:form>
                </f:view>
            </ui:define>
        </ui:composition>
    </body>
</html>

Again, I shall walk you through one-by-one:

01 The namespace

As mentioned previously, since we put our paginator on resources/ezcomp/paginator.xhtml, JSF allows us to refer to it by using the namespace http://java.sun.com/jsf/composite/ezcomp. So later on (as shown in 04), you can use the newly created paginator by using ezcomp:paginator.

02 The list table in its own form

Let us jump a little bit further to part 02. Part 02 shows that in this customers.xhtml, we use two forms. Mainly because I want to the interaction you are doing in with the table, you don’t want it affects or be affected by another form, which in this case the Create Customer section.

Let us say, suppose we only use one form for the entire customers.xhtml. On clicking the button to sort (part 06), the validation on the create text box may be trigger, e.g. the customer name cannot be empty. We don’t want that.

We also need to give this form a name, for reason outlined in section 03.

03 Re-render another form

The intention here is to be able to refresh the table whenever one adds a new customer. Notice that the naming container (in relation to section 02) is the second h:form. Consequently, because the Create customer and the table are residing on different naming container, let us just refresh the entire second form, and this is done by using the correct ‘Search Expression’. By using ‘:’ at the start, it means that JSF will search the tree from the root of the document (BalusC, 2011b).

04 Using our newly created composite component

This is simply the way to use our newly created paginator component, i.e. by passing the appropriate param into it (later on this).

See also the paginator.xhtml and its explanation for more details.

05 The actual data table

This is the actual data table. As I said previously, whilst we can make a generic paginator, I thought it would be very difficult to make a generic table rendering. So, in this case, I simply want to show you the case where we determine what column to render.

One thing to note though that we called the listCustomers.data to supply the javax.faces.DataModel for our data table. This ‘data’ should be the correct data, based on the page, the size, the sorting, etc. If you still don’t understand, please do not worry. Next section, it will become clearer.

06 The sorting

As per requirements above, we need to implement the sorting. This one is quite self-explanatory, and the use of f:ajax is of the same reasons as previously mentioned.

Create the class to support pagination

Okay, we have created the ‘contract/requirement’, with the paginator.xhtml and then use it on customers.xhtml. What we need now, is to implement a class that support the functionality.

What I am going to do, is to go through customers.xhtml and paginator.xhtml. You can also do that, so that you can easily understand each of the points listed below:

  • Firstly, looking at customers.xhtml the class is called ‘listCustomers’. Since we are using CDI, we need to use @Named to expose the bean to JSF environment. We can create a ListCustomers.java, or populate the value in the @Named annotation.

  • In the past, I would use @ViewScoped for this bean. However, since we use the JSF ‘stateless’ feature with f:view transient="true", we can no longer use @ViewScoped. These kinds of beans are tied to views being managed by the JSF framework. But with this stateless feature, the view is always recreated, and so are the beans on this scope (Busscher 2013). So, the best scope to use is @RequestScoped.

  • It needs to have getData() which return javax.faces.DataModel<T>. This should return the list of Customer to be displayed.

  • It needs to support public void sort(final String sortField) to support header sorting.

  • Accessor for String getSortField(), boolean isAscending(), int getPage(), AND their corresponding mutators/setters. These are required, related to our hidden inputs.

  • Accessor/mutator for rowsPerPage to support our rows-per-page selection.

  • It needs to support public void updateRowsPerPage(AjaxBehaviorEvent event), so that we can update the listing based on user’s rows-per-page selection.

  • It needs to support public void navigatePage(final boolean forward).

  • Accessor for recordCount

Anyway, you should be able to implement the class now.

The way I implement it, however, is to split it into two parts. If you think about it, let us say in the future there are multiple lists in your application, e.g. List of Orders, Persons, Invoices and so on. They willl be implemented in a same way. I thought it would be a better idea to create a base class and then extend it later with actual entities.

First, the base class.

DataListingSupport.java

package id.co.dwuysan.util;

import java.io.Serializable;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.model.DataModel;

public abstract class DataListingSupport<T extends Serializable> implements Serializable {
    private int recordCount = 0;
    private int totalPages = 0;
    private DataModel<T> data;
    
    private int page = 1;
    private Integer rowsPerPage = null;
    private boolean ascending = true;
    private String sortField;
    
    public void navigatePage(final boolean forward) {
        setPage((forward) ? ++page : --page);
        refresh();
    }
    
    public void sort(final String sortField) {
        setSortField(sortField);
        setAscending(getSortField().equals(sortField) ? !isAscending() : true);
        refresh();
    }
    
    public void updateRowsPerPage(final AjaxBehaviorEvent event) {
        setPage(1); // page must reset to the first one
        refresh();
    }
    
    public void refresh() {
        // hook to populate count and data
        populateCountAndData();
        // compute total pages
        setTotalPages(countTotalPages(getRecordCount(), getRowsPerPage()));
    }
    
    /**
     * The concreate implementation of this class must perform data retrieval
     * based on the current information available (accessible via methods such
     * as {@link #getSortField()}, {@link #isAscending()}, etc.
     * <p>
     * The implementation is responsible in populating the values for {@link #setRecordCount(int)}
     * and {@link #setData(javax.faces.model.DataModel)}
     */
    protected abstract void populateCountAndData();
    
    /************************************************************** HELPER(S) */
    
    private static int countTotalPages(int totalRecord, int rowsPerPage) {
        int pageCounter = 0;
        for (int pageCountTracker = 0; pageCountTracker < totalRecord; ++pageCounter) {
            pageCountTracker += rowsPerPage;
        }
        return pageCounter;
    }
    
    /************************************************* ACCESSORS AND MUTATORS */

    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public boolean isAscending() {
        return ascending;
    }

    public void setAscending(boolean ascending) {
        this.ascending = ascending;
    }

    public Integer getRowsPerPage() {
        return rowsPerPage;
    }

    public void setRowsPerPage(Integer rowsPerPage) {
        this.rowsPerPage = rowsPerPage;
    }

    public DataModel<T> getData() {
        return data;
    }

    public void setData(DataModel<T> data) {
        this.data = data;
    }

    public String getSortField() {
        return sortField;
    }

    public void setSortField(String sortField) {
        this.sortField = sortField;
    }

    public int getRecordCount() {
        return recordCount;
    }

    public void setRecordCount(int recordCount) {
        this.recordCount = recordCount;
    }

    public int getTotalPages() {
        return totalPages;
    }

    public void setTotalPages(int totalPages) {
        this.totalPages = totalPages;
    }
}

The next is how we extends that class to create our backing bean to support listing of Customer.

DataListingSupport.java

package id.co.dwuysan.customer;

import id.co.dwuysan.entity.Customer;
import id.co.dwuysan.service.CustomerService;
import id.co.dwuysan.util.DataListingSupport;
import javax.enterprise.context.RequestScoped;
import javax.faces.model.ListDataModel;
import javax.inject.Inject;
import javax.inject.Named;

@RequestScoped
@Named
public class ListCustomers extends DataListingSupport<Customer> {

    @Inject
    private CustomerService customerService;

    public ListCustomers() {
        setSortField("name");
        setRowsPerPage(10);
    }
    
    @Override
    protected void populateCountAndData() {
        /*
         * This is where we call an EJB (or whatever service layer you have)
         * to perform data retrieval.
         *
         * You need to make sure to retrieve the result (paginated, sorted), and
         * also the total number of records.
         */
        setRecordCount(result.getCount());
        setData(new ListDataModel<>(result.getResult()));
    }
}

So you see, using this approach, should I need another kind of listings, i.e. lists of orders, we can easily extend DataListingSupport<>.

The Result

Before I show you the full result, one thing we might want to add, is an action to load all the current customers from the database, on display of the page. JSF 2.2 adds a feature, called View Action, which makes this very very easy (McGinn 2011).

All you need to do, is to add this f:viewAction after the f:view as follows:

customers.xhtml

<?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:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ez="http://java.sun.com/jsf/composite/ezcomp"> <!-- 01 -->
    <body>
        <ui:composition template="./common/template.xhtml">
            <ui:define name="content">
                <f:view transient="true">
                    <!-- to load on display of the page -->
                    <f:metadata>
                        <f:viewAction transient="true" action="#{listCustomers.refresh}"/>
                    </f:metadata>
                    <h:form id="frmCreateCustomer">
                        <!-- the rest of the code remains unchanged -->
                    </h:form>
                </f:view>
            </ui:define>
        </ui:composition>
    </body>
</html>

Notice that we simply call DataListingSupport<>#refresh(). The viewAction actually analysis the String return to perform the implicit navigation. In this case, our refresh() method actually returns void, so no navigation is performed (McGinn 2011).

The result should be like this:

result

I took the list of the customers from NASDAQ 100.

So, there you go, now you have the an AJAX, scrollable, lazy-loading data table.

References

BalusC, 2011a, ‘What is the default Managed Bean Scope in a JSF 2 application in netbeans?’, Stack Overflow, accessed on 06 November 2013

BalusC, 2011b, ‘How to reference components in JSF ajax? Cannot find component with identifier “foo” in view’, Stack Overflow, accessed on 11 November 2013

Busscher, R, 2013, ‘JSF 2.2 Stateless views explained’, JSF Corner, accessed on 12 November 2013

Geary, D, Horstmann, C, 2010, ‘Core JavaServer Faces (3rd Edition)’, 3rd edn, Prentice Hall, California USA

Lubke, R, 2008, ‘JSF 2.0 New Feature Preview Series (Part 4) Resource Re-location’, Oracle.com, accessed on 07 October 2013

McGinn, T, 2011, ‘New JavaServer Faces 2.2 Feature: The viewAction Component’, Oracle.com, accessed on 17 November 2013

Oracle, 2013, ‘Composite Component’, Oracle.com, accessed on 07 November 2013

Riem, M, 2013, ‘JSF Tip #26 – JSF is going Stateless’, Java.net, accessed on 09 November 2013

Categories: Software Development Tags: , ,

Testing Java EE 6 with Arquillian (incl. JPA, EJB, Bean Validation and CDI)

July 3, 2013 4 comments

For a very long time, I heard quite a lot of people saying good things about Arquillian. Whilst I have been reading articles around its use, I couldn’t really find one that covers some of the aspects that I find important, all in a single article. Granted, I haven’t looked hard enough.

Points that I would like to cover are:

  • The use of JPA. I simply use EclipseLink here,
  • The use of in-memory database,
  • The use of CDI injection,
  • The use of EJB, say local Stateless session bean,
  • The use of JSR-303 Bean Validation,
  • The use of (embedded) glassfish for integration testing.

It took me a while to gather information to get such project up and running. I thought I dedicate this post to help out those who’s got similar requirement.

So, what are we waiting for!? Let’s start!!!

Configure pom.xml

Of course, we need to configure out project to use Arquillian, and also use EclipseLink as the persistence provider. But, bear in mind that we also decide before that we want to use an in-memory database. You might want to include your dependency here, in this pom.xml. I, however, decide to use Derby, which is available in the standard Oracle Java SDK classpath.

Anyway, so the pom.xml would look like this:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 

http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>inout</artifactId>
        <groupId>id.co.dwuysan</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <groupId>id.co.dwuysan</groupId>
    <artifactId>inout-ejb</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>ejb</packaging>

    <name>inout-ejb</name>

    <properties>
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <netbeans.hint.deploy.server>gfv3ee6</netbeans.hint.deploy.server>
    </properties>


    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.jboss.arquillian</groupId>
                <artifactId>arquillian-bom</artifactId>
                <version>1.0.0.Final</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    <dependencies>
        <dependency>
            <groupId>org.eclipse.persistence</groupId>
            <artifactId>eclipselink</artifactId>
            <version>2.3.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.persistence</groupId>
            <artifactId>javax.persistence</artifactId>
            <version>2.0.3</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.persistence</groupId>
            <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId>
            <version>2.3.2</version>
            <scope>provided</scope>
        </dependency>

        <!-- test -->

        <dependency>
            <groupId>org.jboss.arquillian</groupId>
            <artifactId>arquillian-bom</artifactId>
            <version>1.0.3.Final</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>org.glassfish.main.extras</groupId>
            <artifactId>glassfish-embedded-all</artifactId>
            <version>3.1.2.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-glassfish-embedded-3.1</artifactId>
            <version>1.0.0.CR3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.arquillian.junit</groupId>
            <artifactId>arquillian-junit-container</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

        <!-- environment requirement -->
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.12.4</version>
                <configuration>
                    <argLine>-XX:-UseSplitVerifier</argLine>
                    <systempropertyvariables>
                        <java.util.logging.config.file>
                        	${basedir}/src/test/resources/logging.properties
                        </java.util.logging.config.file>
                    </systempropertyvariables>
                    <systemProperties>
                        <property>
                            <name>derby.stream.error.file</name>
                            <value>target/derby.log</value>
                        </property>
                    </systemProperties>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <compilerArguments>
                        <endorseddirs>${endorsed.dir}</endorseddirs>
                    </compilerArguments>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-ejb-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <ejbVersion>3.1</ejbVersion>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.1</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${endorsed.dir}</outputDirectory>


                            <silent>true</silent>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>javax</groupId>
                                    <artifactId>javaee-endorsed-api</artifactId>
                                    <version>6.0</version>
                                    <type>jar</type>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>java.net</id>
            <url>http://download.java.net/maven/</url>
        </repository>
        <repository>
            <id>JBOSS_NEXUS</id>
            <url>http://repository.jboss.org/nexus/content/groups/public</url>
        </repository>
        <repository>
            <url>http://download.eclipse.org/rt/eclipselink/maven.repo/</url>
            <id>eclipselink</id>
            <layout>default</layout>
            <name>Repository for library EclipseLink (JPA 2.0)</name>
        </repository>
    </repositories>
</project>

As shown in the XML above, the things we have done are:

  • Include the use of Arquillian, using embedded Glassfish
  • Include the use of EclipseLink
  • Set Derby props for later use, i.e. logging and location of the database created.
    • Create out ‘case’, i.e. our JPA, EJB, CDI

      Of course, we first start by creating a case, so that we can then later test it. I assume you are familiar with JPA, EJB, CDI. Hence, following are very quick glimpses of classes using these technology.

      JPA class, Outlet.java

      package id.co.dwuysan.inout.entity;
      
      // imports omitted
      
      @Entity
      @NamedQueries({
          @NamedQuery(
              name = Outlet.FIND_BY_NAME,
              query = "SELECT o FROM Outlet o WHERE o.name = :name")
      })
      public class Outlet implements Serializable {
          
          public static final String FIND_BY_NAME = "Outlet#FIND_BY_NAME";
          
          @Id
          @GeneratedValue(strategy = GenerationType.AUTO)
          private Long id;
          
          @Column(name = "code", length = 50, insertable = true, 
                  updatable = false, unique = true)
          @Size(message = "{dwuysan.nameSizeError}", min = 1, max = 50)
          @NotNull
          private String name;
      
          /* Accessors and mutators goes here */
      
          @Override
          public int hashCode() {
              // omitted
          }
      
          @Override
          public boolean equals(Object obj) {
              // omitted
          }
      }
      

      Persistence.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <persistence version="2.0" 
      	xmlns="http://java.sun.com/xml/ns/persistence"
      	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence     http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
        <persistence-unit name="inoutPU" transaction-type="JTA">
          <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
          <jta-data-source>inoutDb</jta-data-source>
          <exclude-unlisted-classes>false</exclude-unlisted-classes>
          <properties>
            <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
          </properties>
        </persistence-unit>
      </persistence>
      

      Then let’s add a producer method to supply our PersistenceContext, as well as our EJB that uses it.

      EntityManagerProducer.java

      package id.co.dwuysan.inout.util;
      
      import javax.enterprise.inject.Produces;
      import javax.persistence.EntityManager;
      import javax.persistence.PersistenceContext;
      
      public class EntityManagerProducer {
      
          @Produces
          @PersistenceContext
          private EntityManager em;
      }
      

      OutletService.java

      package id.co.dwuysan.inout.service;
      
      // imports omitted
      
      @Stateless
      @LocalBean
      public class OutletService {
      
          @Inject
          private EntityManager em;
          
          @Resource
          private Validator validator;
      
          public Outlet createOutlet(final String name) {
              final Outlet outlet = new Outlet();
              outlet.setName(name);
              final Set<ConstraintViolation<Outlet>> violations = this.validator.validate(outlet);
              if (!violations.isEmpty()) { throw new ConstraintViolationException(new HashSet<ConstraintViolation<?>>(violations)); }
              return this.em.merge(outlet);
          }
      
          public Outlet getOutlet(final String name) {
              final Query query = this.em.createNamedQuery(Outlet.FIND_BY_NAME);
              query.setParameter("name", name);
              try {
                  return (Outlet) query.getSingleResult();
              } catch (NoResultException e) {
                  return null;
              }
          }
      }
      

      Sets beans.xml and ValidationMessages.properties
      Don’t forget to:

      • add beans.xml under src/main/resources/META-INF, and
      • add ValidationMessages.properties under src/main/resources, and
      • configure your message dwuysan.nameSizeError=error message you like here

      Configure for testing purpose

      At this point, should you deploy, it should work. HOWEVER, that’s not our goal. We would like to get it working under Arquillian, using embedded Glassfish.

      Firstly, let’s prepare configuration for embedded glassfish, using Derby database. The file is glassfish-resources.xml. In my case, I simply put this file under a new directory, mainly for separation, i.e. src/test/resources-glassfish-embedded/glassfish-resources.xml.

      glassfish-resources.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE resources PUBLIC
          "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN"
          "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
      <resources>
          <jdbc-resource pool-name="ArquillianEmbeddedDerbyPool"
                         jndi-name="jdbc/arquillian"/>
          <jdbc-connection-pool name="ArquillianEmbeddedDerbyPool"
                                res-type="javax.sql.DataSource"
                                datasource-classname="org.apache.derby.jdbc.EmbeddedDataSource"
                                is-isolation-level-guaranteed="false">
              <property name="databaseName" value="target/databases/derby"/>
              <property name="createDatabase" value="create"/>
          </jdbc-connection-pool>
      </resources>
      

      It is quite self-explanatory. Just remember to configure the database to be created on target/databases/derby so that when you do mvn clean it will be cleaned.

      Next step, is to configure Arquillian to “recognise” this glassfish-resources.xml. To do this, add arquillian.xml under the src/test/resources directory.

      glassfish-resources.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <arquillian xmlns="http://jboss.org/schema/arquillian"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
          <engine>
              <property name="deploymentExportPath">target/arquillian</property>
          </engine> 
          <container default="true" qualifier="glassfish">
              <configuration>
                  <property name="resourcesXml">src/test/resources-glassfish-embedded/glassfish-resources.xml</property>
              </configuration>
          </container>
      </arquillian>
      

      The next step is to prepare our persistence.xml. We already have one, but remember we need to supply the one which is in-memory, and make use of the jdbc connection provided by our embedded Glassfish (see glassfish-resources.xml above, which provide the jdbc-resource-pool under the JNDI name jdbc/arquillian. In my case, I named this test-persistence.xml, under src/test/resources

      test-persistence.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" 
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
          <persistence-unit name="inoutPU" transaction-type="JTA">
              <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
              <jta-data-source>jdbc/arquillian</jta-data-source>
              <exclude-unlisted-classes>false</exclude-unlisted-classes>
              <shared-cache-mode>ALL</shared-cache-mode>
              <properties>
                  <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" />
                  <property name="javax.persistence.jdbc.url" value="jdbc:derby:target/databases/derby;create=true" />
                  <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
                  <property name="eclipselink.target-database" value="Derby"/>
                  <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
                  <property name="eclipselink.debug" value="OFF"/>
                  <property name="eclipselink.weaving" value="static"/>
                  <!--<property name="eclipselink.logging.level" value="FINEST"/>-->
                  <property name="eclipselink.logging.level.sql" value="FINE"/>
                  <property name="eclipselink.logging.parameters" value="true"/>
                  <!--<property name="eclipselink.logging.level.cache" value="FINEST"/>-->
                  <property name="eclipselink.logging.logger" value="DefaultLogger"/>
              </properties>
          </persistence-unit>
      </persistence>
      

      When everything is ready, we are now ready to write our unit test, with Arquillian. In this case, it is best to test our service EJB, since that’s where we are going to use JPA, CDI, and the Validation.

      OutletServiceTest.java

      package id.co.dwuysan.inout.service;
      
      // imports omitted
      
      @RunWith(Arquillian.class)
      public class OutletServiceTest {    
          
          @Inject
          private OutletService outletService;
      
          @Deployment
          public static JavaArchive createTestArchive() {
              return ShrinkWrap.create(JavaArchive.class)
                      .addClass(Outlet.class)
                      .addClass(OutletService.class)
                      .addClass(EntityManagerProducer.class)
                      .addAsManifestResource("test-persistence.xml",
                      	ArchivePaths.create("persistence.xml"))
                      .addAsManifestResource("META-INF/beans.xml",
                      	ArchivePaths.create("beans.xml"))
                      .addAsResource("ValidationMessages.properties");
          }
          
          
          @Test
          public void testCreateOutlet() throws Exception {
              final String outletName = "Outlet 001";
              final Outlet outlet = this.outletService.createOutlet(outletName);
              Assert.assertNotNull(outlet);
      
              // check retrieval
              final Outlet retrievedOutlet = this.outletService.getOutlet(outletName);
              Assert.assertEquals(outlet.getName(), retrievedOutlet.getName());
          }
          
          @Test(expected = ConstraintViolationException.class)
          public void testCreateOutletWithEmptyName() throws Exception {
              try {
                  final Outlet outlet = this.outletService.createOutlet("");
              } catch (EJBException e) {             
                  final ConstraintViolationException cve = (ConstraintViolationException) e.getCause();
                  
                  Assert.assertEquals("Total error message should only be one",
                  	1, cve.getConstraintViolations().size());            
                  Assert.assertEquals("Message must be correct",
                  	"Name must be provided",
                  	cve.getConstraintViolations().iterator().next().getMessage());
                  throw cve;
              }
          }
      }
      

      In the above example, the first test is testing the successful case. Given a name, a retrieval should result in an Outlet entity return providing the same name as parameter. Underneath the surface though, if we look back at the body of the OutletService.java, we are actually testing:

      • Persistence (JPA), into the underlying Derby
      • EJB injected into this test/li>
      • PersistenceContext injected via Producer method (CDI)
      • Testing no validation violated
      • Testing our NamedQuery

      The second test is aimed to test that the message is interpolated correctly. Referring to what mentioned previously, for my error message, I have put the following entry in my ValidationMessages.properties:

      dwuysan.nameSizeError=Name must be provided
      

      So, we need to test that the message from Bean Validation in Outlet is interpolated correctly.

      Please pay attention to the second test. Notice that firstly, we are catching EJBException. That is because any runtime exception thrown inside an EJB will be wrapped into EJBException, hence the need to extract it via #getCause().

      So, there you go. You can now add more services and start your Arquillian test. Happy coding :)

      Future investigation

      Many Java EE application of course requires authentication and authorisation, which is generally done via JAAS. For example, using my simple example above, supposed that the service is to be modified to retrieve the outlets the current user has access to, then of course we need to get the current user’s identity. Generally, this is done via EJBContext.getCallerPrincipal(). I wonder how we can do this using Arquillian and embedded Glassfish.

    javax.persistence.TransactionRequiredException (using Arquillian)

    March 29, 2013 1 comment

    I recently encountered javax.persistence.TransactionRequiredException when I am trying to perform some cleanup, on @After method in my unit test. I am currently playing with Arquillian (and it is such a great technology to complement Java EE).

    The scenario is simple.

    I have an Item entity, and I have ItemService. The service provides functionality to add an item and to retrieve it. That’s about it.

    In unit test, for one reason or another, one might decide to clean up, or DELETE some item. However, in this case, I would very much like to keep my service layer clean, i.e. just because I happen to need a clean up on the test-side, I should not force my service to implement it. Perhaps another way to look at it is that this is my way to reduce coupling. The user of the service should knows about the service, and the service should not know about where it is being used. One direction, so to speak.

    So, to start with, here’s the code:

    ItemDistributionServiceTest

    package com.dwuysan.service;
    
    import com.dwuysan.entity.Item;
    import com.dwuysan.util.EntityManagerProducer;
    import javax.inject.Inject;
    import javax.persistence.EntityManager;
    import org.jboss.arquillian.container.test.api.Deployment;
    import org.jboss.arquillian.junit.Arquillian;
    import org.jboss.shrinkwrap.api.ArchivePaths;
    import org.jboss.shrinkwrap.api.ShrinkWrap;
    import org.jboss.shrinkwrap.api.spec.JavaArchive;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    
    /**
     * @author denywuy
     */
    @RunWith(Arquillian.class)
    public class ItemDistributionServiceTest {
    
        private Item item;
        @Inject
        private ItemService itemService;
        @Inject
        private EntityManager em;
    
        @Deployment
        public static JavaArchive createTestArchive() {
            return ShrinkWrap.create(JavaArchive.class)
                    .addClass(Item.class)
                    .addClass(ItemService.class)
                    .addClass(EntityManagerProducer.class)
                    .addAsManifestResource("test-persistence.xml", ArchivePaths.create("persistence.xml"))
                    .addAsManifestResource("META-INF/beans.xml", ArchivePaths.create("beans.xml"))
                    .addAsResource("ValidationMessages.properties");
        }
    
        @Before
        public void setup() {
            this.item = new Item();
            item.setCode("item01");
            item.setName("item01");
            item.setUom("piece");
    
            this.item = this.itemService.getItem(this.itemService.createItem(item));
        }
    
        @After
        public void cleanUp() throws Exception {
            this.em.remove(em.merge(this.item));
        }
    
        @Test
        public void testDistribute() throws Exception {
            /*
             * Test omitted
             */
        }
    }
    

    So, to DELETE the item, I directly use EntityManager#remove(...). However, that results in the following error:

    Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 11.847 sec <<< FAILURE!
    testDistribute(com.dwuysan.service.ItemDistributionServiceTest)  Time elapsed: 0.625 sec  <<< ERROR!
    javax.persistence.TransactionRequiredException
    	at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTxRequiredCheck(EntityManagerWrapper.java:163)
    	at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTransactionScopedTxCheck(EntityManagerWrapper.java:145)
    	at com.sun.enterprise.container.common.impl.EntityManagerWrapper.merge(EntityManagerWrapper.java:280)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    

    same as above

    After further reading, I found that we need to explicitly initiates transaction. So, the code change slightly to:

    ItemDistributionServiceTest

    package com.dwuysan.service;
    
    // the rest of the imports go here
    import javax.annotation.Resource;
    import javax.transaction.UserTransaction;
    
    @RunWith(Arquillian.class)
    public class ItemDistributionServiceTest {
    
        private Item item;
    
        // the rest of the injections go here
        @Resource
        private UserTransaction utx;
    
        @Deployment
        public static JavaArchive createTestArchive() {
            // same as above
        }
    
        @Before
        public void setup() {
            // same as above
        }
    
        @After
        public void cleanUp() throws Exception {
            utx.begin();
            this.em.remove(em.merge(this.item));
            utx.commit();
        }
    
        @Test
        public void testDistribute() throws Exception {
            /*
             * Test omitted
             */
        }
    }
    

    Reference:

    Kosi2801, 2009, EntityManager throws TransactionRequiredException on merge() in JBoss JSF bean, accessed 29 March 2013.

    JAAS-secured JAX-RS end point

    February 13, 2013 3 comments

    With the advent of RESTFUL (JAX-RS) as the “preferred” way to create web service end points, for a long time I have always wondered how people implement security mechanism around it.

    At the end of the day, I presume the underlying implementation of JAX-RS is servlet, and therefore its security might also be around what is already provided by the container, i.e. JAAS.

    This post will cover my findings on how to step-by-step implement FORM-based security using JDBC realm, JAX-RS and how to test it using cURL, on Glassfish 3.

    Setting up JDBC-realm

    Firstly, since we are using JDBC-realm, let’s assume that we have created a JDBC connection to the underlying database under the JNDI jdbc/test.

    The next step is to create a new realm. You can do this by going to server-config > Security > Realms and add a new realm. Select the realm type com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm, and then populate the mandatory fields.

    • Start by giving your new realm a name.
    • For JAAS Context, put jdbcRealm
    • Populate JNDI name, preferably starts with "jndi/"

    Next, do pay attention to the rest of the fields. It seems that Glassfish expects to see two tables. The first table is to contain a list of users, with usernames as their unique identifier. The second table is to list the groups that each user belongs to. Username is to be the foreign-key link between the two tables. (The next section should give you better idea on how the tables should look, they are after all very simple).

    Once these tables are created, we can then populate the mandatory fields accordingly.

    Populate database for testing purpose

    The next step is to populate the table for testing purpose. Let’s just assume that we will be testing using username hpotter and password test. For the password however, note that Glassfish digest by default is SHA-256, as illustrated by the following screen shot.

    sha-256

    Hence, you need to encode the password test before insert. You can use encoder by technipixel, which will give you the String 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08.

    The next step is to write some INSERT statements:

    INSERT INTO person (id, password, username) VALUES (1, '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08', 'hpotter');
    COMMIT;
    INSERT INTO person_role (username, user_group) VALUES ('hpotter', 'User');
    INSERT INTO person_role (username, user_group) VALUES ('hpotter', 'Admin');
    COMMIT;
    

    Let’s move on to the next step.

    Securing web application using JAAS

    Quite a number of tutorials out there on JAAS with FORM authentication method. However, I thought I put it here again, with the hope that some might find it simpler.

    web.xml

    Make the following modification to your web.xml

        <welcome-file-list>
            <welcome-file>/index.jsp</welcome-file><!-- 1 -->
        </welcome-file-list>
        <security-constraint><!-- 2 -->
            <display-name>TestConstraint</display-name>
            <web-resource-collection>
                <web-resource-name>TestResource</web-resource-name>
                <description/>
                <url-pattern>/*</url-pattern>
            </web-resource-collection>
            <auth-constraint>
                <description/>
                <role-name>User</role-name>
                <role-name>Admin</role-name>
            </auth-constraint>
        </security-constraint>
        <login-config><!-- 3 -->
            <auth-method>FORM</auth-method>
            <realm-name>testRealm</realm-name>
            <form-login-config>
                <form-login-page>/login.html</form-login-page>
                <form-error-page>/error.html</form-error-page>
            </form-login-config>
        </login-config>
        <security-role><!-- 4 -->
            <description/>
            <role-name>User</role-name>
        </security-role>
        <security-role><!-- 5 -->
            <description/>
            <role-name>Admin</role-name>
        </security-role>
    

    Let’s go through them one-by-one.

    1. This is the file to be displayed on successful login. You can also use this file as redirection. For example, suppose you have a file called index.xhtml (a JSF page), you can use response.sendRedirect("index.jsf");
    2. This is the actual constraint, i.e. how you secure the application. This section is basically there to secure all access to the application, denoted by /* url pattern, and only allow access of user with the role of User and Admin.
    3. This part denotes that what we are using is FORM authentication method (which I’ll explain in more detail in the next section). Important part is to ensure the correct name of the security realm used, which in this case, testRealm, the same realm name we have given when setting it up via Glassfish admin page. The other part is to set the page containing j_security_check that the application will automatically redirect to in the event of request access has not been authenticated yet.
    4. The known role
    5. Same as previous section.

    glassfish-web.xml

    We also need to configure glassfish-web.xml so that the container knows about the mapping between groups from the database and the role recognised by the application.

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
    <glassfish-web-app error-url="">
        <security-role-mapping>
            <role-name>Admin</role-name>
            <group-name>Admin</group-name>
        </security-role-mapping>
        <security-role-mapping>
            <role-name>User</role-name>
            <group-name>User</group-name>
        </security-role-mapping>
        <class-loader delegate="true"/>
        <jsp-config>
            <property name="keepgenerated" value="true">
                <description>Keep a copy of the generated servlet class' java code.</description>
            </property>
        </jsp-config>
    </glassfish-web-app>
    

    N.B. If you use Netbeans, this file might be generated for you.

    Login page: login.html

    If we refer again to web.xml above, notice that the login page is pointing to login.html. For FORM authentication method, as per specification, we need to have a form with j_security_check, with j_username and j_password (Oracle 2013).

    <!DOCTYPE html>
    <html>
        <body>
    
            <form action="j_security_check" method="post">
                <p>
                    <strong>Username</strong>
                    <input type="text" name="j_username" size="25" />
                </p>
                <p>
                    <strong>Password</strong>
                    <input type="password" size="15" name="j_password" />
                </p>
                <p>
                    <input type="submit" value="Submit" />
                    <input type="reset" value="Reset" />
                </p>
            </form>
        </body>
    </html>
    

    With all of these completed, we can start up Glassfish, deploy our application and test it using any browser. Upon accessing the application, users should be directed to login.html to login. Remember to use hpotter as username and test as password. On successful login, the user should be redirected to index.jsp (which in turn redirects user to index.jsf, or anything the index.jsp is redirecting to, according to your requirement).

    Create a RESTFUL end point

    The next step of course is to create a RESTFUL end point, which is very simple. One of the posts I have written here might also be useful.

    To start, assuming we have the following application path.

    package com.dwuysan;
    
    import javax.ws.rs.ApplicationPath;
    import javax.ws.rs.core.Application;
    
    /**
     * @author denywuy
     */
    @ApplicationPath(value = "resources")
    public class ApplicationConfig extends Application {
    }
    

    Let us assume that we have the following simple RESTFUL service.

    package com.dwuysan;
    
    import com.dwuysan.entity.Outlet;
    import com.dwuysan.service.OutletService;
    import javax.annotation.ManagedBean;
    import javax.annotation.security.RolesAllowed;
    import javax.inject.Inject;
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.PathParam;
    
    @Path(value = "generic")
    @RolesAllowed(value = "User")
    @ManagedBean
    public class GenericResource {
    
        @Inject
        private OutletService outletService;
    
        @GET
        @Path("{id}")
        public Outlet get(@PathParam(value = "id") final long id) {
            return this.outletService.getOutlet(id);
        }
    }
    

    Note that we have secured this service with javax.annotation.security.RolesAllowed annotation.

    Testing secured RESTFUL service using curl

    Given the RESTFUL service we created above, we should be able to test it using CURL with the following command:

    curl -X GET -H "Accept:application/json" -H "Content-Type:application/json" http://localhost:8080/testApp/resources/generic/101
    

    The above command translate to the following: hit the URL above using GET, with the headers Accept:application/json and Content-Type:application/json (cURL 2013)

    Since we have secured our application, invocation as above will not work. The user will be redirected to login.html. Hence, our aim now is to first login. With cURL, we can submit parameters to login, i.e. username and password, and then obtain the cookie. To do that, we can use this command:

    curl -b cookies.txt -c cookies.txt -d "j_username=hpotter&j_password=test" http://localhost:8080/testApp/j_security_check
    

    This command is submitting username and password, to the j_security_check (remember our login.html that we have created previously), and storing the cookies obtain under the file cookies.txt.

    If you open your cookies.txt, you may see the following:

    # Netscape HTTP Cookie File
    # http://curl.haxx.se/docs/http-cookies.html
    # This file was generated by libcurl! Edit at your own risk.
    
    #HttpOnly_localhost     FALSE   /testApp     FALSE   0       JSESSIONID      245a317ab91fbb28244403346770
    

    N.B. You might receive Document Moved response. This means login has been successful. Otherwise, you would get the raw html of the error.html again.

    Once we have been authenticated successfully, we can use the cookies we have obtained from the login to invoke the RESTFUL service.

    curl -X GET -H "Accept:application/json" -H "Content-Type:application/json" -b cookies.txt -c cookies.txt http://localhost:8080/testApp/resources/generic/101
    

    References:

    BalusC, 2012, ‘Does JSF support form based security’, accessed 12 February 2013.

    Oracle, 2013, ‘Securing Web Application’, accessed 12 February 2013.

    Wolff, N, 2005, ‘How do you handle authentication via cookie with CURL?’, accessed 12 February 2013.

    Reduce eye strain with Netbeans Dark Nimbus Theme

    February 6, 2013 1 comment

    If you do feel that your IDE is WAYYYY TOO BRIGHT, well, Netbeans 7.3 RC1 Dark Nimbus Theme probably can help.

    What you need to do:

    • Go to Plugins, and download the Netbeans Dark Nimbus Theme
    • Go to <Netbeans home directory>/etc/netbeans.conf
    • Append --laf Nimbus on the option netbeans_default_options
    • Restart IDE
    • Go to Options > Fonts & Colors, then select Norway Today
    Categories: Software Development Tags:

    Injecting EJB into a JAX-RS

    December 6, 2012 Leave a comment

    Following my previous post here, I tried to inject an EJB 3.1 stateless session bean into this resource, only to find the infamous java.lang.NullPointerException.

    Supposed you have an EJB as follows:

    MainService

    package com.wordpress.dwuysan.service;
    import javax.ejb.Stateless;
    import javax.ejb.LocalBean;
    
    @Stateless
    @LocalBean
    public class MainService {
    
        public String sayHello(final String name) {
            return "Hello" + name;
        }
    }
    

    And injecting it in a JAX-RS bean:

    GenericResource

    package com.wordpress.dwuysan;
    
    import javax.inject.Inject;
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    
    @Path(value = "generic")
    public class GenericResource {
    
        @Inject
        private com.wordpress.dwuysan.service.MainService mainService;
    
        @GET
        public String get() {
            return this.mainService.sayHello("test");
        }
    }
    

    This will result in java.lang.NullPointerException.

    To fix this, the JAX-RS bean must also be “managed”, so simply add the annotation javax.annotation.ManagedBean to your JAX-RS bean (Nelson 2011)

    References:

    Nelson, L, 2011, ‘How do I inject a local stateless session bean into a JAX-RS resource using CDI?’, accessed 06 December 2012.

    Categories: Software Development Tags: , ,

    Starting with JAX-RS: Configuring javax.ws.rs.ApplicationPath

    December 6, 2012 2 comments

    I recently started with a very simple Hello-World-like JAX-RS. So, to start with, I created a class like this:

    GenericResource

    package com.wordpress.dwuysan;
    
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    
    @Path(value = "generic")
    public class GenericResource {
    
        @GET
        public String get() {
            return "Hello World";
        }
    }
    

    Once the application server is running, when I run curl http://<web application address>/generic, it failed.

    After a little bit of Google-ing around, I found that you need to set up the resource path, either by installing a correct servlet on web.xml, or if you are fortunate enough and are using Java EE 6, you can use @javax.ws.rs.ApplicationPath and extends javax.ws.rs.core.Application (Kuchtiak 2009).

    So, once I add this class:

    ApplicationConfig

    package com.wordpress.dwuysan;
    
    import javax.ws.rs.ApplicationPath;
    import javax.ws.rs.core.Application;
    
    @ApplicationPath(value = "resources")
    public class ApplicationConfig extends Application {
    }
    

    I can now invoke curl http://<web application address>/resources/generic, I got correct response.

    References:

    Kuchtiak, M, 2009, 'How to Combine REST Services with EJB 3.1', accessed 06 December 2012.

    Categories: Software Development Tags:
    Follow

    Get every new post delivered to your Inbox.

    Join 34 other followers