Skip to main content

What do you think about a litle of Convention over Configuration for the JSF programming? if you like the idea, than read this ...

Posted by urubatan on December 14, 2006 at 11:15 AM PST

<Versão em portugues aqui>



I think JSF ia a great technology for web development, and it gets better if you mix it with the SPring Framework, but I also think it has the same problem that Java EE 1.4 has, you have to configure every thing before you can do any think ...

and it is a lot of configuration.

I do not think that configuration is a bad thing, I think that you must be able to configure, but I do not think you must be obligated to configure any thing ...



the Spring-Annotation has a JSF module, and in this module we have some goodies that I think makes Easy to program using JSF ...



Bellow we have a little example of an users and projects application (very simple) just to illustrate what I`m talking about ...

Just to make it clear, there is no faces-config.xml, the web.xml has only 21 lines, Spring Framework and XML Schema declaration already included in that, what left us 3 lines less ..., the applicationContext.xml has exactly 6 lines, but 5 of them are schema declarations and

, after that we have only one line added to the basic applicationContext.xml, 1 servlet, 1 servlet-mapping, 1 listener e 1 context-param at web.xml and it is it,

after that you just think about coding your application ...



And how is it possible?



For doing that I had to accept that every JSP for each managed bean will be in a directory with the same name as the Managed bean, and that the Managed Beans will be configured using the Spring-Annotation annotations.



for example, if you have a bean annotated with @Bean(name="projectM")

all the JSPs for that managed bean will be placed at a directory named "projectM".



so, lets see some coding ...



this is the "memory persistence engine" I have wrote for this example, all the entities are persisted in memory using a HashMap :D


package br.com.urubatan.blog;

import net.java.dev.springannotation.annotation.Bean;

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

/**
* Created by IntelliJ IDEA.
* User: Rodrigo
* Date: 14/12/2006
* Time: 12:00:45
* To change this template use File | Settings | File Templates.
*/
@Bean(name = "persistence")
public class PersistenceExample {
   
private HashMap projects = new HashMap();
   
private HashMap users = new HashMap();

   
public List allProjects() {
       
return new ArrayList(projects.values());
    }

   
public void updateRef(Project project) {
       
projects.put(project.getName(), project);
    }

   
public void add(Project project) {
       
projects.put(project.getName(), project);
    }

   
public List allUsers() {
       
return new ArrayList(users.values());
    }

   
public void updateRef(User user) {
       
users.put(user.getUserName(), user);
    }

   
public void add(User user) {
       
users.put(user.getUserName(), user);
    }
}




after that I have created two value objects (that litle classes with lots of gets and sets and no logic at all)
the User VO:

package br.com.urubatan.blog;

import org.hibernate.validator.NotNull;
import org.hibernate.validator.Length;

import java.io.Serializable;

public class User implements Serializable {
   
private String userName;
    private String password;
    private String fullName;

    public String getUserName() {
       
return userName;
    }

   
public void setUserName(String userName) {
       
this.userName = userName;
    }

   
public String getPassword() {
       
return password;
    }

   
public void setPassword(String password) {
       
this.password = password;
    }

   
public String getFullName() {
       
return fullName;
    }

   
public void setFullName(String fullName) {
       
this.fullName = fullName;
    }

   
public boolean equals(Object o) {
       
if (this == o) {
           
return true;
        }
       
if (o == null || getClass() != o.getClass()) {
           
return false;
        }

        User user = (User) o;

       
if (fullName != null ? !fullName.equals(user.fullName) : user.fullName != null) {
           
return false;
        }
       
if (password != null ? !password.equals(user.password) : user.password != null) {
           
return false;
        }
       
if (userName != null ? !userName.equals(user.userName) : user.userName != null) {
           
return false;
        }

       
return true;
    }

   
public int hashCode() {
       
int result;
        result = (
userName != null ? userName.hashCode() : 0);
        result =
31 * result + (password != null ? password.hashCode() : 0);
        result =
31 * result + (fullName != null ? fullName.hashCode() : 0);
       
return result;
    }

   
@Override
   
public String toString() {
       
final StringBuilder sb = new StringBuilder();
        sb.append(
"User");
        sb.append(
"{userName='").append(userName).append('\'');
        sb.append(
", password='").append(password).append('\'');
        sb.append(
", fullName='").append(fullName).append('\'');
        sb.append(
'}');
       
return sb.toString();
    }
}




and the Project VO:

package br.com.urubatan.blog;

import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.io.Serializable;

public class Project implements Serializable {
   
private String name;
    private String description;
    private List users = new ArrayList();


   
public String getName() {
       
return name;
    }

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

   
public String getDescription() {
       
return description;
    }

   
public void setDescription(String description) {
       
this.description = description;
    }

   
public List getUsers() {
       
return Collections.unmodifiableList(users);
    }

   
public void addUser(User u) {
       
if (!users.contains(u)) {
           
users.add(u);
        }
    }

   
public void removeUser(User u) {
       
users.remove(u);
    }

   
public boolean equals(Object o) {
       
if (this == o) {
           
return true;
        }
       
if (o == null || getClass() != o.getClass()) {
           
return false;
        }

        Project project = (Project) o;

       
if (description != null ? !description.equals(project.description) : project.description != null) {
           
return false;
        }
       
if (name != null ? !name.equals(project.name) : project.name != null) {
           
return false;
        }
       
if (users != null ? !users.equals(project.users) : project.users != null) {
           
return false;
        }

       
return true;
    }

   
public int hashCode() {
       
int result;
        result = (
name != null ? name.hashCode() : 0);
        result =
31 * result + (description != null ? description.hashCode() : 0);
        result =
31 * result + (users != null ? users.hashCode() : 0);
       
return result;
    }

   
@Override
   
public String toString() {
       
final StringBuilder sb = new StringBuilder();
        sb.append(
"Project");
        sb.append(
"{name='").append(name).append('\'');
        sb.append(
", description='").append(description).append('\'');
        sb.append(
", users=").append(users);
        sb.append(
'}');
       
return sb.toString();
    }
}





After that litle play with Java, I started all the XML coding I need for this project:

here is my web.xml

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
style="background-color:#efefef;">>
<display-name>Example JSF Applicationdisplay-name>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath*:applicationContext.xmlparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<servlet>
<servlet-name>Faces Servletservlet-name>
<servlet-class>javax.faces.webapp.FacesServletservlet-class>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>Faces Servletservlet-name>
<url-pattern>*.jsfurl-pattern>
servlet-mapping>
web-app>






and here is my applicationContext.xml





all done, no mor XML for today :D



after this we can start writing all the managed beans:

look ar the UserMBean bellow


package br.com.urubatan.blog;

import java.util.List;

import net.java.dev.springannotation.annotation.*;

import javax.faces.event.ActionEvent;

import org.hibernate.validator.Valid;

@Bean(
name = "userM", scope = Scope.REQUEST)
@ManagedBean
public class UserMBean {
   
@Out
    @Value(
"#{user}")
   
@DataModelSelection
   
private User user;
    @Out
    @Value(
"#{userList}")
   
@DataModel(name = "users", factory = "#{userM.list}", scope = Scope.REQUEST)
    private List userList;
    private PersistenceExample persistence;
    @Value("#{project}")
   
private Project project;


    public void setProject(Project project) {
       
this.project = project;
    }

   
public void setPersistence(PersistenceExample persistence) {
       
this.persistence = persistence;
    }


   
public User getUser() {
       
return user;
    }

   
public void setUser(User user) {
       
this.user = user;
    }

   
public List getUserList() {
       
return userList;
    }

   
public void setUserList(List userList) {
       
this.userList = userList;
    }

   
public String list() {
       
userList = persistence.allUsers();
       
return "def:list";
    }

   
public String create() {
       
user = new User();
       
return "def:form";
    }

   
public String edit() {
       
return "def:form";
    }

   
public String update() {
       
persistence.updateRef(user);
       
return list();
    }
   
   
public String save() {
       
persistence.add(user);
       
return list();
    }

   
public void addUser(ActionEvent evt) {
       
project.addUser(user);
    }
}





the addUser method adds the selected user to the project beeing edited now, the other methods are just simple CRUD methods ...



and the ProjectMBean

in this one, I had to add some of the JSF API since in the current version of the Spring-Annotation project you can have only one @DataModel per managed bean, and I had no other way to get what was the selected user to be removed from the current project ...