Creating a simple CRUD application with JSF, CDI and JPA

This post describes a simple setup of a web application. It has a web front (JSF), a backing bean (CDI), a database entity (JPA) and a Java Bean (EJB) for database access.
Find the whole example on GitHub: https://github.com/sapsiero/webapp-demo2

Setting up a JPA Entity

First set up a JPA entity by simply adding the @Entity annotation. A JPA entity always needs an identifier (in this case the id). This field has to be marked with the @Id annotation. Using the @GeneratedValue(strategy = GenerationType.AUTO) makes sure that the Id is generated by the JPA framework.

@Entity
public class PersonEntity {

    long id;

    String name;

    String firstName;

    int age;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public long getId() {
        return id;
    }
...

Setting up an Enterprise Java Bean (EJB)

The EJB is responsible for persisting the entity object into a persistence contect. The EJB container offers transcations and dependency injection, so that the configuration can easily be made.
The EJB is stateless (@Stateless), since it has no need for state information. The entity manager is automatically injected using the @PersistenceContext annotation.

@Stateless
public class PersonBean {

    @PersistenceContext
    EntityManager em;

    public List list() {
        TypedQuery q = em.createQuery("Select p From PersonEntity p", PersonEntity.class);
        return q.getResultList();
    }
...

Setting up the backing CDI bean

The backing bean is a request scoped CDI bean. To make a POJO available in JSF Faceletts you have to name it (@Named). Furthermore the @RequestScoped annotation determines that the objects’ lifecycle is related to the users request.
Two objects are injected into this class: The personEntity is an instance of the just created JPA class PersonEntity. The personBean is an instance of the stateless EJB.

@Named
@RequestScoped
public class PersonController {

    @Inject
    PersonEntity personEntity;

    @Inject
    PersonBean personBean;

    public List getListAll() {
        return personBean.list();
    }

    public String save() {
        personBean.save(personEntity);
        return "index";
    }
...

Adding the Faceletts

In this example you only need to faceletts: one showing the list of PersonEntity objects (name it index.xhtml) and another making the data available in an HTML formular (edit.xhtml).

<h:body>
    <h:outputLabel value="Existing persons"/>
    <h:dataTable value="#{personController.listAll}" var="person">
        <h:column>
            <f:facet name="header">
                <h:outputLabel value="Edit"/>
            </f:facet>
            <h:form>
                <h:commandButton value="Edit" action="#{personController.edit(person.id)}"/>
            </h:form>
        </h:column>
        <h:column>
            <f:facet name="header">
                <h:outputLabel value="Del"/>
            </f:facet>
            <h:form>
                <h:commandButton value="Del" action="#{personController.delete(person.id)}"/>
            </h:form>
        </h:column>
        <h:column>
            <f:facet name="header">
                <h:outputLabel value="First Name"/>
            </f:facet>
            <h:outputLabel value="#{person.firstName}" />
        </h:column>
...

Start from Scratch: Build a new Business App using Java EE 6 (CDI, JSF and JPA)

A few weeks ago I read quite a lot about Java EE 6 and its newly achieved ease of use. So I started, building a new basic app from scratch. Here is my cookbook.

My setup:

  • Oracle Java SE 7
  • Glassfish 3.1.2 as JavaEE Application Server (but I try to use as much the standard as possible)
  • Maven 3

and all that on my Oneiric Ocelot (Ubuntu 11.10) box.

Setup folder

First create your project using maven:

mvn archetype:generate

Follow the given instructions.

  • As archetype select webapp-javaee6
  • with its most recent version (currently 1.5).
  • Set your GroupId (e.g. sapsiero.com).
  • Set your ArtifactId (e.g. webapp-demo1).
  • Set the version (e.g. 1.0).
  • Finally set the default package name (to com.sapsiero.webappdemo1).

Change the dependency within your pom.xml to point to the javaee-api (instead of javaee-web-api) since we want to use the full profile.

Activate JSF (Java Server Faces)

Add web.xml to ./webapp-demo1/src/main/webapp/WEB-INF

add the following content:

<?xml version='1.0' encoding='UTF-8'?>
<web-app version="3.0"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> 

