JSF 2 managed bean does not get instantiated - jsf-2

I am having this problem in this sample jsf project I created. Managed beans do not get instantiated.
Bean class:
#ManagedBean(name="loginMB")
#RequestScoped
public class LoginMB extends AbstractMB {
private static final long serialVersionUID = -8523135776442886000L;
#ManagedProperty("#{userMB}")
private UserMB userMB;
//getters and setters
public String login() {
UserSupport userSupport = new UserSupportImpl();
User user = userSupport.isValidLogin(email, password);
if (user != null) {
getUserMB().setUser(user);
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context
.getExternalContext().getRequest();
request.getSession().setAttribute("user", user);
return "loggedIn";
//return "/pages/protected/index.xhtml";
}
displayErrorMessageToUser("Check your email/password");
return null;
}
}
ManagedBean annotation and RequestScope annotation have been imported from
import javax.faces.bean.*;
this is how i ve used above bean,
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<p>#{bundle.loginHello}</p>
<h:form>
<p:growl showDetail="false" life="3000" />
<h:panelGrid columns="2">
<h:outputLabel value="#{bundle.loginUserName}" />
<h:inputText value="#{loginMB.email}" label="Email" id="email" required="true">
<f:validateLength minimum="6" />
</h:inputText>
<h:outputLabel value="#{bundle.loginPassword}" />
<h:inputSecret value="#{loginMB.password}" label="Password" id="senha" required="true" autocomplete="off" >
<f:validateLength minimum="6" />
</h:inputSecret>
</h:panelGrid>
<p:commandButton action="#{loginMB.login}" value="Log in" ajax="false" />
</h:form>
</h:body>
</html>
Other managed bean
#SessionScoped
#ManagedBean(name = "userMB")
public class UserMB implements Serializable {
public static final String INJECTION_NAME = "#{userMB}";
private static final long serialVersionUID = 1L;
private User user;
.......
}
Exception:
javax.el.PropertyNotFoundException: /login.xhtml #14,83 value="#{loginMB.email}": Target Unreachable, identifier 'loginMB' resolved to null
at com.sun.faces.facelets.el.TagValueExpression.getType(TagValueExpression.java:100)
at com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getConvertedValue(HtmlBasicInputRenderer.java:95)
faces-config.xml
<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd"
version="2.1">
<application>
<resource-bundle>
<base-name>messages</base-name>
<var>bundle</var>
</resource-bundle>
<message-bundle>messages</message-bundle>
</application>
<navigation-rule>
<from-view-id>/login.xhtml</from-view-id>
<navigation-case>
<from-action>#{loginMB.login}</from-action>
<from-outcome>loggedIn</from-outcome>
<to-view-id>/index.xhtml</to-view-id>
<redirect />
</navigation-case>
</navigation-rule>
<!-- <managed-bean>
<managed-bean-name>loginMB</managed-bean-name>
<managed-bean-class> com.sample.jsfjpa.beans.LoginMB</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>userMB</managed-bean-name>
<managed-bean-class> com.sample.jsfjpa.beans.UserMB</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean> -->
</faces-config>

Managed beans are not created unless you specifically invoke one of their properties or methods. That happens for all the scopes, except the #ApplicationScoped ones having #ManagedBean(eager=true) which are specifically created when JSF context loads.
Here you're referencing #{loginMB} from the view, but not #{userMB} so there's no chance to have it created.
In order to instance your #SessionScoped managed bean you can add following code in your login page:
<f:metadata>
<f:event type="preRenderView" listener="#{userMB.initialize}" />
</f:metadata>
Which sets a listener that is executed before page rendering. You can invoke here just an empty method (to execute it JSF will construct your bean if not already created).
Starting from JSF 2.2 you can replace the preRenderView method for the new f:viewAction, which has some benefits (it's parameterless and it doesn't get invoked on postbacks ):
<f:metadata>
<f:viewAction action="#{userMB.initialize}" />
</f:metadata>

Related

Conditional render in tagfile depending on whether the attribute is specified or not

