Integrating Guice and JSF

I was wondering about how the integration of JSF and the community’s new hot IOC Framework Guice can be done and later figured out a way. The example I’ve created is simple, there’s a JSF page used for creating an Account entity, a service class AccountService that implements IAccountService, and a JSF managed bean serving as the backing bean of the JSF page. Simply the JSF bean has a dependency to IAccountService and the injection is done via Guice.

Account

  
    
    

package com.cc.guicejsf.domain;

import java.io.Serializable;

public class Account implements Serializable{

  private String name;
  private String password;
  
  public Account() {}
  
  public Account(String name, String password) {
    this.name = name;
    this.password = password;
  }
  
  //Getters/Setters of properties
}
      

IAccountService

 
    
    

package com.cc.guicejsf.service;

import com.cc.guicejsf.domain.Account;

public interface IAccountService {
  public void save(Account account);
}
      

AccountService

package com.cc.guicejsf.service;

import com.cc.guicejsf.domain.Account;

public class AccountService implements IAccountService{

  public void save(Account account) {
    //TODO: Persist account
  }
}
      

createAccount form

<%@ taglib uri=”http://java.sun.com/jsf/html&#8221; prefix=”h” %>
<%@ taglib uri=”http://java.sun.com/jsf/core&#8221; prefix=”f” %>
<html>
    <head>
        <title>Create an Account</title>
    </head>
    <body>
        <f:view>
            <h:form>
                <h:panelGrid columns=”2″>
                    <h:outputLabel value=”Name” for=”txt_name”></h:outputLabel>
                    <h:inputText id=”txt_name” value=”#{createAccount.account.name}” />
                   
                    <h:outputLabel value=”Password” for=”txt_password”></h:outputLabel>
                    <h:inputSecret id=”txt_password” value=”#{createAccount.account.password}” />
                </h:panelGrid>
                <h:commandButton action=”#{createAccount.save}” value=”Save” />
            </h:form>
        </f:view>
    </body>   
</html> 

CreateAccount

  
    
    

package com.cc.guicejsf.pages;

import com.cc.guicejsf.domain.Account;
import com.cc.guicejsf.service.IAccountService;
import com.google.inject.Inject;

public class CreateAccount extends BasePageBean{

  private Account account = new Account();
  private IAccountService accountService;

  public Account getAccount() {
    return account;
  }
  public void setAccount(Account account) {
    this.account = account;
  }
  
  public String save() {
    accountService.save(account);
    return null;
  }
  
  public IAccountService getAccountService() {
    return accountService;
  }
  @Inject
  public void setAccountService(IAccountService accountService) {
    this.accountService = accountService;
  }
}
      

BaseBackingBean

  
    
    

package com.cc.guicejsf.pages;

import java.io.Serializable;

import javax.annotation.PostConstruct;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;

import com.google.inject.Injector;

public abstract class BasePageBean implements Serializable{

  private Injector injector;
  
  public BasePageBean() {}
  
  public Injector getInjector() {
    if(injector == null) {
      ServletContext servletContext = (ServletContext)FacesContext.getCurrentInstance().
                                       getExternalContext
().getContext();
      injector = (Injector)servletContext.getAttribute(Injector.class.getName());  
    }
    return injector;
  }
  public void setInjector(Injector injector) {
    this.injector = injector;
  }
  
  @PostConstruct
  public void init() {
    getInjector().injectMembers(this);
  }
}
      

Listener (To be defined in web.xml)

  
    
    

 package com.cc.guicejsf.config;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import com.google.inject.Guice;
import com.google.inject.Injector;

public class ModuleListener implements ServletContextListener {

  public void contextDestroyed(ServletContextEvent servletContextEvent) {
    ServletContext servletContext = servletContextEvent.getServletContext();
    servletContext.removeAttribute(Injector.class.getName());
  }

  public void contextInitialized(ServletContextEvent servletContextEvent) {
    Injector injector = Guice.createInjector(new  GuiceJSFModule());
    ServletContext servletContext = servletContextEvent.getServletContext();
    servletContext.setAttribute(Injector.class.getName(), injector);
  }
}
      

GuiceJSFModule

  
    
    

 package com.cc.guicejsf.config;

import com.cc.guicejsf.service.IAccountService;
import com.cc.guicejsf.service.AccountService;
import com.google.inject.AbstractModule;
import com.google.inject.Scopes;

public class GuiceJSFModule extends AbstractModule{

  public void configure() {
    bind(IAccountService.class).to(AccountService.class).in(Scopes.SINGLETON);
  }
}
      

The idea here is, the backing JSF bean is created by JSF IOC but it’s dependencies like IAccountService is injected by Guice. At startup, a listener creates and sets a Guice Injector to application scope(I get the listener idea from this blog). This part can be refactored so that the module lists are not hardcoded and retrieved from a context param instead. Anyway, when a JSF bean is created, the method annotated with @PostConstruct gets the injector and calls the injection procedure. This @PostConstruct is called after the bean is created but before being put into it’s scope.

The example is a kickstart for an app that uses JSF and Guice, frankly I don’t think Guice fits the JSF model well, the @PostConstruct is a JSF 1.2 feature and it’ll be problematic to do a similar thing with JSF 1.1. I’m not a spring fan but using spring 2.0 with JSF is very easy and effective compared to Guice since it’s also possible to define the JSF beans in Spring Context with different scopes, apply AOP on them, add BeanPostProcessor to add custom lifecycle logics and etc.

About these ads

One Response to Integrating Guice and JSF

  1. rotanove says:

    A think the this is a good solution…

    http://code.google.com/p/guicesf

Follow

Get every new post delivered to your Inbox.

Join 106 other followers

%d bloggers like this: