As a basis for many different kinds of web applications, the JDevelopment team has released an open source Java EE kickoff app.

This app is a skeleton application that demonstrates a couple of technologies:

JSF 2.1 based views

CDI based backing beans

JASPIC based authentication module

EJB based services

Bean Validation constraints

JPA based models

Java EE 6 standard data source

Embedded H2 database

The concrete functionality that’s implemented:

Logging in with username/password

Remember-me for login

Login-to-continue for protected pages

Basic user registration with password validation

Authentication via app controlled Service and domain entity

Extra app controlled layer above roles: groups

Admin CRUD page for editing and deleting users

Authentication is done via a reusable JASPIC SAM (JSR 196), that’s being developed in a separate project: OmniSecurity which is a sub-project of OmniFaces, which is also demonstrated in the kickoff app (e.g. for HTML5 placeholders).

The Java code

A n overview of the code and the main packages is given below:

org.example.kickoff.auth

This package contains the KickoffAuthenticator class, which loads a user from the embedded database. This class implements the UsernamePasswordAuthenticator interface and is auto-discovered (via CDI) by the JASPIC authentication module.

An excerpt of this class:

@SessionScoped public class KickoffAuthenticator implements UsernamePasswordAuthenticator { @EJB private UserService userService ; private User user ; private List applicationRoles ; @ Override public boolean authenticate ( String name, String password ) { try { user = userService. getUserByCredentials ( name, password ) ; } catch ( InvalidCredentialsException e ) { return false ; } applicationRoles = user. getRoles ( ) ; return true ; } }

org.example.kickoff.business

This package contains the Services and associated exception types. It now mainly contains class UserService, which is an EJB bean that uses JPA to handle Users.

An excerpt of this class:

@Stateless public class UserService { @PersistenceContext private EntityManager entityManager ; public void registerUser ( User user, String password ) { if ( getByEmail ( user. getEmail ( ) ) ! = null ) { throw new ValidationException ( "Email address is already registered" ) ; } setCredentials ( user, password ) ; if ( ! user. getGroups ( ) . contains ( USERS ) ) { user. getGroups ( ) . add ( USERS ) ; } entityManager. persist ( user ) ; } }

org.example.kickoff.model

This package contains all domain models (entities) that the application uses. Currently this is mainly contains the User entity, and several security related types like Group, Role and Credentials. There’s also a BaseEntity, which provides a universal hashCode and equals implementation, which are based on the unique persistent Id that all persisted JPA entities have. An individual entity can of course provide a more specific implementation whenever that’s needed.

The base entity looks as follows:

public abstract class BaseEntity { public abstract T getId ( ) ; public abstract void setId ( T id ) ; @ Override public int hashCode ( ) { return ( getId ( ) ! = null ) ? ( getClass ( ) . hashCode ( ) + getId ( ) . hashCode ( ) ) : super . hashCode ( ) ; } @ Override public boolean equals ( Object other ) { return ( other ! = null & amp ;& amp ; getClass ( ) == other. getClass ( ) & amp ;& amp ; getId ( ) ! = null ) ? getId ( ) . equals ( ( ( BaseEntity ) other ) . getId ( ) ) : ( other == this ) ; } }

An excerpt of the User entity:

@ Entity public class User extends BaseEntity { @Id @GeneratedValue ( strategy = IDENTITY ) private Long id ; @NotNull @Email @Column ( nullable = false , unique = true ) private String email ; @OneToOne ( mappedBy = "user" , fetch = LAZY, cascade = ALL ) private Credentials credentials ; private String loginToken ; // TODO: make collection later @ElementCollection ( targetClass = Group . class , fetch = EAGER ) @Enumerated ( STRING ) @CollectionTable ( name = "user_group" ) @Column ( name = "group_name" ) private List groups = new ArrayList ( ) ; }

org.example.kickoff.validator

This package contains validation logic, mostly intended to be used with Bean Validation. It currently contains a basic email validator, for the @Email annotation that was shown above:

public class EmailValidator implements ConstraintValidator { @ Override public void initialize ( Email constraintAnnotation ) { } @ Override public boolean isValid ( String email, ConstraintValidatorContext context ) { try { new InternetAddress ( email ) . validate ( ) ; } catch ( AddressException e ) { return false ; } return true ; } }

org.example.kickoff.view

This package contains the view specific artifacts, which are mostly backing beans (which back a single view, or dialog on a view) and more general managed beans (which can be used from multiple views).

An excerpt from a bean called LoginBean that’s used by the index and the “login-to-continue” views to login:

@Named @RequestScoped public class LoginBean { private String loginUserName ; private String loginPassword ; private boolean rememberMe ; public void login ( ) throws IOException , ServletException { boolean authenticated = Jaspic. authenticate ( loginUserName, loginPassword, rememberMe ) ; if ( ! authenticated ) { addGlobalError ( "Login failed" ) ; } } public void logout ( ) throws ServletException { Jaspic. logout ( ) ; } }

The Facelets views

The Facelets views (pages) are located in the src/main/webapp folder. Public views are directly put into the root, while other pages are organized per role. There is a single page for users with role admin now, which is thus located in /admin.

Includes, useful for breaking up bigger pages into smaller chunks, have been put into WEB-INF/includes. Folders within this includes folder correspond to the top-level views. E.g. WEB-INF/includes/index contains all includes for the index page.

The main index page looks as follows:

<ui:composition template = "/WEB-INF/templates/layout.xhtml" xmlns = "http://www.w3.org/1999/xhtml" xmlns:h = "http://java.sun.com/jsf/html" xmlns:ui = "http://java.sun.com/jsf/facelets" > <ui:define name = "title" > Java EE kickoff app </ui:define > <ui:define name = "content" > <h:panelGroup rendered = "#{empty request.userPrincipal}" > <ui:include src = "/WEB-INF/includes/index/public.xhtml" /> </h:panelGroup > <h:panelGroup rendered = "#{!empty request.userPrincipal}" > <ui:include src = "/WEB-INF/includes/index/loggedin.xhtml" /> </h:panelGroup > </ui:define > </ui:composition >

What’s next?

We intend to periodically update the project with common things that we found to be useful for a kickoff app. Some things that are on the road map is i18n support, a mechanism for system (app) settings and something for storing user preferences.

Download and Demo

The project itself is hosted on GitHub: github.com/javaeekickoff/java-ee-kickoff-app.

There is a live demo at OpenShift: javaee6-kickoffapp.rhcloud.com

See also