I have a Facelet tagfile and need to render different components depending on whether the attribute is specified or not. I tried it as below,
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:pe="http://primefaces.org/ui/extensions"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:panelGrid columns="1">
<p:outputLabel value="test1" rendered="#{empty myParam}" />
<p:outputLabel value="test2" rendered="#{not empty myParam}" />
</h:panelGrid>
</ui:composition>
Which is used as below,
<mt:myTag myParam="#{myManagedBean.someProperty}" />
However, it didn't work. It takes the evaluated value of #{myManagedBean.someProperty}. If it's empty, then it still shows test1. How can I check if the myParam attribute is actually being set or not?
Create another custom tag with a taghandler class which checks the presence of a certain attribute in the variable mapper of the current Facelet context, and sets a boolean in the Facelet scope indicating the presence of the desired attribute. Finally make use of it in your tagfile.
E.g.
<my:checkAttributePresent name="myParam" var="myParamPresent" />
<h:panelGrid columns="1">
<p:outputLabel value="test1" rendered="#{not myParamPresent}" />
<p:outputLabel value="test2" rendered="#{myParamPresent}" />
</h:panelGrid>
With this tag handler:
public class CheckAttributePresentHandler extends TagHandler {
private String name;
private String var;
public CheckAttributePresentHandler(TagConfig config) {
super(config);
name = getRequiredAttribute("name").getValue();
var = getRequiredAttribute("var").getValue();
}
#Override
public void apply(FaceletContext context, UIComponent parent) throws IOException {
context.setAttribute(var, context.getVariableMapper().resolveVariable(name) != null);
}
}
Which is registered as below in your .taglib.xml:
<tag>
<tag-name>checkAttributePresent</tag-name>
<handler-class>com.example.CheckAttributePresentHandler</handler-class>
<attribute>
<name>name</name>
<required>true</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<name>var</name>
<required>true</required>
<type>java.lang.String</type>
</attribute>
</tag>

validator for custom components in JSF fails

In my custom component, I have
<composite:interface>
<composite:editableValueHolder name="val_pwd" targets="form:pwd"/>
<composite:attribute name="name" required="true"/>
.....
</composite:interface>
<composite:implementation>
<h:form id="form">
<h:panelGrid columns="3">
<h:outputText value="#{cc.attrs.namePrompt}" />
<h:inputText value="#{cc.attrs.name}" id="name"/>
<h:outputText value="#{cc.attrs.passwordPrompt}" />
<h:inputSecret value="#{cc.attrs.pwd}" id="pwd"/>
<h:commandButton value="#{cc.attrs.submitButtonValue}" action="#{cc.attrs.actionMethod}"/>
</h:panelGrid>
</h:form>
</composite:implementation>
I have a validator,
#FacesValidator("passwordVal")
public class PasswordValidator implements Validator {
public PasswordValidator() {
super();
}
#Override
public void validate(FacesContext facesContext, UIComponent uIComponent, Object object) throws ValidatorException {
if(object instanceof String){
String s = (String) object;
if(s.contains("#"))
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error","Password cannot have #"));
}
}
}
In my JSF page, I have
<h:body>
<util:ccwithcustomval namePrompt="r_Name" passwordPrompt="r_pwd" name="#{person.name}"
pwd="#{person.pwd}" actionMethod="#{person.action}" submitButtonValue="r_submit">
<f:validateLength for="val_name" maximum="5"/>
<f:validator validatorId="passwordVal" for="val_pwd" />
</util:ccwithcustomval>
</h:body>
However, it fails with exception
InputComponent.xhtml #12,60 <f:validator> ADF_FACES-60085:Parent not an instance of
EditableValueHolder: javax.faces.component.UINamingContainer#4e18afaa
The problem is with my validator, if I comment it out the page displays

JSF Message on SUBMIT action

