tags:

views:

705

answers:

2

I have a JSF validator that checks whether a Container Number string conforms to the ISO-6346 specficiation.

It works fine, however I need to add some conditional processing in based on other values in the Bean where the Container Number comes from. This Bean can be of several different types.

Is there any way to access the Bean in the validator and perform operations on it? Ideally I'd love to keep it as a validator, however if there is no solution I'll have to implement the logic in the Bean before persisting.

I'm thinking something along the lines of:

public class ContainerNumberValidator implements javax.faces.validator.Validator {
   public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {

      Object bean = UIComponent.getMyBeanSomehowThroughAMagicMethod();
      if(bean instanceof BeanA) {
         //do this
      } else if(bean instanceof BeanB) {
         //do that
      }
}

UPDATE: In many ways this is a similar problem to the validation of multiple fields at the same time. This code by BalusC is helpful.

Much appreciated.

D.

A: 

Using the <f:attribute> you can pass a Bean to the validator and retrieve it from the component as a value expression.

So my input is like this (must be using <f:validator> and not the validator attribute on the <h:inputText>) :

<h:inputText id="containerNum" size="20" maxlength="20" value="#{containerStockAction.containerStock.containerNumber}">
    <f:validator validatorId="containerNumberValidator" />
    <f:attribute name="containerBean" value="#{containerStockAction.containerStock}"/>
</h:inputText>

And my validator class:

public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
  String containerNumber = (String)value;
  Object containerBean = component.getValueExpression("containerBean").getValue(context.getELContext());

  if(containerBean instanceof BeanA) {
    //do this
  }
Damo
An alternative is to get the attribute map directly from the component. Combine it with an interface for your stuff and it could be as simple as this... ISOBean bean = (ISOBean)component.getAttribute("containerBean"); bean.doStuff();
Drew
A: 

You can use the following to get any old bean you like using the FacesContext. Very similar to the solution you found.

public void validate(FacesContext context, UIComponent component, Object value)
{
 Application app = context.getApplication();

 ValueExpression expression = app.getExpressionFactory().createValueExpression( context.getELContext(),
   "#{thingoBean}", Object.class );

 ThingoBean thingoBean = (ThingoBean) expression.getValue( context.getELContext() );
}
Martlark
Thanks. If you're using Seam you can do the same thing withThingoBean thingoBean = (ThingoBean)Component.getInstance("thingoBean");However using this approach I can't reuse the validator for different Beans.
Damo