Skip to content
This repository was archived by the owner on Mar 20, 2021. It is now read-only.
This repository was archived by the owner on Mar 20, 2021. It is now read-only.

Injecting in Converter/Validator requires a JSF 2.3 faces-config.xml file #4270

@ConstantinAlin

Description

@ConstantinAlin

Injecting in Converter/Validator requires a JSF 2.3 faces-config.xml file, even if the application uses a JSF 2.3 configuration bean:

ConfigurationBean.java

@FacesConfig(version = FacesConfig.Version.JSF_2_3)
public class ConfigurationBean {
}

As pointed by Arjan Tijms in this topic, an empty JSF 2.3 faces-config.xml file is not involved into enabling CDI injection and EL resolution using CDI and switching into a JSF 2.3 mode, thus, it should not be required when using CDI injection into Converter/Validator.

Consider the following example:

index.xhtml

<h:form>
	Phone number:
	<h:inputText id="phoneId" value="#{phoneNumberBean.number}"
			converter="phoneNumberConverter"
			validator="phoneNumberValidator" />
	<h:message for="phoneId"/>
	<h:commandButton value="Send" action="#{phoneNumberBean.pingNumberAction()}"/>
</h:form>
Ping number: #{phoneNumberBean.number}

PhoneNumberConverter.java

@FacesConverter(value = "phoneNumberConverter", managed = true)
public class PhoneNumberConverter implements Converter {

    @Inject
    private PhonePrefixServiceBean phonePrefixServiceBean;

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (!value.contains("-")) {
            return phonePrefixServiceBean.computePrefix() + "-" + value;
        }
        return value;
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        return String.valueOf(value);
    }
}

PhoneNumberValidator.java

@FacesValidator(value = "phoneNumberValidator", managed = true)
public class PhoneNumberValidator implements Validator {

    @Inject
    private PhonePrefixServiceBean phonePrefixServiceBean;

    @Override
    public void validate(FacesContext fc, UIComponent uic, Object o) throws ValidatorException {
        String pn = String.valueOf(o);
        if (!phonePrefixServiceBean.getPrefix().contains(pn.substring(0, 4))) {
            throw new ValidatorException(new FacesMessage(null, "Wrong prefix!"));
        }
    }
}

PhonePrefixServiceBean.java

@Named
@ApplicationScoped
public class PhonePrefixServiceBean implements Serializable {

    private static final long serialVersionUID = 1L;

    private final List prefix;

    public PhonePrefixServiceBean() {
        prefix = new ArrayList<>();
        prefix.add("0721");
        prefix.add("0723");
        prefix.add("0909");
    }

    public String computePrefix() {
        return (String) prefix.get(new Random().nextInt(3));
    }

    public List getPrefix() {
        return prefix;
    }
}

Exception thrown

Without a JSF 2.3 faces-config.xml file or with a faces-config.xml version 2.2 file, the application throws the following exception:

FATAL:   JSF1073: javax.faces.FacesException caught during processing of PROCESS_VALIDATIONS 3 : UIComponent-ClientId=, Message=null
FATAL:   No associated message
javax.faces.FacesException
	at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:85)
	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
	at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:201)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:670)
	at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1606)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:258)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
	at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:654)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:593)
	at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155)
	at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:371)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:238)
	at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:480)
	at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:180)
	at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
	at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
	at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:242)
	at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
	at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
	at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:539)
	at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
	at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:593)
	at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:573)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NullPointerException
	at beans.PhoneNumberConverter.getAsObject(PhoneNumberConverter.java:18)
	at com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getConvertedValue(HtmlBasicInputRenderer.java:171)
	at javax.faces.component.UIInput.getConvertedValue(UIInput.java:1122)
	at javax.faces.component.UIInput.validate(UIInput.java:1030)
	at javax.faces.component.UIInput.executeValidate(UIInput.java:1334)
	at javax.faces.component.UIInput.processValidators(UIInput.java:757)
	at javax.faces.component.UIForm.processValidators(UIForm.java:269)
	at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1298)
	at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1298)
	at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1332)
	at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:77)
	... 31 more

Testing environment:

JSF 2.3.2, Payara Server 5.0.0.174

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions