Data la seguente classe di gestione tag.java.lang.IllegalStateException: java.lang.InstantiationException durante l'implementazione di un gestore tag personalizzato in JSF
public final class ViewParamValidationFailed extends TagHandler implements ComponentSystemEventListener
{
private final String redirect;
public ViewParamValidationFailed(TagConfig config) {
super(config);
redirect = getRequiredAttribute("redirect").getValue();
}
@Override
public void apply(FaceletContext context, UIComponent parent) throws IOException {
if (parent instanceof UIViewRoot && !context.getFacesContext().isPostback()) {
((UIViewRoot) parent).subscribeToEvent(PostValidateEvent.class, this);
}
}
@Override
public void processEvent(ComponentSystemEvent event) throws AbortProcessingException {
FacesContext context = FacesContext.getCurrentInstance();
if (context.isValidationFailed()) {
try {
ExternalContext externalContext = context.getExternalContext();
externalContext.redirect(externalContext.getRequestContextPath() + redirect);
}
catch (IOException e) {
throw new AbortProcessingException(e);
}
}
}
}
Il gestore tag ha lo scopo di reindirizzare a una pagina, quando la conversione fallisce.
Viene utilizzato su pagine XHTML come segue.
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:my="http://example.com/ui"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Test</title>
</h:head>
<h:body>
<f:metadata>
<f:viewParam name="id" required="true" value="#{testManagedBean.id}"/>
<my:viewParamValidationFailed redirect="/public_resources/PageNotFound.jsf"/>
</f:metadata>
<h:form id="form" prependId="true">
<p:commandButton value="Submit" actionListener="#{testManagedBean.submitAction}"/>
</h:form>
</h:body>
</html>
possiamo avere un attributo convertitore opzionale <f:viewParam>
proprio come converter="javax.faces.Long"
In realtà, c'è un modello in cui <f:metadata>
è racchiuso all'interno di <ui:define name="metaData">
.
Il JSF associato bean gestito:
@ManagedBean
@RequestScoped
public final class TestManagedBean
{
private Long id; // Getter and setter.
public TestManagedBean() {}
public void submitAction() {
System.out.println("submitAction() called.");
}
}
quando si preme il data <p:commandButton>
, il seguente viene generata un'eccezione.
SEVERE: java.lang.IllegalStateException: java.lang.InstantiationException: tags.ViewParamValidationFailed
at javax.faces.component.StateHolderSaver.restore(StateHolderSaver.java:153)
at javax.faces.component.UIComponent$ComponentSystemEventListenerAdapter.restoreState(UIComponent.java:2633)
at javax.faces.component.StateHolderSaver.restore(StateHolderSaver.java:165)
at javax.faces.component.UIComponentBase.restoreAttachedState(UIComponentBase.java:1793)
at javax.faces.component.UIComponentBase.restoreSystemEventListeners(UIComponentBase.java:1911)
at javax.faces.component.UIComponentBase.restoreState(UIComponentBase.java:1607)
at javax.faces.component.UIViewRoot.restoreState(UIViewRoot.java:1771)
at com.sun.faces.application.view.FaceletPartialStateManagementStrategy$2.visit(FaceletPartialStateManagementStrategy.java:380)
at com.sun.faces.component.visit.FullVisitContext.invokeVisitCallback(FullVisitContext.java:151)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1690)
at com.sun.faces.application.view.FaceletPartialStateManagementStrategy.restoreView(FaceletPartialStateManagementStrategy.java:367)
at com.sun.faces.application.StateManagerImpl.restoreView(StateManagerImpl.java:138)
at com.sun.faces.application.view.ViewHandlingStrategy.restoreView(ViewHandlingStrategy.java:123)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.restoreView(FaceletViewHandlingStrategy.java:590)
at com.sun.faces.application.view.MultiViewHandler.restoreView(MultiViewHandler.java:150)
at javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:353)
at org.omnifaces.viewhandler.RestorableViewHandler.restoreView(RestorableViewHandler.java:66)
at javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:353)
at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:197)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:121)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:344)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:70)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:316)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.InstantiationException: tags.ViewParamValidationFailed
at java.lang.Class.newInstance0(Class.java:357)
at java.lang.Class.newInstance(Class.java:325)
at javax.faces.component.StateHolderSaver.restore(StateHolderSaver.java:150)
... 54 more
Questo tag handler deve essere associato solo con <f:viewParam>
e dovrebbe essere saltato nella sua interezza, quando un palo è fatto, per esempio.
C'è qualche soluzione?
cruciale:
Nel controllo condizionale all'interno del metodo apply()
,
if (parent instanceof UIViewRoot && !context.getFacesContext().isPostback()) {
System.out.println("Inside if");
((UIViewRoot) parent).subscribeToEvent(PostValidateEvent.class, this);
}
Quando il pulsante proposta viene cliccato, questa condizione viene valutata false come ovvio. Quindi, non dovrebbe esserci alcun problema.
Sorprendentemente, l'eccezione scompare quando l'unica riga all'interno dell'istruzione if
viene rimossa come segue.
if (parent instanceof UIViewRoot && !context.getFacesContext().isPostback()) {
//Debug statements only.
}
Esso non genera l'eccezione come detto sopra, quando viene premuto il dato <p:commandButton>
se la condizione viene valutata false, in questo caso.
non ha mai visto questo tipo di situazione :)