Java7
JSF2
JSF 2.0 Custom Validator Calling @EJB Injected Bean
Dec 31st
One of the wonders of JSF 2.0 that i love is the simplicity of creating a custom validator for another mere business scenario validation.
The highlights of this post showcase:
- Creating custom validator in JSF 2.0
- How it is possible to call on injected @EJB bean from the Validator
Scenario
Consider the business scenario where a form collects a price model name from the user. The business rule is that the price model name must be unique, i.e. it has not been used before.

Validation error message showing that the name is already in use.
To determine whether my price model name has been used, the application needs to check the DBMS if the price model name has already been used. Now, you could implement the logic of creating a connection to the DBMS, performing the if\else check all in the Validator. But i hope this is not what you are going to do in any real scenario because it violates many principles. This tutorial will show you how you can call on an injected @EJB bean that would contain all the business logic to check if a price model name is in use.
JSF 2.0 Validator
JSF 2.0 has a Validator framework that allows you to write a custom validation in a class, and then tie this validation class to a XHTML boundary page.
package sg.java.hms.validator.manage.pricing;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
import sg.java.hms.service.manage.pricing.IPriceModelService;
/**
* JSF Custom Validator.
* <p>
* Validates that the price model name is not duplicate.
* </p>
*
* @author Chin Boon
*
*/
@ManagedBean
@RequestScoped
public class PriceModelNameValidator implements Validator {
@EJB
private IPriceModelService priceModelService;
@Override
public void validate(FacesContext arg0, UIComponent arg1, Object value)
throws ValidatorException {
// cast value into String
final String priceModelName = value.toString();
// call business method to check if price model name exists
boolean priceModelNameExists = this.priceModelService
.checkPriceModelNameExists(priceModelName);
// if price model name exists, fail the validation
if (priceModelNameExists) {
FacesMessage msg = new FacesMessage(priceModelName
+ " is already in use. Please choose another name");
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(msg);
}
}
}
You may have noticed that i am not decorating my validator class with @FacesValidator. That is because i am going to call an @EJB bean from the validator and because @FacesValidator isn’t managed by the injecton container (Answered by BalusC), i would be unable to call the injected @EJB bean that i wanted had i used @FacesValidator.
PriceModelService.java
Lets assume that priceModelService is an EJB3 bean and the method checkPriceModelNameExists() performs all the work of communicating with the DBMS and returns the result true if a price model name exists and false otherwise.
createPriceModel.xhtml
After writing up the custom validator class, binding the validator to the input field is sufficient to make the new validation take effect!
<p:inputText id="priceModelName" size="30"
value="#{priceModelBackingBean.priceModel.priceModelName}"
required="true" label="#{labelResource.priceModelName}">
<f:validator binding="#{priceModelNameValidator}" />
</p:inputText>
Conclusion
The simplicity and cleanliness of the JSF 2.0 Validator framework to provide extensive business validation scenario that would otherwise had been troublesome to create and maintain makes JSF 2.0 a very developer friendly framework to work with.
Target Unreachable, xxx returned null
Dec 22nd
This error is probably happening when you are trying to submit a form. JSF tries to populate all the user entered form values into the corresponding backing bean attributes that aren’t yet initialized, i.e. null.
Consider this simple form where we are trying to collect the Price Model Name from the user.