I begin with my case:
JSF 2.1
Tomcat 7.0.27
Netbeans as IDE
JSF and PRIMEFace (but optional)
Level JSF beginner
Level JAVA good and not god
I have done a simple JSF site to learn how to works with JSF. My question is based on Login example at this step the problem is not related about that login that is obviously insicure.
A bit of code:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
/**
*
* #author
*/
#ManagedBean
#SessionScoped
//#RequestScoped
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private final String userName = "User";
private final String userPassword = "12345";
private String name;
private String password;
private boolean isLogged=false;
public String getName() {
return name;
}
public void setName( String name ) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword( String password ) {
this.password = password;
}
public String login() {
if( !(userName==null || password==null)
&&
(userName.equals( name ) && userPassword.equals( password ))) {
isLogged=false;
return "main";
} else {
isLogged=true;
return "index";
}
}
public boolean getIsLogged(){
return isLogged;
}
}
The page index
<?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://java.sun.com/jsf/html">
<h:head>
<title>TSAM 7.5 Login</title>
</h:head>
<h:body>
Login system
<br />
<!--<h:link outcome="welcomePrimefaces" value="Primefaces welcome page" />-->
<h:form>
User : <h:inputText value="#{user.name}" />
Password : <h:inputSecret value="#{user.password}" />
<h:commandButton action="#{user.login()}" value="Submit" />
<h:commandButton value="reset" type="reset" />
<h:commandButton value="otherpage" action="otherpage"></h:commandButton>
</h:form>
</h:body>
</html>
The main page
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<f:event type="preRenderView" listener="#{user.isLogged}"/>
<f:view contentType="text/html">
<h:head>
<f:facet name="first">
<meta content='text/html; charset=UTF-8' http-equiv="Content-Type"/>
<title>PrimeFaces</title>
</f:facet>
</h:head>
<h:body>
<p:layout fullPage="true">
<p:layoutUnit position="north" size="100" resizable="true" closable="true" collapsible="true">
Header
</p:layoutUnit>
<p:layoutUnit position="south" size="100" closable="true" collapsible="true">
Footer
</p:layoutUnit>
<p:layoutUnit position="west" size="175" header="Left" collapsible="true">
<p:menu>
<p:submenu label="Resources">
<p:menuitem value="Demo" url="http://www.primefaces.org/showcase-labs/ui/home.jsf" />
<p:menuitem value="Documentation" url="http://www.primefaces.org/documentation.html" />
<p:menuitem value="Forum" url="http://forum.primefaces.org/" />
<p:menuitem value="Themes" url="http://www.primefaces.org/themes.html" />
</p:submenu>
</p:menu>
</p:layoutUnit>
<p:layoutUnit position="center">
Welcome to PrimeFaces
</p:layoutUnit>
</p:layout>
</h:body>
</f:view>
</html>
First
I use action="#{user.login()}" to make navigation action is this correct or there is a better pattern?
But the real question is: How to show a message If I redirect?
I like to show a message I know the example by PrimeFace http://www.primefaces.org/showcase/ui/dialogLogin.jsf. but it doesn't redirect or show anything.
But if i use only "plain" JSW without PrimeFace, i like to put a
because it is similar to PrimeFaces so switch is simple.
I'd like to adopt a "pattern" so i can reuse it for eg when i do a serch an no data is present, or when i call "erease DB" and application say work in progress an then say OK all bank account are esreased (Only an example!! but interesting because there are 2 message).
Thanks
I try
public String login() {
if (!(userName == null || password == null)
&& (userName.equals( name ) && userPassword.equals( password ))) {
isLogged = true;
return "main";
} else {
isLogged = false;
FacesMessage facesMsg;
facesMsg = new FacesMessage( FacesMessage.SEVERITY_ERROR, "No login", "No login because username or passsword are incorrect etc" );
FacesContext fc = FacesContext.getCurrentInstance();
fc.addMessage( "loginError", facesMsg );
return "index";
}
}
And edited the page
<h:body>
Login system
<br />
<!--<h:link outcome="welcomePrimefaces" value="Primefaces welcome page" />-->
<h:form>
User : <h:inputText value="#{user.name}" />
Password : <h:inputSecret value="#{user.password}" />
<h:commandButton action="#{user.login()}" value="Submit" />
<h:commandButton value="reset" type="reset" />
<h:commandButton value="Cambio Password" action="changePassword"></h:commandButton>
</h:form>
<h:message for="" style="color:red;margin:8px;"/>
</h:body>
It works but it's not ok because it's not ok to put a string in the bean. And I need the multilanguage this string has to generated by the beans.... mmm this is not OK something i'm missing.
There's extremely a lot of noise in the question. I understand that your question ultimately boils down to:
How do I create a localized faces message in bean action method?
In that case, just get the message from the current resource bundle yourself.
As you're talking about localization, you should surely already have something like as
<resource-bundle>
<base-name>com.example.i18n.text</base-name>
<var>text</var>
</resource-bundle>
in your faces-config.xml. You could just get it in the bean as well with help of ResourceBundle which JSF itself is actually also using under the covers
Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
ResourceBundle text = ResourceBundle.getBundle("com.example.i18n.text", locale);
This way you could compose your message as
String summary = text.getString("messages.no_login_summary");
String detail = text.getString("messages.no_login_detail");
new FacesMessage(FacesMessage.SEVERITY_ERROR, summary, detail);

Form doesn't submit values when commandLink is used instead of commandButton

I made following jsf page. In my Managed Bean i want evaluate the input,
but i dont get the values.
If i press my commandLink i dont get any values. when i use a commandButton it works:
<?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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<ui:composition template="../templates/common.xhtml">
<ui:define name="pageTitle">Test</ui:define>
<ui:define name="pageHeader">Test</ui:define>
<ui:define name="body">
<h:panelGroup id="messagePanel" layout="block">
<h:messages errorStyle="color: red" infoStyle="color: green"
layout="table" />
</h:panelGroup>
<h:form>
<h:outputLabel value="#{bundle.SearchAdressLabel_name}"
for="axname" />
<h:inputText id="axname"
value="#tbaxController.name}"
title="#{bundle.SearchAdressTitle_name}" />
</h:panelGrid>
<br />
<br />
<h:commandButton id="submit" value="#{bundle.SearchAdressLabel_cmdsearch}" action="#{tbaxController.prepareList}">
</h:commandButton>
<h:commandLink action="#{tbaxController.prepareList}"
value="#{bundle.SearchAdressLabel_cmdsearch}" immediate="true" />
<br />
<br />
<h:commandLink value="#{bundle.SearchAdressLabel_cmdclear}"
type="reset" />
</h:form>
</ui:define>
</ui:composition>
</html>
Here is a part of my MB:
#ManagedBean(name = "tbaxController")
#SessionScoped
public class tbaxController implements Serializable {
private static final long serialVersionUID = 1L;
private static final org.apache.log4j.Logger logger = org.apache.log4j.Logger
.getLogger(tbaxController.class);
private Tbax current;
private DataModel items = null;
#EJB
private TbaxFacade ejbFacade;
private PaginationHelper pagination;
private int selectedItemIndex;
private String name;
public tbaxController() {
}
public String getname() {
// Get the field
return searchAxart;
}
public void setname(String oname) {
// Set the field this.searchAxart
this.name = oname.trim();
}
...
public String prepareList() {
logger.info("prepareList:" + name); **//null with commandLink!
recreateModel();
return "ADList";
}
...
Why does my prepareList method doesn't get any values with a commandLink?
The immediate="true" makes jsf to step over the process validation and update model phases. It jump directly to invoke application phase. That's why you don't get any values on the model. Try removing it and see what happens.

When adding a faces message in JSF my actions aren't performed?

I have the following backing bean:
#ViewScoped
#ManagedBean
public class WeighFamilyBacking2 implements Serializable {
private static final long serialVersionUID = 1L;
private String[] children = new String[] { "Child1", "Child2", "Child3" };
private HashMap<String, Integer> newWeights;
public WeighFamilyBacking2() {
newWeights = new HashMap<String, Integer>();
for (String s : getChildren())
newWeights.put(s, new Integer(0));
}
public void distributeWeightsWithoutMessage(ActionEvent event) {
for (String s : newWeights.keySet()) {
newWeights.put(s, newWeights.get(s) + 1);
}
}
public void distributeWeights(ActionEvent event) {
for (String s : newWeights.keySet()) {
newWeights.put(s, newWeights.get(s) + 1);
}
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage("Succesful", "Weights redistributed."));
}
public HashMap<String, Integer> getNewWeights() {
return newWeights;
}
public List<String> getChildren() {
return Arrays.asList(children);
}
}
... And the following xhtml page:
<!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:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
<h:body>
<h:form>
<ui:repeat var="child" value="#{weighFamilyBacking2.children}">
<h:outputText value="#{child}" />
<h:outputText value="#{weighFamilyBacking2.newWeights[child]}" /> -
<h:outputText value="#{weighFamilyBacking2.newWeights[child]}" /> -
<h:inputText id="oz" value="#{weighFamilyBacking2.newWeights[child]}" />
<h:inputText id="lbs"
value="#{weighFamilyBacking2.newWeights[child]}" />
<br />
</ui:repeat>
<h:commandButton
actionListener="#{weighFamilyBacking2.distributeWeights}"
value="Redistribute" />
<h:commandButton
actionListener="#{weighFamilyBacking2.distributeWeightsWithoutMessage}"
value="Redistribute Without Message" />
</h:form>
</h:body>
</html>
This is a simple reproducible test case. When you click on the redistribute without message, things work as expected. When you click on the redistribute button it displays the success message but the input fields are not updated. However, the text output field is updated just one time.
I have tried using immediate=true on both buttons and that doesn't affect this. This is a very simple case, I can't understand why it doesn't work.
I have tried this with all recent versions of Mojarra including 2.1.3.
This is another <ui:repeat> anomaly. I haven't nail down the exact root cause yet so that I can check if this is already reported to the JSF guys and if necessary report it, but I can tell that it works when I replace the <ui:repeat> by a <h:dataTable>.
<h:dataTable var="child" value="#{weighFamilyBacking2.children}">
<h:column>
<h:outputText value="#{child}" />
<h:outputText value="#{weighFamilyBacking2.newWeights[child]}" /> -
<h:outputText value="#{weighFamilyBacking2.newWeights[child]}" /> -
<h:inputText id="oz" value="#{weighFamilyBacking2.newWeights[child]}" />
<h:inputText id="lbs"
value="#{weighFamilyBacking2.newWeights[child]}" />
</h:column>
</h:dataTable>
Maybe a <table> is not semantically correct for you. If this is really undesireable, you might want to check if it works without problems with Tomahawk's <t:dataList>, RichFaces' <rich:dataList>, PrimeFaces' <p:dataList>, etc each which supports rendering the children without additional markup.
Update: I reported it as issue 2157.

Resources