  <!-- Faces Servlet -->
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet> 

  <!-- Faces Servlet Mapping -->
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.faces</url-pattern>
  </servlet-mapping> 

  <welcome-file-list>
    <welcome-file>index.faces</welcome-file>
  </welcome-file-list>
</web-app>

Make sure to select version 3.0 since it’s the only version able to handle CDI objects as backing beans.
The config file contains now

  • the reference to the JSF Faces servlet,
  • the mapping to this servlet (*.faces), and
  • the welcome file (index.faces).

Activate CDI (Contexts and Dependency Injection)

Add beans.xml to ./webapp-demo1/src/main/webapp/WEB-INF

add the following content:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>

The file does not contain any configuration, but it indicates the Application Server to activate the CDI.

Activate JPA (Java Persistence API)

Add persistence.xml to ./webapp-demo1/src/main/webapp/WEB-INF/classes/META-INF

add the following content:

<?xml version="1.0" encoding="UTF-8"?>
<persistence 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" version="2.0">
    <persistence-unit name="UserManagement">
        <jta-data-source>jdbc/__default</jta-data-source>
        <properties>
            <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
            <property name="eclipselink.ddl-generation.output-mode" value="database"/>
        </properties>
    </persistence-unit>
</persistence>

This configuration defines a persistence unit that is linked to the Applications server’s jdbc/__default data source. Just log into the AS web console to change this or define a new one.
The unit is named UserManagement in my example.
While the configuration so far is AS independant, the properties are specific. They are referring to properties that only EclipseLink (which is part of Glassfish 3.1.2) processes. Use theses properties to define that the data base is automatically deployed. If you are using another AS check the documentation for the JPA implementation (e.g Hibernate is also providing this feature).
Before you start, make sure that your Data Base is up and running!
For Glassfish this might be JavaDB. You can start the DB using the Glassfish admin command:

./bin/asadmin start-database --dbhost 0.0.0.0

What’s next

Now you are ready to start implementing. Stay tuned, I’ll add my demo app the next days.

Quick Input Demo Video

See the short demo on the quick input plugin’s functionality.

If you want to try it yourself, follow the installation guide in the documentation.

Then create the following domain class and the scaffolded controller.

package howtoquickinput

class Howto {

    Date foo
    Date bar

    Number one
    Number two
    Number three

    static constraints = {
        foo(attributes:[errornode:"this.parentNode", errorclass:"error"])
        bar(attributes:[errornode:"this.parentNode", errorclass:"error", register:"foo"])

        one(attributes:[errornode:"this.parentNode", errorclass:"error", decimals:2])
        two(attributes:[errornode:"this.parentNode", errorclass:"error", decimals:2])

        three(attributes:[errornode:"this.parentNode", errorclass:"error", decimals:4, function:"one * two", register: "one,two"])
    }
}

Quick Input Plugin Release 0.1

I’m proud to announce version 0.1 of the Quick Input Plugin for the grails web framework (http://grails.org).

The plugin provides new input tags supporting some mass input capabilities.

They provide functions to easily input

  • dates, only using the number values, and
  • number.

Main feature is that you can link (relate) one field to another. Whenever you change a field, the related field is change.

Here an example for number fields:

Just enter a number in the "foo" field.

You enter a number (e.g. 2):

You enter a number (e.g. 2).

The data in field “bar” is automatically calculated – as soon as “foo” looses focus – using the provided formula.

The value of "bar" is automatically replaced by a formular.

For further information visit the documentation page.

Welcome

Welcome to sapsiero!

This website is my personal incubator for my developments.

But I also want to take the chance to present my thoughts and developments to the public.

Main subject of my developments are groovy & grails with JavaScript.

If you are interested, have a look. I’d be happy, if you provide feedback, whenever possible.

Thanks

Tim