Categotry Archives: Web App [English]

Complete Web Application: Angular Twitter Bootstrap Spring MVC, Data and Security

55

Posted on by

Hello, how are you?

Today we will see how to create a complete Java web application using Spring, Angular, JQuery, Twitter Bootstrap, Tiles, Maven, Tomcat, JPA/Hibernate.

The project that will be done here in this post will be used in another post that I will write, because of this future post, in this post will be described a detailed environment configuration. I will be using linux as my operational system (OS), but almost nothing will change if you use Windows or other OS.

I received a lot of emails asking for a post using Spring in a full web application, all the applications already posted here were using JEE technology (JSF, EJB, JPA). In this post we will see a project using Spring framework with the following modules: Spring MVC, SpringData e Spring Security. We will see how to do internationalization (i18n) with SpringMVC and templates with Tiles framework.

Postgre will be the database used here, but if you want use it with MySQL just add the MySQL jar to the project and change some configuration. In this post will be displayed both Postgre and MySQL configurations.

It is possible to find the source code of this project in the last page of this post, and to make everybody happy, 3 downloading ways will be available in the end of the post. In this post we will focus in the Spring/JPA code and some of the JPS code highlighting the Angular and Bootstrap libraries, all the JSP code, classes and configurations can be downloaded in the last page.

What we will see in here:

Page 02: Environment Setup
Page 03: Creating the project
Page 04: Understanding the “pom.xml”, “log4j.xml” and the “context.xml” files
Page 05: Creating the Spring and the project XMLs
Page 06: Tiles – Page templates
Page 07: Project Model Classes
Page 08: Using SpringData as Repository (DAO); creating User Service
Page 09: Using SpringData as Repository (DAO); creating Contact Service
Page 10: Creating the Controllers
Page 11: Using Restful approach with SpringMVC
Page 12: Understanding the Login, SpringMVC Interceptor and the Security Rules
Page 13: First Contact with Angular.js and the SpringMVC
Page 14: Using Angular.js bind in a HTML table
Page 15: Internationalization (i18n) with Spring
Page 16: Understanding the Twitter Bootstrap role
Page 17: Running the project

Let us get started!

JSF Mini Book – Tips, concepts and good practices

18

Posted on by

Hello, how are you?

This post was written as an article to a Brazilian Java magazine. Unfortunately it was not published =(. I decided to post it here! =D

This post will display tips, concepts and solutions to developers that works with JSF 2.0 every day. We will see the concepts and the right way of using the JSF to help those who works with this technology or has interest in learning it – students or developers that works with others frameworks. Using this tool without knowledge of it will give more problems to your software instead solutions. It is really needed to understand how the JSF works, how it handles each user action request and how it is possible to build a software code that will optimize the JSF usage.

We will see some technical questions like: importing images/javascript into the pages, how to upgrade a JSF 1.2 app to a JSF 2.0, using Ajax that is a technology of asynchronously requests, and more; we will see some needed theory that is usually set aside.

With JSF we will be able to face one of the major problems of the web technology, code reuse. The JSF allow us to reuse the code of pages, javascript and validations in Java code that are used in the pages. When we reuse the code we will reduce the maintenance time expend, the change impacts will reduce also and others.

Today we will see:

  • Page 02: Creating a JSF project
  • Page 03: How to import CSS/Images/JavaScript as Library
  • Page 04: XHTML page reuse with Facelets
  • Page 05: JSP x Facelets
  • Page 06: Hiding the comments of the xhtml page
  • Page 07: Avoiding @SessionScoped type. Check all Scope Types
  • Page 08: Avoiding the use of logic in the xhtml page
  • Page 09: Use the h:outputLink to navigate
  • Page 10: Ajax with JSF 2.0
  • Page 11: Smoothing the JSF development
  • Page 12: Upgrading from JSF 1.2 to 2.0
  • Page 13: How to receive null value from the view
  • Page 14: Choosing between action and actionListener
  • Page 15: Flash Scope
  • Page 16: Dot no mix JSF Implementations
  • Page 17: Internationalization as good practice
  • Page 18: JSF 2.2 new features

This post is a celebration for the mark of 200k of viewers that we received in the two years of existence of this blog.

“The Father of Java” uses Jelastic

0

Posted on by

Hello, how are you?

Today we will have an unusual post, it is more like a good news about this framework that is getting its space in the development world. Jelastic has as characteristic to work as a container of containers.

This news were sent to me by Judah Johns from Jelastic.

As far as we can tell, this is the first PaaS that Dr. Gosling has given his endorsement. We reached out to him to confirm it, and sure enough, it turns out that he is a very happy Jelastic user and is very excited about what he can do with it and what he will be doing with it in the near future.

Though I know that in our community, most everyone knows who James Gosling is, there a lot of younger guys learning Java that have never heard of him, like my 13 year-old brother, Daniel, who is quite an avid Java coder. So, who is James Gosling?

The Dr. James Gosling Bio

This bio comes from Gosling’s own blog: James Gosling received a BSc in Computer Science from the University of Calgary, Canada in 1977. He received a PhD in Computer Science from Carnegie-Mellon University in 1983. The title of his thesis was “The Algebraic Manipulation of Constraints”. He spent many years as a VP & Fellow at Sun Microsystems. He has built satellite data acquisition systems, a multiprocessor version of Unix, several compilers, mail systems and window managers. He has also built a WYSIWYG text editor, a constraint based drawing editor and a text editor called `Emacs’ for Unix systems.

At Sun his early activity was as lead engineer of the NeWS window system. He did the original design of the Java programming language and implemented its original compiler and virtual machine. He has been a contributor to the Real-Time Specification for Java, and a researcher at Sun labs where his primary interest was software development tools. He then was the Chief Technology Officer of Sun’s Developer Products Group and the CTO of Sun’s Client Software Group. He briefly worked for Oracle after the acquisition of Sun. After a year off, he spent some time at Google and is now the chief software architect at Liquid Robotics where he spends his time writing software for the Wave Glider, an autonomous ocean-going robot.

Full Web Application with Tomcat JSF Primefaces JPA Hibernate

90

Posted on by

Hello, how are you?

We are happy for the 100k visitors. To celebrate this mark in this blog we created this post that will show how to create a full web application using the following tools: Tomcat7, JSF2 (Facelets and Libraries) with Primefaces (with AutoComplete), JPA / Hibernate (with a relationship NxN), Login with Filter.

If you want to see a full web application with JSF + EJB + JPA + JBoss 7 click here.

To run the code of this post you will need the artifacts bellow (all jar file you will find in the last page of this post):

You can use the any database you want, you will need the specific driver of the database and to edit the URL connection at the persistence.xml.

At the end of this post you will find the source code with all needed libraries to download.

What you will see today in this post:

  • Page 02: Entity classes of the model. A relationship NxN (@ManyToMany), NamedQueries with JoinFetch, Enum as attribute.
  • Page 03: Generic DAO, application transaction methods, generic methods to populate query parameters.
  • Page 04: Façades an transactions, using the method findReferenceOnly, care using the entityManager.merge() method.
  • Page 05: Filters.
  • Page 06: ManagedBeans. How to inject a ManagedBean inside another ManagedBean, observations about @ViewScoped.
  • Page 07: JSFMessageUtil.
  • Page 08: Configurations file: log4j.properties, messages.properties.
  • Page 09: xhtml pages, Facelets.
  • Page 10: Primefaces AutoComplete, JSF Converter with “forClass”.
  • Page 11: Easiest way to use CSS/javascript/images with JSF.
  • Page 12: “web.xml” configurations.
  • Page 13: Increasing the security of your application.
  • Page 14: Running the application.

The application that you will find in here will have a Dog and Person CRUD (Create, Read, Update, and Delete); only the ADMIN will have access to the Dog CRUD. Before you run this application you should create a database named “JSFCrudDB”.

Lazy JSF Datatable Pagination (Primefaces)

25

Posted on by

Hello, how are you?

Today we will do JSF datatable pagination with a Lazy List with a view scoped managed bean. What all those words/expressions mean?

There are several JSF frameworks today that provide datatables with a ready pagination, columns sorter and others functionalities. Today we will use the Primefaces datatable.

Usually the datatables will put the displayed List, with the entities, inside the user http session. Increasing the objects inside the user session will have a direct impact on the server performance; each user that displays a datatable,  that keeps a list in the session, will be allocating more and more memory in the server.

To look like real life, our post will use JPA and HSQLDB as database, and we will use JPQL to query the data.

In the end of this post you will find the link to download the source code.

We will use:

  • JSF 2.0 – JBoss 7 Implementation
  • JBoss 7.1 – the code of this post should be applied to all servers
  • Eclipse Indigo
  • JPA 2.0 – JBoss 7 Implementation
  • HSQLDB (2.2.8) – The HSQL it is a memory database, it will be easier to run it.
  • Primefaces 3.2

This post is not about good development practices nor about adding classes layers of project modeling. I just intend to show how to do a pagination without a session managed bean.

Full WebApplication JSF EJB JPA JAAS

71

Posted on by

Hello, how are you?

This post will be the biggest so far in my blog! We will see a full web application. It will be done will the newest technologies (until today), but I will give some hints to show how to adapt this post to older technologies.

In the end of this post you will find the source code to download. You can use it as you wish. Just go to the last page and do the download. \o/

If you downloaded the code and did not understand something, in this post I will explain every detail found in the code. Just read the subject inside this post that you want.

I will list bellow the technologies that I will use in this post:

  • JSF 2.0 Mojarra – With ManagedBeans as RequestScope and SessionScope.
  • Message Internationalization – File that will have all the messages of our system; it will be easier to translate you pages.
  • Default CSS file that will be imported as a library.
  • EJB 3 – Our DAOs and Façades will be @Stateless.
  • Generic DAO – A generic DAO that will have the CRUD actions to make our life easier.
  • JPA 2 – To map our classes in the DB
  • JAAS – To control the login and the user access to the pages.
  • MVC – I will use this pattern with small modifications.
  • Postgres as database, but I will show how to set up your app to MySQL also.

I will not use TDD – JUnit to test our View/Model/Classes, but in the following link you can see a technique to use the JUnit to test your ManagedBeans: JUnit with HSQLDB, JPA and Hibernate.

Tools that we will use:

This post will have several pages; this first page is just to show the technical details of the post today.

I will not code to interface my model/DAO, just to save space. Remember that you should always code to interfaces (Design Pattern – Strategy).

Before you go to the next pages be sure that you installed the JBoss Tools and the JBoss 7 in this exactly order.

JSF RESTFull Get Request Parameters

0

Posted on by

Hello, how are you?

How can we pass parameters through a URL using JSF 2.0? I believe this will be smallest post here.

At the end of this post you will find the link to download the created source code.

The other posts about JSF/Web Applications you can find in here: JSF Simple Ajax SamplesJSF Persisting Objects and Messages after a Redirect ,User Login Validation with JAAS and JSFJSF: Converter and Bean AutoCompleteJSF – Hello World, Auto CompleteHandling Exceptions on a WebAppUser Authentication (Filter/Servlet)Creating a WebServer.

Take a look bellow to see that is very easy to receive a parameter through a URL:

<!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>
	<f:metadata>
		<f:viewParam name="email" value="#{user.email}" />
		<f:viewParam name="name" value="#{user.name}" />
	</f:metadata>
</h:head>
<h:body>
	<h:form>
		Your email is: #{user.email} <br/>
		Your name is: #{user.name} <br/>
		Your name and email from MB: #{user.nameAndEmail} <br/>
	</h:form>
</h:body>
</html>
package demo;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

/**
 * Created by JBoss Tools
 */
@ManagedBean(name = "user")
@RequestScoped
public class User {

	private String email;
	private String name;

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getName() {
		return name;
	}

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

	public String getNameAndEmail(){
		return email + " " + name;
	}
}

The used URL to access that page is: http://localhost:8080/RequestParameter/values.xhtml?email=Read+Romans&name=Chapter10+Ver+09.

As you can see the page expects two parameters and in our ManagedBean exists a method that uses both parameters; in this method you could search for your entities in the database or any other action that you need.

How can we create a link to be navigated by the user? Piece of cake, take a look at the page/code bellow:

<!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>

</h:head>
<h:body>
	<h:form>
		01) A pre-formed link: <br/>
		<h:link outcome="values?email=Read Romans&amp;name=Chapter10 Ver 09" value="Let us go!" />
		<br/>
		<br/>
		02)Link with the f:param component<br/>
		<h:link outcome="values" value="Write all params and let us go!" >
			<f:param name="email" value="Read Romans" />
			<f:param name="name" value="Chapter10 Ver 09" />
		</h:link>
		<br/>
		<br/>
		03) <h:commandLink value="Redirect Me!" action="values?faces-redirect=true&amp;email=Read Romans&amp;name=Chapter10 Ver 09" />
	</h:form>
</h:body>
</html>
<!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>
	<f:metadata>
		<f:viewParam name="email" value="#{user.email}" />
		<f:viewParam name="name" value="#{user.name}" />
	</f:metadata>
</h:head>
<h:body>
	<h:form>
		Your email is: #{user.email} <br/>
		Your name is: #{user.name} <br/>
		Your name and email from MB: #{user.nameAndEmail} <br/>

		04) <h:link outcome="values" value="Get everybody and leave this place" includeViewParams="true" />
	</h:form>
</h:body>
</html>


I will talk about each approach used in the codes to generate the links (according to each number used like 01, 02…):

  • 01)  A pre-formed link that has all the parameters written in it.
  • 02)  We are using the “f:param” component that gives us a cleaner code.
  • 03)  A link that will use the redirect to navigate through the commandLink component. BE CAREFULL: until today, the JSF will not send paramters in a redirect if you use the “f:param” component. That is why I wrote all URL in the link with the redirect. “<h:commandLink action=”values?faces-redirect=true”.
  • 04)  Using this approach with the option (includeViewParams=”true”) you will automatically includ all the “f:viewParam” that are present in the view. You will not need to write them in the “h:link” component. JSF will gather all the parameters for you.

You can also add parameters when you use the navigation through the “faces-config.xml”:

<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="2.0" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xi="http://www.w3.org/2001/XInclude" 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-facesconfig_2_0.xsd">
	<navigation-rule>
		<navigation-case>
			<from-outcome>redirectMe</from-outcome>
			<to-view-id>/myPage.xhtml</to-view-id>
			<redirect include-view-params="true">
				<view-param>
					<name>calculatedValue</name>
					<value>#{myBean.value}</value>
				</view-param>
			</redirect>
		</navigation-case>
	</navigation-rule>
</faces-config>

The code from this post will work with the “h:link” or the “h:commandLink” and both can be used with the redirect option.

I also want to remind you that your URL can be wrote in a ManagedBean and the value used like #{youMB.createTheURL} in the “link/commandLink” components.

Click here to download the source code.

I hope this post helps you.

If you have any question/doubt/suggestion just post it.

See you soon. \o_

JSF Simple Ajax Samples

0

Posted on by

Hello, how are you?

Today we will see some Simple Samples of Ajax with JSF.

If you want to see other posts about JSF/Web Applications click on the next links: JSF Persisting Objects and Messages after a Redirect ,User Login Validation with JAAS and JSFJSF: Converter and Bean AutoComplete, JSF – Hello World, Auto Complete, Handling Exceptions on a WebApp, User Authentication (Filter/Servlet), Creating a WebServer.

In the end of this post you will find the link to download the source code of the samples. In this post (User Login Validation with JAAS and JSF) I show how to install the JBoss 6 in case you want to run the project from today. You will need to install the JBoss tools plugin in your Eclipse.

Take a look at the page bellow and its code:

<!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>
</h:head>
<h:body>
	<h:form>
		Your Name: <h:inputText id="inputname" label="${msgs.prompt}" value="#{user.name}"/>
		<br />
		<h:commandButton action="#{user.sayHello}" value="Display my name here, now!"/>
		<br />
	</h:form>
</h:body>
</html>

How could we display the typed name in the same screen using Ajax? Piece of cake, just add the “f:ajax” component. Check the code update and the result:

<!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>
</h:head>
<h:body>
	<h:form>
		Your Name: <h:inputText id="inputname" label="${msgs.prompt}" value="#{user.name}"/>
		<br />
		<h:commandButton action="#{user.sayHello}" value="Display my name here, now!">
			<f:ajax render="myName" execute="inputname" />
		</h:commandButton>
		<br />
		<br />
		<h:outputText id="myName" value="#{user.name}" />
	</h:form>
</h:body>
</html>

It is very easy right? We just need to pass the value that will be carried to the ManagedBean by the “execute” parameter; with the “render” parameter we will tell to the JSF which component will be “refreshed”.

Notice also that the typed name appears in the Console.

With this code we can “refresh” all kind of components. Let us see another sample?

Let us display an error message if the user types a name with less than 4 characters.

Check our new message and the new code:

<!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>
</h:head>
<h:body>
	<h:form>
		<h:messages id="myMessage" globalOnly="true" showDetail="true"/>
		Your Name: <h:inputText id="inputname" label="${msgs.prompt}" value="#{user.name}"/>
		<br />
		<h:commandButton action="#{user.sayHello}" value="Display my name here, now!">
			<f:ajax render="myName myMessage" execute="inputname" />
		</h:commandButton>
		<br />
		<br />
		<h:outputText id="myName" value="#{user.name}" />
	</h:form>
</h:body>
</html>
package demo;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;

/**
 * Created by JBoss Tools
 */
@ManagedBean(name = "user")
@RequestScoped
public class User {

	private String name;

	public String sayHello() {
		if (isNameIncorrect()) {
			FacesContext context = FacesContext.getCurrentInstance();
			context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Too small", "Can you write it a little bigger?"));
		}

		System.out.println(name);
		return null;
	}

	private boolean isNameIncorrect() {
		return "".equals(name.trim()) || name.length() < 3;
	}

	public String getName() {
		return name;
	}

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

Notice that we have the component “h:messages” and its ID is used in the “f:ajax” component. This code also works when you use the “h:message for=“YYY”” component.

What if we work now with comboboxes? Let us display a combobox that will contain 4 items when we have a name with less than 6 characters, and a list with more than 4 items if the typed name has more than 6 characters.

package demo;

import java.util.ArrayList;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UISelectItems;
import javax.faces.component.html.HtmlSelectOneMenu;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;

/**
 * Created by JBoss Tools
 */
@ManagedBean(name = "user")
@RequestScoped
public class User {

	private String name;

	private List<String> cars;

	private String selectedCar;
	private HtmlSelectOneMenu htmlSelectCars;

	private static final String SELECT_A_CAR = "Select One Car";

	public User() {
		cars = new ArrayList<String>();
	}

	public String sayHello() {
		if (isNameInCorrect()) {
			FacesContext context = FacesContext.getCurrentInstance();
			context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Too small", "Can you write it a little bigger?"));
		}

		System.out.println(name);
		return null;
	}

	private boolean isNameInCorrect() {
		return name == null || "".equals(name.trim()) || name.length() < 3;
	}

	public String getName() {
		return name;
	}

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

	public void editMyCarsList(AjaxBehaviorEvent event) {
		if (htmlSelectCars == null) {
			htmlSelectCars = new HtmlSelectOneMenu();
		}

		htmlSelectCars.getChildren().clear();

		UISelectItems items = new UISelectItems();
		items.setValue(getCars());
		htmlSelectCars.getChildren().add(items);
	}

	public List<String> getCars() {
		cars.clear();

		cars.add(SELECT_A_CAR);

		if (!isNameInCorrect() && name.length() >= 6) {
			cars.add("Ferrari");
			cars.add("Porch");
			cars.add("Beetle");
			cars.add("Opala");
			cars.add("Passat");
			cars.add("Vectra");
			cars.add("Chevet");
			cars.add("Corvet");
		} else {
			cars.add("Ferrari");
			cars.add("Porch");
			cars.add("Beetle");
			cars.add("Opala");
		}

		return cars;
	}

	public void setCars(List<String> cars) {
		this.cars = cars;
	}

	public String getSelectedCar() {
		return selectedCar;
	}

	public void setSelectedCar(String selectedCar) {
		this.selectedCar = selectedCar;
	}

	public HtmlSelectOneMenu getHtmlSelectCars() {
		editMyCarsList(null);

		return htmlSelectCars;
	}

	public void setHtmlSelectCars(HtmlSelectOneMenu htmlSelectCars) {
		this.htmlSelectCars = htmlSelectCars;
	}
}

Take a look now at our page:

<!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>
</h:head>
<h:body>
	<h:form>
		<h:messages id="myMessage" globalOnly="true" showDetail="true" />
		Your Name: <h:inputText id="inputname" label="${msgs.prompt}" value="#{user.name}" />
		<br />
		<h:commandButton action="#{user.sayHello}" value="Display my name here, now!">
			<f:ajax render="myName myCars myMessage" execute="inputname" listener="#{user.editMyCarsList}" />
		</h:commandButton>
		<br />
		<br />
		<h:outputText id="myName" value="#{user.name}" />
		<br />
		<br />
		Choose your car: <h:selectOneMenu id="myCars" binding="#{user.htmlSelectCars}" value="#{user.selectedCar}" />
		<br />
		<br />
	</h:form>
</h:body>
</html>

Notice that our combobox items size is updated according to the typed name. At the end of this post I will talk more about why I used the binding attribute to the HtmlSelectOneMenu instead returning the List<String>.

As our last sample, let us create a combobox that will appear and disappear according to the selected value in the Car combobox.

Take a look at our ManagedBean:

package demo;

import java.util.ArrayList;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UISelectItems;
import javax.faces.component.html.HtmlSelectOneMenu;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;

/**
 * Created by JBoss Tools
 */
@ManagedBean(name = "user")
@RequestScoped
public class User {

	private String name;

	private List<String> cars;
	private List<String> colors;

	private String selectedCar;
	private String selectedColor;
	private HtmlSelectOneMenu htmlSelectCars;

	private static final String SELECT_A_CAR = "Select One Car";

	public User() {
		cars = new ArrayList<String>();
		colors = new ArrayList<String>();

		colors.add("Red");
		colors.add("Blue");
		colors.add("Orange");
		colors.add("Pink --> O.o");
	}

	public String sayHello() {
		if (isNameInCorrect()) {
			FacesContext context = FacesContext.getCurrentInstance();
			context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Too small", "Can you write it a little bigger?"));
		}

		System.out.println(name);
		return null;
	}

	private boolean isNameInCorrect() {
		return name == null || "".equals(name.trim()) || name.length() < 3;
	}

	public String getName() {
		return name;
	}

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

	public void editMyCarsList(AjaxBehaviorEvent event) {
		if (htmlSelectCars == null) {
			htmlSelectCars = new HtmlSelectOneMenu();
		}

		htmlSelectCars.getChildren().clear();

		UISelectItems items = new UISelectItems();
		items.setValue(getCars());
		htmlSelectCars.getChildren().add(items);
	}

	public List<String> getCars() {
		cars.clear();

		cars.add(SELECT_A_CAR);

		if (!isNameInCorrect() && name.length() >= 6) {
			cars.add("Ferrari");
			cars.add("Porch");
			cars.add("Beetle");
			cars.add("Opala");
			cars.add("Passat");
			cars.add("Vectra");
			cars.add("Chevet");
			cars.add("Corvet");
		} else {
			cars.add("Ferrari");
			cars.add("Porch");
			cars.add("Beetle");
			cars.add("Opala");
		}

		return cars;
	}

	public void setCars(List<String> cars) {
		this.cars = cars;
	}

	public String getSelectedCar() {
		return selectedCar;
	}

	public void setSelectedCar(String selectedCar) {
		this.selectedCar = selectedCar;
	}

	public List<String> getColors() {
		return colors;
	}

	public void setColors(List<String> colors) {
		this.colors = colors;
	}

	public boolean isColorsAlloweToDisplay() {
		if (isNameInCorrect()) {
			return false;
		}

		if (selectedCar == null || selectedCar.trim().equals("") || selectedCar.equals(SELECT_A_CAR)) {
			return false;
		}

		return true;
	}

	public String getSelectedColor() {
		return selectedColor;
	}

	public void setSelectedColor(String selectedColor) {
		this.selectedColor = selectedColor;
	}

	public HtmlSelectOneMenu getHtmlSelectCars() {
		editMyCarsList(null);

		return htmlSelectCars;
	}

	public void setHtmlSelectCars(HtmlSelectOneMenu htmlSelectCars) {
		this.htmlSelectCars = htmlSelectCars;
	}
}

Our ManagedBean were lightly updated, we just added a List with a method that return a list of colors that will populate our combobox; we added also a method that will return a Boolean – true if the combobox is allowed to be displayed.

Check our new page:

<!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>
</h:head>
<h:body>
	<h:form>
		<h:messages id="myMessage" globalOnly="true" showDetail="true" />
		Your Name: <h:inputText id="inputname" label="${msgs.prompt}" value="#{user.name}" />
		<br />
		<h:commandButton action="#{user.sayHello}" value="Display my name here, now!">
			<f:ajax render="myName myCars myMessage myColors" execute="inputname" listener="#{user.editMyCarsList}" />
		</h:commandButton>
		<br />
		<br />
		<h:outputText id="myName" value="#{user.name}" />
		<br />
		<br />
		Choose your car:
		<h:selectOneMenu id="myCars" binding="#{user.htmlSelectCars}" value="#{user.selectedCar}">
			<f:ajax render="myColors" execute="inputname myCars"/>
		</h:selectOneMenu>
		<br />
		<br />
		<h:panelGroup id="myColors">
			<h:selectOneMenu value="#{user.selectedColor}" rendered="#{user.colorsAlloweToDisplay}">
				<f:selectItems value="#{user.colors}" />
			</h:selectOneMenu>
		</h:panelGroup>
	</h:form>
	</h:body>
</html>

I will talk about the code used in the post:

  • HtmlSelectOneMenu – I used the component instead a List because the JSF is not so good in render the components in the user screen (DOM Tree). If your combobox has 4 lines and by using ajax you add more lines to the List, the JSF/Ajax will not recognize the new added lines; you will be able to use only the older values. You can try to use the code with a List<String> instead using the HtmlSelectOneMenu and see the result; I spend like 3~4 hours to understand this by a lot of searches on the internet.
  • HtmlSelectOneMenu inside the “h:panelGroup” component – I did this because every time you want to render a non rendered component you need to update its container. If our selectOne were inside the same form of the car selectOne you would need to render all form.

Click here to download the code from this post.

I hope this post might help you.

If you have any question/doubt/suggestion just post it.

See you later. \o_

JSF Persisting Objects and Messages after a Redirect

0

Posted on by

Hello, how are you?

Let us talk today about how to send messages with JSF after a redirect action. The redirect action will not carry any data from the first request; sometimes you will not have the value to be displayed.

We often see this happen in an application with a heavy use of Ajax; sometimes to navigate between the pages you will need to use the redirect command.

The other posts of JSF/Web you can find in here: User Login Validation with JAAS and JSFJSF: Converter and Bean AutoComplete, JSF – Hello World, Auto Complete, Handling Exceptions on a WebApp, User Authentication (Filter/Servlet), Creating a WebServer.

In the end of the post you will find the link to download the source code of today’s post.

Today we will see two ways to send an object and/or a message after a redirect. We will use the Flash Scope (JSF 2.0 API) or creating a class to control the JSF phases (works on JSF 1.2 or a higher version).

Bellow you will see some images of the project screen shots and a few codes:

/*******************************************************************************
 * Copyright (c) 2010 Red Hat, Inc.
 * Distributed under license by Red Hat, Inc. All rights reserved.
 * This program is made available under the terms of the
 * Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Red Hat, Inc. - initial API and implementation
 ******************************************************************************/
package demo;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

/**
 * Created by JBoss Tools
 */
@ManagedBean(name="user")
@RequestScoped
public class User {
	private String name;

	public User() {
	}

	public String getName() {
		return name;
	}

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

	public String sayHello() {
		return "greeting";
	}
}
<?xml version="1.0" encoding="UTF-8"?>

<faces-config
    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-facesconfig_2_0.xsd"
	version="2.0">

	<navigation-rule>
		<from-view-id>/pages/inputname.xhtml</from-view-id>
		<navigation-case>
			<from-outcome>greeting</from-outcome>
			<to-view-id>/pages/greeting.xhtml</to-view-id>
		</navigation-case>
	</navigation-rule>

    <application>
        <resource-bundle>
            <base-name>resources</base-name>
            <var>msgs</var>
        </resource-bundle>
    </application>
</faces-config>

I will edit now the “faces-config.xml”; we will use the redirect to navigate between the pages. The code bellow will show how our file will be (take a look at the line 14):

<?xml version="1.0" encoding="UTF-8"?>

<faces-config
    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-facesconfig_2_0.xsd"
	version="2.0">

	<navigation-rule>
		<from-view-id>/pages/inputname.xhtml</from-view-id>
		<navigation-case>
			<from-outcome>greeting</from-outcome>
			<to-view-id>/pages/greeting.xhtml</to-view-id>
			<redirect/>
		</navigation-case>
	</navigation-rule>

    <application>
        <resource-bundle>
            <base-name>resources</base-name>
            <var>msgs</var>
        </resource-bundle>
    </application>
</faces-config>


Where is Peter? That is what happens when we use the redirect and the object is not in the session scope. To fix this “problem” we will use the not so popular Flash Scope.

Let us edit the User class (take a look at the lines 38, 39):

/*******************************************************************************
 * Copyright (c) 2010 Red Hat, Inc.
 * Distributed under license by Red Hat, Inc. All rights reserved.
 * This program is made available under the terms of the
 * Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Red Hat, Inc. - initial API and implementation
 ******************************************************************************/
package demo;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

import com.sun.faces.context.flash.ELFlash;

/**
 * Created by JBoss Tools
 */
@ManagedBean(name="user")
@RequestScoped
public class User {
	private String name;

	public User() {
	}

	public String getName() {
		return name;
	}

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

	public String sayHello() {
		// Put the object inside the flash scope
		ELFlash.getFlash().put("user", this);
		return "greeting";
	}
}

And to access the user object in the Flash Scope, you just have to edit your page:

<!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">

	<ui:composition template="/templates/common.xhtml">
			<ui:define name="pageTitle">Greeting to User</ui:define>
			<ui:define name="pageHeader">Greeting Page</ui:define>
			<ui:define name="body">
				#{msgs.greeting} #{flash.user.name}!
			</ui:define>
	</ui:composition>
</html>

Now we will be able to meet Peter again:

The Flash scope keeps the object just like if it was a session scope. Pay attention to the fact that after you use the object “user” that is stored inside the flash scope, the object will be removed. How can you keep an object inside the Flash Scope after we use it? Piece of cake, just edit the invocation:

      #{flash.user.name}

For

      #{flash.keep.user.name}

If you use the last line your object will remain inside the Flash Scope.

To JSF 1.2: Unfortunately the only way to keep an object / message after a redirect (until today) is controlling it inside the session. =/ BUT, if you want just to send an alert (message) to the next screen there is another solution.

I will create another page to display the welcome message as an alert “<h:messages/>”. Take a look at our new code:

<!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"
	xmlns:ez="http://java.sun.com/jsf/composite/demo">

	<ui:composition template="/templates/common.xhtml">

		<ui:define name="pageTitle">Input User Name</ui:define>

		<ui:define name="pageHeader">JSF 2 Hello Application</ui:define>

		<ui:define name="body">
			<h:message showSummary="true" showDetail="false" style="color: red; font-weight: bold;" for="inputname" />
			<ez:input id="inputname" label="${msgs.prompt}" value="#{user.name}" action="#{user.sayHello}" submitlabel="Say Hello"/>
			<ez:input id="inputname2" label="${msgs.prompt}" value="#{user.name}" action="#{user.sayHelloWithAlert}" submitlabel="Say Hello With Alert"/>
		</ui:define>
	</ui:composition>
</html>
<!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">

	<ui:composition template="/templates/common.xhtml">
			<ui:define name="pageTitle">Greeting to User With alert</ui:define>
			<ui:define name="pageHeader">Greeting Page With alert</ui:define>
			<ui:define name="body">
				<h:messages />
			</ui:define>
	</ui:composition>
</html>
/*******************************************************************************
 * Copyright (c) 2010 Red Hat, Inc.
 * Distributed under license by Red Hat, Inc. All rights reserved.
 * This program is made available under the terms of the
 * Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Red Hat, Inc. - initial API and implementation
 ******************************************************************************/
package demo;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;

import com.sun.faces.context.flash.ELFlash;

/**
 * Created by JBoss Tools
 */
@ManagedBean(name="user")
@RequestScoped
public class User {
	private String name;

	public User() {
	}

	public String getName() {
		return name;
	}

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

	public String sayHello() {
		// Put the object inside the flash scope
		ELFlash.getFlash().put("user", this);
		return "greeting";
	}

	public String sayHelloWithAlert() {
		String message = "Hello : " + name;
		FacesContext context = FacesContext.getCurrentInstance();

		context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, message, message));

		return "greetingWithAlert";
	}
}
<?xml version="1.0" encoding="UTF-8"?>

<faces-config
    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-facesconfig_2_0.xsd"
	version="2.0">

	<navigation-rule>
		<from-view-id>/pages/inputname.xhtml</from-view-id>
		<navigation-case>
			<from-outcome>greeting</from-outcome>
			<to-view-id>/pages/greeting.xhtml</to-view-id>
			<redirect/>
		</navigation-case>
		<navigation-case>
			<from-outcome>greetingWithAlert</from-outcome>
			<to-view-id>/pages/greetingWithAlert.xhtml</to-view-id>
		</navigation-case>
	</navigation-rule>

    <application>
        <resource-bundle>
            <base-name>resources</base-name>
            <var>msgs</var>
        </resource-bundle>
    </application>
</faces-config>


But, if we use the redirect action our message will not be displayed:

<?xml version="1.0" encoding="UTF-8"?>

<faces-config
    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-facesconfig_2_0.xsd"
	version="2.0">

	<navigation-rule>
		<from-view-id>/pages/inputname.xhtml</from-view-id>
		<navigation-case>
			<from-outcome>greeting</from-outcome>
			<to-view-id>/pages/greeting.xhtml</to-view-id>
			<redirect/>
		</navigation-case>
		<navigation-case>
			<from-outcome>greetingWithAlert</from-outcome>
			<to-view-id>/pages/greetingWithAlert.xhtml</to-view-id>
			<redirect/>
		</navigation-case>
	</navigation-rule>

    <application>
        <resource-bundle>
            <base-name>resources</base-name>
            <var>msgs</var>
        </resource-bundle>
    </application>
</faces-config>


The solution bellow I found in the site: “ocpsoft.com/java/persist-and-pass-facesmessages-over-page-redirects/”.

The class bellow will get your message and store it in the session scope. Once the message was displayed it will be removed from the session scope. This is a very useful solution to prolong the scope of a message:

package demo;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;

/**
 * Enables messages to be rendered on different pages from which they were set.
 *
 * After each phase where messages may be added, this moves the messages
 * from the page-scoped FacesContext to the session-scoped session map.
 *
 * Before messages are rendered, this moves the messages from the
 * session-scoped session map back to the page-scoped FacesContext.
 *
 * Only global messages, not associated with a particular component, are
 * moved. Component messages cannot be rendered on pages other than the one on
 * which they were added.
 *
 * To enable multi-page messages support, add a <code>lifecycle</code> block to your
 * faces-config.xml file. That block should contain a single
 * <code>phase-listener</code> block containing the fully-qualified classname
 * of this file.
 *
 * @author Jesse Wilson jesse[AT]odel.on.ca
 * @secondaryAuthor Lincoln Baxter III lincoln[AT]ocpsoft.com
 */
public class MultiPageMessagesSupport implements PhaseListener
{

    private static final long serialVersionUID = 1250469273857785274L;
    private static final String sessionToken = "MULTI_PAGE_MESSAGES_SUPPORT";

    public PhaseId getPhaseId()
    {
        return PhaseId.ANY_PHASE;
    }

    /*
     * Check to see if we are "naturally" in the RENDER_RESPONSE phase. If we
     * have arrived here and the response is already complete, then the page is
     * not going to show up: don't display messages yet.
     */
    // TODO: Blog this (MultiPageMessagesSupport)
    public void beforePhase(final PhaseEvent event)
    {
        FacesContext facesContext = event.getFacesContext();
        this.saveMessages(facesContext);

        if (PhaseId.RENDER_RESPONSE.equals(event.getPhaseId()))
        {
            if (!facesContext.getResponseComplete())
            {
                this.restoreMessages(facesContext);
            }
        }
    }

    /*
     * Save messages into the session after every phase.
     */
    public void afterPhase(final PhaseEvent event)
    {
        if (!PhaseId.RENDER_RESPONSE.equals(event.getPhaseId()))
        {
            FacesContext facesContext = event.getFacesContext();
            this.saveMessages(facesContext);
        }
    }

    @SuppressWarnings("unchecked")
    private int saveMessages(final FacesContext facesContext)
    {
        List<FacesMessage> messages = new ArrayList<FacesMessage>();
        for (Iterator<FacesMessage> iter = facesContext.getMessages(null); iter.hasNext();)
        {
            messages.add(iter.next());
            iter.remove();
        }

        if (messages.size() == 0)
        {
            return 0;
        }

        Map<String, Object> sessionMap = facesContext.getExternalContext().getSessionMap();
        List<FacesMessage> existingMessages = (List<FacesMessage>) sessionMap.get(sessionToken);
        if (existingMessages != null)
        {
            existingMessages.addAll(messages);
        }
        else
        {
            sessionMap.put(sessionToken, messages);
        }
        return messages.size();
    }

    @SuppressWarnings("unchecked")
    private int restoreMessages(final FacesContext facesContext)
    {
        Map<String, Object> sessionMap = facesContext.getExternalContext().getSessionMap();
        List<FacesMessage> messages = (List<FacesMessage>) sessionMap.remove(sessionToken);

        if (messages == null)
        {
            return 0;
        }

        int restoredCount = messages.size();
        for (Object element : messages)
        {
            facesContext.addMessage(null, (FacesMessage) element);
        }
        return restoredCount;
    }
}

And as our last action, let us edit the “faces-config.xml”:

<?xml version="1.0" encoding="UTF-8"?>

<faces-config
    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-facesconfig_2_0.xsd"
	version="2.0">

	<navigation-rule>
		<from-view-id>/pages/inputname.xhtml</from-view-id>
		<navigation-case>
			<from-outcome>greeting</from-outcome>
			<to-view-id>/pages/greeting.xhtml</to-view-id>
			<redirect/>
		</navigation-case>
		<navigation-case>
			<from-outcome>greetingWithAlert</from-outcome>
			<to-view-id>/pages/greetingWithAlert.xhtml</to-view-id>
			<redirect/>
		</navigation-case>
	</navigation-rule>
	<lifecycle>
		<phase-listener>demo.MultiPageMessagesSupport</phase-listener>
	</lifecycle>	

    <application>
        <resource-bundle>
            <base-name>resources</base-name>
            <var>msgs</var>
        </resource-bundle>
    </application>
</faces-config>

Deploy the application again and guess who is back? Peter! \o/

If you want to download the source code of this post, click here. To run this code, you will need to have the JBoss 6 configured in your Eclipse. But to set up the JBoss 6 in you Eclipse you will need the JBoss tools. If you need some help to install the JBoss Tools check this post: User Login Validation with JAAS and JSF.

I hope this post might help you.

If you have any question or comment just post it.

This post was based on:

  • Book: “Core JavaServer Faces” Chapter: “Redirection and Flash”
  • JSF source code generated by the JBoss tools
  • The class to persist the message through the redirect: “ocpsoft.com/”

See you soon! \o_

User Login Validation with JAAS and JSF

14

Posted on by

Hello, how are you?

In another post I have talked about a User validation using Servlet / Filter. Today we will see another way of doing it, we will use JSF and JAAS.

The JAAS validation uses the server as tools to validate the user, his password and the role that the user has. You will not need to validate the user (programmatically) at every http request.

He are the others posts about web in my blog: JSF: Converter and Bean AutoComplete, JSF – Hello World, Auto Complete, Handling Exceptions on a WebApp, User Authentication (Filter/Servlet), Creating a WebServer.

We will use today JSF, Postgres, Eclipse and JBoss AS 6:

I will use the JBoss Tools just to help us with the JSF and allow us to use the JBoss 6 inside the Eclipse. You can create all the code posted here and put the WAR inside the JBoss folder and run it without the need of the Eclipse. In the beginning of the post I have listed a link with a “how-to” about a JSF application.

I will not show how to install the Postgres database because it is out of the scope of this post, but you can use any database that you want like MySQL, SqlServer, Oracle, etc.

To install the JBoss you just have to unzip it and it will be ready to be used.

Unzip the Eclipse and install the JBoss Tools. It is a really helpful tool when we work with JBoss and JSF.

  •   To make it easier I have selected this two options:

  • Then Finish the installation.

To install the server just need to click in the tab “Servers” > New >Server

Select JBoss 6 > Next

Select the path where you unzipped your JBoss:

And click in the “Finish” button.

Let us create a new JSF project (File > New > Project). I will use a project created by the JBoss Tools. If you want to create a JSF project by yourself, check the link in the begging of this post about JSF.

I am naming the application “LoginJSF”, select JSF 2.0 and click in Finish.

The Eclipse will ask you if you want to change to the web view, I clicked on the “No” button. You can click Yes later to see this view.

The Eclipse will create an application with a basic navigation. Notice that the Eclipse already added your application to the server, if it did not added, click with the right button of the mouse on the project name > Run As > Run on Server. Select JBoss.


Run the server and access by the link: http://localhost:8080/LoginJSF/pages/inputname.jsf

Stop the JBoss and let us create 3 folders:

  • A folder with public access
  • A folder only to admin access
  • A folder to user and admin access

<?xml version="1.0"?>
<!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:h="http://java.sun.com/jsf/html"
      xmlns:composite="http://java.sun.com/jsf/composite">

    <h:head>
        I am public! [=
    </h:head>
    <h:body>
        Everyone can see me. \o/
    </h:body>
</html>
<?xml version="1.0"?>
<!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:h="http://java.sun.com/jsf/html"
      xmlns:composite="http://java.sun.com/jsf/composite">

    <h:head>
        Yes master admin! Welcome!
    </h:head>
    <h:body>
        Let us run this business!
    </h:body>
</html>
<?xml version="1.0"?>
<!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:h="http://java.sun.com/jsf/html"
      xmlns:composite="http://java.sun.com/jsf/composite">

    <h:head>
        Welcome mister user!
    </h:head>
    <h:body>
        <br/>
        Please, do not create any bugs, ok?! >=)
    </h:body>
</html>

Now let us start the JAAS configuration. Let us start editing the web.xml file indicating which folders are protected:

<?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">
    <display-name>LoginJSF</display-name>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
        <url-pattern>*.jsf</url-pattern>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>

    <!-- Protected Areas -->
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Only admins</web-resource-name>
            <url-pattern>/pages/protected/admin/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>ADMIN</role-name>
        </auth-constraint>
    </security-constraint>
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Users and admins</web-resource-name>
            <url-pattern>/pages/protected/user/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>ADMIN</role-name>
            <role-name>USER</role-name>
        </auth-constraint>
    </security-constraint>

    <!-- Validation By Form -->
    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/pages/public/login.xhtml</form-login-page>
            <form-error-page>/pages/public/loginError.xhtml</form-error-page>
        </form-login-config>
    </login-config>

    <!-- Allowed Roles -->
    <security-role>
        <role-name>ADMIN</role-name>
    </security-role>
    <security-role>
        <role-name>USER</role-name>
    </security-role>

    <!-- Filter to get the user name and work with it -->
    <filter>
        <filter-name>LoginFilter</filter-name>
        <filter-class>com.filters.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <url-pattern>/pages/protected/*</url-pattern>
    </filter-mapping>
</web-app>

We will need a page to login and another page to be displayed if any error happens. Take a closer look at web.xml and you will see these pages described there.

<!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:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
    JSF 2 Login
</h:head>
<h:body>
    <p>Login to access secure pages:</p>
    <form method="post" action="j_security_check">
        <h:panelGrid columns="2">
            <h:outputLabel for="j_username" value="Username" />
            <input type="text" id="j_username" name="j_username" />
            <h:outputLabel for="j_password" value="Password" />
            <input type="password" id="j_password" name="j_password" />
            <input type="submit" name="submit" value="Login" />
        </h:panelGrid>
        <br />
    </form>
</h:body>
</html>
<!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:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
    JSF 2 Login
</h:head>
<h:body>
    <p>Ops! Check your user and password</p>
</h:body>
</html>

Let us create a java Filter that will catch the login (user name) that was typed. With this login (user name) you will be able to search for the user in the database and put it in the session.

package com.filters;

import java.io.IOException;

import javax.servlet.*;

import org.jboss.security.SecurityAssociation;

public class LoginFilter implements Filter {

    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException,
            ServletException {

        String userName = SecurityAssociation.getPrincipal().getName();

        System.out.println("Yeeey! Get me here and find me in the database: " + userName);

        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
}

Let us create now our database tables.

I will use the simplest database possible, with only two tables and a few columns.
Create a database named LoginJSF and run the script bellow:

CREATE TABLE "users"
(
  "name" character varying(50),
  pass character varying(50)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE "users" OWNER TO postgres;

CREATE TABLE user_roles
(
  user_name character varying(50),
  role_name character varying
)
WITH (
  OIDS=FALSE
);
ALTER TABLE user_roles OWNER TO postgres;

Let us insert two users, one with the USER role and another with the ADMIN role:

INSERT INTO users("name", pass) VALUES ('user', 'user');
INSERT INTO users("name", pass) VALUES ('admin', 'admin');
INSERT INTO user_roles(user_name, role_name) VALUES ('user', 'USER');
INSERT INTO user_roles(user_name, role_name) VALUES ('admin', 'ADMIN');

We are almost there, have a little bit more of patient. [=

We need to edit the file “login-config.xml” of the JBoss. You will find this file at “/JBOSS_THAT_YOU_UNZIPPED/server/default/conf/“. Add the lines bellow near the other tags named “application-policy”:

<!-- Others application-policy -->

<!-- ..................... -->

<!-- Security Profile Of our Software-->
<application-policy name="LoginJSFRealm">
    <authentication>
        <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required">
            <module-option name="dsJndiName">java:/LoginJSFRealmDS</module-option>
            <module-option name="principalsQuery">select pass from users where name=?</module-option>
            <module-option name="rolesQuery">select role_name, 'Roles' from user_roles where user_name = ?</module-option>
        </login-module>
    </authentication>
</application-policy>

We just gave to the JBoss a Realm to use: LoginJSFRealm. Now we need to let the JBoss know that our app will use this Realm. Let us create a file named “jboss-web.xml” inside the folder WEB-INF with the code bellow:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
    <!-- Links with JBoss the Realm to use -->
    <security-domain>java:/jaas/LoginJSFRealm</security-domain>
</jboss-web>

In the file “login-config.xml” we informed the JBoss to use a datasource named “LoginJSFRealmDS”. Through this datasource the JBoss will connect to the database. Let us create a file named “LoginJSFRealm-ds.xml” inside the folder “/JBOSS_THAT_YOU_UNZIPPED/server/default/deploy/“:

<?xml version="1.0" encoding="UTF-8"?>

<datasources>
    <local-tx-datasource>
        <jndi-name>LoginJSFRealmDS</jndi-name>
        <connection-url>jdbc:postgresql://localhost:5432/LoginJSF</connection-url>
        <driver-class>org.postgresql.Driver</driver-class>
        <user-name>postgres</user-name>
        <password>YOUR_PASSWORD</password>
        <!-- sql to call when connection is created. Can be anything, select 1 is valid for PostgreSQL <new-connection-sql>select 1</new-connection-sql> -->

        <!-- sql to call on an existing pooled connection when it is obtained from pool. Can be anything, select 1 is valid for PostgreSQL <check-valid-connection-sql>select
            1</check-valid-connection-sql> -->

        <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
        <metadata>
            <type-mapping>PostgreSQL 7.2</type-mapping>
        </metadata>
    </local-tx-datasource>
</datasources>

To finish this tutorial, copy the Postgres Driver JDBC 4 that you downloaded into the folder “/JBOSS_THAT_YOU_UNZIPPED/server/default/lib/“.

Let us run our application! \o/

Access the public link first: http://localhost:8080/LoginJSF/pages/public/public.html

Let us access the protected area where only the admin may enter: http://localhost:8080/LoginJSF/pages/protected/admin/admin.html

Type and user and the password and it is done. You will log in.

What if a USER accesses the admin URL? What will happen?

Try the same with the USER trough the URL: http://localhost:8080/LoginJSF/pages/protected/user/user.html
We cannot forget about the message that were be displayed in our console:
With the filter you will be able to search in your database for a user with the user name typed in the login page and put the user in the session.

Note 1: Your filter will be invoked only if the user login with success. The job to validate if the password/login is correct we leave to the JBoss.

Note 2: If you type the right login/password and the error page is displayed check again the JBoss datasource data, if the datasource name declared in the login-config.xml is the same declared in the file with the “-ds.xml” in its name, if the configurations inside the datasource are correct like: password, database, connection URL.

Note 3: Just after I finish the post I notice that I named the pages with html and not with xhtml (user.html,admin.html, pubilc.html). You can rename this pages and access again to see the JSF working (do not forget to change the link also before you access, it will finish with xhtml and not html). My bad! =/

I hope this post helps you.

Any doubt, question or suggestions just post it.

See you soon! \o_

1 2