createPriceModel.xhtml JSF2 Form
In the form, the value of the price model name text field is set into a backing bean containing a complex data object PriceModel which contains the attribute priceModelName.
<h:form>
<p:inputText id="priceModelName"
value="#{priceModelBackingBean.priceModel.priceModelName}" />
</p:inputText>
...
</h:form>
PriceModelBackingBean.java Backing Bean
@ManagedBean
@SessionScoped
public class PriceModelBackingBean implements IPriceModelBackingBean {
private PriceModel priceModel;
...
accessors and mutators
...
}
PriceModel.java POJO
public class PriceModel {
private String priceModelName;
...
accessors and mutators
...
}
So, what could go wrong?
Solution
Initialize the priceModel attribute!
You did not initialize the value of priceModel in the backing bean. When the user submits the form and JSF tries to populate the value of the price model name which is “Standard Price Model”, it hits a null pointer exception.
While we could do this in a constructor of the backing bean, it is not advisable to do so, instead use the @PostConstruct JSF bean lifecycle annotation to help you. This way it is guaranteed that the attribute priceModel is initialized.
public class PriceModelBackingBean implements IPriceModelBackingBean {
private PriceModel priceModel;
@PostConstruct
public void init() {
this.priceModel = new PriceModel();
}
...
}
Error Message Encountered (Reference)
22:05:11,706 WARNING [javax.enterprise.resource.webcontainer.jsf.lifecycle] (http-localhost-127.0.0.1-8080-1) /facelet/manage/pricing/createPriceModel.xhtml @47,64 value="#{priceModelBackingBean.priceModel.priceModelName}": Target Unreachable, 'priceModel' returned null: javax.el.PropertyNotFoundException: /facelet/manage/pricing/createPriceModel.xhtml @47,64 value="#{priceModelBackingBean.priceModel.priceModelName}": Target Unreachable, 'priceModel' returned null
at com.sun.faces.facelets.el.TagValueExpression.getType(TagValueExpression.java:100) [jsf-impl-2.1.7-jbossorg-2.jar:]
at org.primefaces.renderkit.InputRenderer.findImplicitConverter(InputRenderer.java:170) [primefaces-3.4.jar:]
at org.primefaces.renderkit.InputRenderer.findConverter(InputRenderer.java:190) [primefaces-3.4.jar:]
at org.primefaces.renderkit.InputRenderer.getConvertedValue(InputRenderer.java:196) [primefaces-3.4.jar:]
at javax.faces.component.UIInput.getConvertedValue(UIInput.java:1030) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at javax.faces.component.UIInput.validate(UIInput.java:960) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at javax.faces.component.UIInput.executeValidate(UIInput.java:1233) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at javax.faces.component.UIInput.processValidators(UIInput.java:698) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at org.primefaces.component.fieldset.Fieldset.processValidators(Fieldset.java:197) [primefaces-3.4.jar:]
at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at org.primefaces.component.layout.Layout.processValidators(Layout.java:245) [primefaces-3.4.jar:]
at javax.faces.component.UIForm.processValidators(UIForm.java:253) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1172) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76) [jsf-impl-2.1.7-jbossorg-2.jar:]
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) [jsf-impl-2.1.7-jbossorg-2.jar:]
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) [jsf-impl-2.1.7-jbossorg-2.jar:]
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
at org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:62) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.13.Final.jar:]
at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.13.Final.jar:]
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:]
at java.lang.Thread.run(Thread.java:662) [rt.jar:1.6.0_35]
j_idt7:hotelName: Validation Error: Value is required
Feb 6th
As you can see, JSF validation produces ugly validation messages.
Solution
To get rid of this, add a label to your input field.
(This solution does not override the default behavior of the JSF message bundle, i will discuss that in more details in a follow-up write up soon)
For example:
<p:inputText id="hotelName" value="#{editHotelBackingBean.hotel.name}" required="true" <strong>label="Hotel Name</strong>">
Warning: This page calls for XML namespace http://primefaces.prime.com.tr/ui declared with prefix p but no taglibrary exists for that namespace.
Feb 5th
You had a recent change of Primefaces JSF 2 component library (2.2.1 to 3.0.0) and your JSFs don’t work anymore.
Problem
Primefaces is no longer using this tag:
xmlns:p="http://primefaces.prime.com.tr/ui"
Solution
Were you using Primefaces version < 3.0.0 and did a recent upgrade to a version that is bigger than 3.0.0? Most likely you are, starting 3.0.0, it is switched to using this tag instead:
xmlns:p="http://primefaces.org/ui"
Once you have the alias changed out, the warning will go away.
JSF 2.2 and HTML5?
Dec 17th
Will JSF 2.2 support HTML 5? Where is JSF in the age of HTML5?
As we know, most browsers have now support for HTML5, which is a sweet revamp from HTML4 (More commonly just known as HTML). HTML5 will be fully supported in JSF 2.2.
JSF 2.0 is the second release of JSF 1.0 specification just as EJB 3.0 is to EJB 2.0.
At a glance:
| JSR | JSF Version |
| JSR 314 * | JSF 2.0 |
| JSR 314 * | JSF 2.1 |
| JSR 344 | JSF 2.2 |
*JSF 2.1 is a maintenance release to JSF 2.0 just as EJB 3.1 is to EJB 3.0, JSF 2.1 shares a JSR number (JSR 314) with JSF 2.0.
JSR 344 is currently still in draft review stage, there are no stable implementation (Either Mojarra or MyFaces) of it at the moment.
Reference

