I have a web application which runs perfectly fine on Wildfly9, but gives me a headache on Websphere8:
<h:form id="productsForm">
<p:selectOneMenu id="productSelector"
value="#{productManager.productName}" style="width: 100%;">
<f:selectItem value="#{null}" />
<f:selectItems value="#{productManager.products}"
var="product" itemLabel="#{product.productName}"
itemValue="#{product.productName}" />
<p:ajax event="change" update="editProductButton" />
</p:selectOneMenu>
<p:button id="editProductButton"
value="Edit Product" outcome="/pages/products/productDetails"
style="float: left; margin-left: 10px;" disabled="#{productManager.productName == null}">
<f:param name="productName"
value="#{productManager.productName}" />
</p:button>
</h:form>
Java side:
private String productName;
private List<Product> products;
public String getProductName() {
return this.productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public List<Product> getProducts() {
if(null == this.products){
this.products = this.productService.findAll();
}
return this.products;
}
If an item in the selectOneMenu is selected, I want the "edit" button to be enabled. On Wildfly everything is fine, on websphere the following exception occurs when I select an item:
com.ibm.ws.webcontainer.servlet.ServletWrapper service SRVE0014E: Uncaught service() exception root cause Faces Servlet: javax.servlet.ServletException
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:221)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1224)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:774)
[...]
Caused by: java.lang.NullPointerException
at javax.faces.component._SelectItemsIterator.hasNext(_SelectItemsIterator.java:124)
at javax.faces.component._SelectItemsUtil.matchValue(_SelectItemsUtil.java:48)
at javax.faces.component.UISelectOne.validateValue(UISelectOne.java:77)
at org.primefaces.component.selectonemenu.SelectOneMenu.validateValue(SelectOneMenu.java:282)
at javax.faces.component.UIInput.validate(UIInput.java:583)
at javax.faces.component.UIInput.processValidators(UIInput.java:247)
at org.apache.myfaces.context.servlet.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:533)
at org.apache.myfaces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:207)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:773)
at javax.faces.component.UIComponentBase.visitTree(UIComponentBase.java:1007)
at javax.faces.component.UIForm.visitTree(UIForm.java:269)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:793)
at javax.faces.component.UIComponentBase.visitTree(UIComponentBase.java:1007)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:793)
at javax.faces.component.UIComponentBase.visitTree(UIComponentBase.java:1007)
at org.apache.myfaces.context.servlet.PartialViewContextImpl.processPartialExecute(PartialViewContextImpl.java:362)
at org.apache.myfaces.context.servlet.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:342)
at org.primefaces.context.PrimePartialViewContext.processPartial(PrimePartialViewContext.java:60)
at javax.faces.component.UIViewRoot$ProcessValidatorPhaseProcessor.process(UIViewRoot.java:1394)
at javax.faces.component.UIViewRoot._process(UIViewRoot.java:1282)
at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:758)
at org.apache.myfaces.lifecycle.ProcessValidationsExecutor.execute(ProcessValidationsExecutor.java:34)
at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:171)
at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:189)
... 33 more
Any ideas why this is happening or how to fix/workaround this?
WebSphere uses MyFaces as JSF implementation and Wildfly uses Mojorra. Thats why you have different results.
You have defined a null value as selectItem. This breaks the code. Use instead an empty String. Or another solution would be to change the JSF implementation.
Also consider your development environment should always be as close as possible to the productive/final one.
Related
I have an issue with OmniFaces 1.11 <o:validateBean /> at class level (http://showcase.omnifaces.org/validators/validateBean)
Basically, i'm trying to validate the same bean using two validation groups according to the button I click :
<h:commandButton value="Mandatory">
<o:validateBean value="#{testBean.pojo}" validationGroups="bo.ihm.beans.Mandatory" />
</h:commandButton>
<h:commandButton value="Optional">
<o:validateBean value="#{testBean.pojo}" validationGroups="javax.validation.groups.Default" />
</h:commandButton>
Whenever I click on a button, I get
GRAVE: Exception occured while doing validation.
javax.el.ELException: /testOmnifaces.xhtml #21,74 value="#{testBean.pojo.forain}": java.lang.IllegalArgumentException: Cannot convert PROPERTY of type class org.omnifaces.el.ExpressionInspector$ValueExpressionType to class java.lang.Boolean
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:114)
at org.omnifaces.el.ExpressionInspector.getValueReference(ExpressionInspector.java:43)
at org.omnifaces.taghandler.ValidateBean$6.invoke(ValidateBean.java:331)
at org.omnifaces.taghandler.ValidateBean$6.invoke(ValidateBean.java:326)
at org.omnifaces.util.Components$ForEach$1.visit(Components.java:508)
at org.omnifaces.util.Components$ForEach$TypesVisitCallback.visit(Components.java:573)
at com.sun.faces.component.visit.FullVisitContext.invokeVisitCallback(FullVisitContext.java:151)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1689)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIForm.visitTree(UIForm.java:371)
at org.omnifaces.util.Components$ForEach.invoke(Components.java:541)
at org.omnifaces.util.Components$ForEach.invoke(Components.java:505)
at org.omnifaces.taghandler.ValidateBean.forEachInputWithMatchingBase(ValidateBean.java:326)
at org.omnifaces.taghandler.ValidateBean.access$400(ValidateBean.java:151)
at org.omnifaces.taghandler.ValidateBean$3.run(ValidateBean.java:286)
at org.omnifaces.taghandler.ValidateBean$ValidateBeanCallback.invoke(ValidateBean.java:430)
at org.omnifaces.util.Events$1.invoke(Events.java:278)
at org.omnifaces.util.Events$4.beforePhase(Events.java:312)
at org.omnifaces.eventlistener.CallbackPhaseListener.beforePhase(CallbackPhaseListener.java:63)
at com.sun.faces.lifecycle.Phase.handleBeforePhase(Phase.java:228)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:99)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:696)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:521)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:138)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:564)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:213)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1097)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:448)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:175)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1031)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:136)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:200)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:109)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:446)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:271)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:246)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.run(AbstractConnection.java:358)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:601)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:532)
at java.lang.Thread.run(Thread.java:745)
Caused by: javax.el.ELException: java.lang.IllegalArgumentException: Cannot convert PROPERTY of type class org.omnifaces.el.ExpressionInspector$ValueExpressionType to class java.lang.Boolean
at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:229)
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)
... 44 more
Caused by: java.lang.IllegalArgumentException: Cannot convert PROPERTY of type class org.omnifaces.el.ExpressionInspector$ValueExpressionType to class java.lang.Boolean
at com.sun.el.lang.ELSupport.coerceToBoolean(ELSupport.java:189)
at com.sun.el.lang.ELSupport.coerceToType(ELSupport.java:394)
at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:227)
... 45 more
testWithClassLevelValidation.xhtml :
<!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:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:o="http://omnifaces.org/ui">
<f:metadata>
<f:viewAction action="#{testBean.init}" />
</f:metadata>
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Test</title>
</h:head>
<h:body>
<h:form id="formaliteACCRE">
<h:panelGrid columns="1" style="width: 100%;">
<h:panelGrid columns="2" style="width: 100%; display: inline-block;">
<h:outputLabel for="forain">Yes or No ?</h:outputLabel>
<h:selectBooleanCheckbox id="forain" value="#{testBean.pojo.forain}">
<f:ajax execute="forain" render="groupeDomicile" />
</h:selectBooleanCheckbox>
</h:panelGrid>
<h:panelGroup id="groupeDomicile">
<h:outputText value="Yes" rendered="#{testBean.pojo.forain}" />
<h:outputText value="No" rendered="#{not testBean.pojo.forain}" />
</h:panelGroup>
<h:inputText id="numeroSecu" value="#{testBean.pojo.numeroSecuriteSociale}" maxlength="13" size="13" />
<h:inputText id="numeroSecuCle" value="#{testBean.pojo.cleSecuriteSociale}" maxlength="2" size="3" />
<h:panelGrid columns="2" style="width: 100%; display: inline-block;">
<h:inputText id="mandatory" value="#{testBean.pojo.mandatory}" maxlength="13" size="13" />
<h:outputText value="*" style="color:red;" />
</h:panelGrid>
<f:ajax execute="#form" render="#form">
<h:commandButton value="Mandatory">
<o:validateBean value="#{testBean.pojo}" validationGroups="bo.ihm.beans.Mandatory" />
</h:commandButton>
<h:commandButton value="Optional">
<o:validateBean value="#{testBean.pojo}" validationGroups="javax.validation.groups.Default" />
</h:commandButton>
</f:ajax>
</h:panelGrid>
<ui:remove> ################################################################################################ </ui:remove>
<ui:remove> ===== MESSAGES D'ERREURS ===== </ui:remove>
<ui:remove> ################################################################################################ </ui:remove>
<h:panelGroup id="messagesErreur">
<h:panelGrid class="dr-pnl" width="100%" rendered="#{not empty facesContext.messageList}">
<h:messages style="color:red;" />
</h:panelGrid>
</h:panelGroup>
</h:form>
</h:body>
</html>
TestBean.java :
package bo.ihm.beans;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.validation.Valid;
#ViewScoped
#ManagedBean(name = "testBean")
public class TestBean implements Serializable {
private static final long serialVersionUID = 1L;
#Valid
private Pojo pojo;
public Pojo getPojo() {
return pojo;
}
public void init() {
pojo = new Pojo();
pojo.setNumeroSecuriteSociale("2531257351038");
pojo.setCleSecuriteSociale("22");
}
public void setPojo(final Pojo pPojo) {
this.pojo = pPojo;
}
}
Pojo.java :
package bo.ihm.beans;
import org.hibernate.validator.constraints.NotEmpty;
#NumeroSecuriteSociale
public class Pojo {
private boolean forain;
private String cleSecuriteSociale;
private String numeroSecuriteSociale;
#NotEmpty(groups = Mandatory.class)
private String mandatory;
public String getCleSecuriteSociale() {
return cleSecuriteSociale;
}
public String getMandatory() {
return mandatory;
}
public String getNumeroSecuriteSociale() {
return numeroSecuriteSociale;
}
public boolean isForain() {
return forain;
}
public void setCleSecuriteSociale(final String pCleSecuriteSociale) {
cleSecuriteSociale = pCleSecuriteSociale;
}
public void setForain(final boolean pForain) {
forain = pForain;
}
public void setMandatory(final String pMandatory) {
mandatory = pMandatory;
}
public void setNumeroSecuriteSociale(final String pNumeroSecuriteSociale) {
numeroSecuriteSociale = pNumeroSecuriteSociale;
}
/*
* (non-Javadoc)
*
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("Pojo [forain=");
builder.append(forain);
builder.append(", cleSecuriteSociale=");
builder.append(cleSecuriteSociale);
builder.append(", numeroSecuriteSociale=");
builder.append(numeroSecuriteSociale);
builder.append(", mandatory=");
builder.append(mandatory);
builder.append("]");
return builder.toString();
}
}
the full code is available at https://github.com/ErwanLeroux/Bo_ihm_test_omnifaces just run clean jetty:run-war et go to http://localhost:14080/bo_ihm/testWithClassLevelValidation.xhtml
The second page http://localhost:14080/bo_ihm/testWithoutClassLevelValidation.xhtml is her to demonstrate that class level constraints doesn't work, when i click on whenever button, I should get a validation error message like this : 'Pojo [forain=false, cleSecuriteSociale=22, numeroSecuriteSociale=2531257351038, mandatory=null] is not valid'
It turns out that implicit EL coercion is was causing this all. We were passing around internal values like ValueExpressionType.PROPERTY and ValueExpressionType.METHOD to indicate if the EL expression represents a property (getter/setter) call or a method (action) call. However, this approach failed if the value has implicit EL coercion support, like java.lang.Boolean, on which EL would implicitly convert e.g. a string of "true" to a boolean true.
This approach of passing around internal values to indicate the kind of EL expression was since OmniFaces 2.0 used to breakdown the EL expression in <o:grapicImage value> and extract any EL method arguments so they could be converted and passed around as HTTP query string parameters. That explains why it still worked fine in OmniFaces 1.x.
As per this commit, this has been fixed for OmniFaces 2.2.
Do you have any idea why my app throws me this exception:
WARNING: /myProfile.xhtml #71,27 target="#{profileBean.selectedUser}": Property 'selectedUser' not found on type bg.fmi.master.thesis.beans.ProfileBean
javax.el.PropertyNotFoundException: /myProfile.xhtml #71,27 target="#{profileBean.selectedUser}": Property 'selectedUser' not found on type bg.fmi.master.thesis.beans.ProfileBean
---
Caused by: javax.el.PropertyNotFoundException: Property 'selectedUser' not found on type bg.fmi.master.thesis.beans.ProfileBean
When i have this property in my bean:
#ManagedBean(name = "profileBean")
public class ProfileBean implements Serializable {
private TUser selectedUser = new TUser();
public TUser getSelectedUser() {
return selectedUser;
}
public void setSelectedUser(TUser selectedUser) {
this.selectedUser = selectedUser;
}
The .xhtml code is this:
<p:dataGrid var="user" value="#{profileBean.userList}">
<p:panelGrid columns="2">
....
<p:commandButton id="submit" value="Save changes" actionListener="#{profileBean.editUser()}" >
<f:setPropertyActionListener target="#{profileBean.selectedUser}" value="#{user}" />
</p:commandButton>
</p:dataGrid>
Thanks in advance!
I have made a simple project based on your sample code.
<h:form>
<p:commandButton id="submit" value="Save changes" actionListener="#{profileBean.editUser()}" >
<f:setPropertyActionListener target="#{profileBean.selectedUser}" value="#{user}" />
</p:commandButton>
</h:form>
There was no such error as described. Your problem comes from other place. Remove unnecessary bits and try to isolate the problem. You could change the name of the property and see if the error reflects the new name. Make sure you don't have another bean with the same name.
I'm trying to render a page, but there is the possibility that some EL Expressions will generate some exceptions.
So I tryed first of all, to sorround by block with a < c:if> in such the way that it shows the code only by checking the critical condition.
But I saw that in case of "error" my page was redirected again as a "HTTP 500 - Internal Server Error".
So I tought that maybe the EL Expression inside the block where computed in any case, also if the < c:if> block where not shown. So I sorrounded my block with a < c:catch> as i read that this block will catch the exceptions. So I also added on all the methods the declaration "throws Exception".
But, again, when the critical condition is not respected, my page will be redirect to the 500 Error page.
I post my XHTML code:
<c:if test="#{!partyBean.emptySet}">
<c:catch>
<p:panel id="panel" style="margin-bottom:10px;">
<f:facet name="header" >
<h:outputLabel value="#{partyBean.currentparty.name}" />
</f:facet>
<f:facet name="actions">
<p:commandButton id="asktojoin" styleClass="ui-panel-titlebar-icon "
action="#{joinRequestBean.askForParty(partyBean.currentparty)}" value="Ask to Join"/>
</f:facet>
<f:facet name="footer" >
<p:commandButton id="pr" action="#{partyBean.previus()}" value="previousParty" rendered="#{partyBean.hasPrevious()}">
</p:commandButton>
<p:commandButton id="nx" style="margin-right:10px" action="#{partyBean.next()}" value="nextParty" rendered="#{partyBean.hasNext()}">
</p:commandButton>
</f:facet>
<h:panelGrid columns="2">
<h:outputLabel value="Symbol:" />
<h:graphicImage value="#{('/partysymbols/'.concat(partyBean.currentparty.symbol))}" width="200" height="171" />
<h:outputLabel for="program" value="Program:" />
<h:outputLabel id="program" value="#{partyBean.currentparty.program}" />
<h:link id="partyname" outcome="memberlist" value="memberlist">
<f:param name="partyname" value="#{partyBean.currentparty.name}" />
</h:link>
</h:panelGrid>
</p:panel>
</c:catch>
</c:if>
<c:if test="#{partyBean.emptySet}">
<h1>There are no parties at the moment</h1></c:if>
</h:form>
</h:body>
And my bean:
#ManagedBean(name="partyBean")
#SessionScoped
public class PartyBean {
#EJB
private PartyManagerLocal ejb;
private PartyDTO[] party;
int i=0;
#PostConstruct
private void init() {
i=0;
refresh();
}
private void refresh(){
Object[] list_o = ejb.getListOfParty().toArray();
party = new PartyDTO[list_o.length];
for(int i=0;i<list_o.length;i++){
party[i]=(PartyDTO)list_o[i];
}
if(i>=list_o.length)
i=list_o.length;
}
public boolean isEmptySet() {
refresh();
return party.length==0;
}
public String next() throws Exception{
refresh();
if(i<party.length-1)
i++;
return "partyview.xhtml?faces-redirect=true";
}
public String previus() throws Exception{
refresh();
if(i>0)
i--;
return "partyview.xhtml?faces-redirect=true";
}
public boolean hasPrevious(){
return i>=1;
}
public boolean hasNext(){
return i<party.length-1;
}
public PartyDTO getCurrentparty() throws Exception{
return party[i];
}
}
I apologize to show to you my whole code, but i have no idea about where is the mistake. Then I also apologize about my horrible code, but at the moment i just need that it works.
The critical condition is that my array should be not empty. Could happen that my Array will be empty but in that case, i need to advise the user about it, instead redirect to the 500 Error page.
Thankyou in advance,
Samuele
You could encapsulate what you want conditionally by surrounding the code in a panelGroup and using the rendered attribute.
Example
<h:panelGroup rendered="#{PartyBean.isEmptySet}">
<!-- Code inside here... -->
<!-- This will render if isEmptySet returns true -->
</h:panelGroup>
I am using JSF,with #ManagedBean annotation and using Primefaces, and I got the following problem.
Why the "onerror" is not triggered? The exception just appears in my console.
login.xhtml
<p:commandButton
value="teste"
action="#{loginBean.methodTest()}"
ajax="true"
immediate="false"
onerror="confirmation.show()" />
<p:dialog
appendToBody="true"
header="Atencao"
widgetVar="confirmation"
showEffect="bounce">
...
</p:dialog>
MyBean
#ManagedBean(name = "loginBean")
#SessionScoped
public class LoginBean {
public void methodTest() throws Exception {
System.out.println("hi");
throw new Exception("Exception Test");
}
This is the expected behavior...
onerror : Client side callback to execute when ajax request fails.
in your case there is no failure in the ajax request at all , that fact that you are throwing exception got nothing to do with ajax failure
onerror is called when jsf doesn't catch your exception, http error or so. Exception != error.
read this thread for further details Ajax Engine: onerror doesn't work (might provide you with some tips...)
See the following detailed explanation about f:ajax onerror
the onerror attribute looks for an http error status code which you need to provide yourself.
In your first example
public void methodTest() {
ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
HttpServletResponse response = (HttpServletResponse) context.getResponse();
response.setStatus(500);
System.out.println("hi");
}
should work.
Thanks everybody,
I solved this problem with a not very good way (but it worked out !), but i think perhaps you can help me to improve this way. I would like to throw a Ajax error into my "catch", and the "onerror" (insted of oncomplete) recive it, and open the dialog.
Is there possibility ??
Example that worked out , with a poor way:
<p:panel id="PanelLogin" header="Login" >
<h:form id="FormLogin" >
<br/>
<h:panelGrid columns="2">
<h:outputLabel for="user" value="Usuario:" />
<p:inputText id="user" required="true" value=" " size="75" />
<h:outputLabel for="pin" value="Senha:" />
<p:password id="pin" required="true" value=" " size="55" />
</h:panelGrid>
<p:commandButton styleClass="botaoLogin" value="OK" action="#{loginBean.checkLogin()}" ajax="true" oncomplete="if (#{loginBean.dialog}) confirmation.show()" />
</h:form>
</p:panel>
<p:dialog id="atencaoDialog" resizable="false" appendToBody="true" header="Atencao" widgetVar="confirmation" height="85" width="300" showEffect="bounce">
<div align="center">
<p:messages id="outputTextAtencaoDialog" autoUpdate="true" redisplay="false" />
</div>
<div style="text-align: center;">
<p:commandButton id="okButtonAtencaoDialog" value="OK" onclick="confirmation.hide();" />
</div>
</p:dialog>
MyBean
#ManagedBean(name = "loginBean")
#SessionScoped
public class LoginBean implements Serializable {
private boolean dialog;
...
public String checarAutenticacao() {
...
try {
...
return "/templantes/telaAplicacao.xhtml";
} catch (Throwable e) {
this.dialog = true;
// try to throw Ajax error instead of this below ??
FacesContext.getCurrentInstance().addMessage(null,new FacesMessage(e.getMessage()));
return null;
}
}
I have request scope backing bean for login page( I am using Spring Security ). When authentication error occurs Spring put it to context and I am trying add error message to my page.
public void doLogin() throws IOException {
final FacesContext context = FacesContext.getCurrentInstance();
ExternalContext externalContext = context.getExternalContext();
externalContext.dispatch("/j_spring_security_check");
if (externalContext.getRemoteUser() == null) {
Exception loginError = (Exception) externalContext.getSessionMap().get(
AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY);
if (loginError instanceof BadCredentialsException) {
externalContext.getSessionMap().put(
AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY, null);
context.addMessage("loginBtn", new FacesMessage(FacesMessage.SEVERITY_ERROR, "Invalid credentials!", null));
context.responseComplete();
}
}
context.renderResponse();
}
my page:
<a4j:form prependId="false">
<h:panelGrid columns="2" cellpadding="5" >
<h:outputText value="#{msgs.login_username}"/>
<h:inputText id="j_username"/>
<h:outputText value="#{msgs.login_password}"/>
<h:inputSecret id="j_password"/>
<h:outputText value=" "/>
<f:facet name="footer">
<h:panelGroup>
<h:commandButton type="submit" id="loginBtn" action="#{guest.doLogin}" value="#{msgs.login}" />
<rich:spacer width="5" height="1"/>
<rich:message id="errorForLogin" for="loginBtn">
<f:facet name="errorMarker">
<h:graphicImage value="./resources/forbidden.gif"/>
</f:facet>
</rich:message>
</h:panelGroup>
</f:facet>
</h:panelGrid>
<br/><br/>
</a4j:form>
But it's don't works. I am trying put error displaying code to #PostConstruct method but this didn't help. This work only if I implement my PhaseListener but I think this is bad idea because it invokes on every request. What my mistake, there are some ways add error message from method, maybe in #PostConstruct method?
You can approach this from other side. As you use SpringSecurity, you can subclass AuthenticationProcessingFilter and override onUnsuccessfulAuthentication method. There you can put the code for desired behaviour. Then you just specify your custom authentication processing filter class instead of AuthenticationProcessingFilter in correspondent bean definition for Spring Security.