JSF CommandButtons's action is not called when using rendered - jsf

When viewing this page with ?mode=test, the button doesn't work. It loads this page without ?mode=test, but h:panelGroup is rendered (because mode is set somewhere else). I use two methods of sending mode (h:inputHidden f:param) and to the server and nothing helps. View scoped bean is not available in CDI. What is the possible solution to this?
XHTML
<?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:f="http://xmlns.jcp.org/jsf/core">
<f:view>
<f:metadata>
<f:viewParam name="mode" value="#{test.mode}" />
</f:metadata>
<h:panelGroup layout="block" rendered="#{test.mode.equals('test')}">
<h:form>
<h:inputHidden value="#{test.mode}" />
<h:commandButton value="Run a method" action="#{test.method}">
<f:param name="mode" value="#{test.mode}" />
</h:commandButton>
</h:form>
</h:panelGroup>
<h:messages />
</f:view>
</html>
Java
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
#Named("test")
#RequestScoped
public class TestBean {
private String mode;
public void method() {
System.out.print(mode);
}
public String getMode() {
return mode;
}
public void setMode(String mode) {
this.mode = mode;
}
}

You've got a wide range of possibilities. The easiest one for you is not to bind the view parameter to the backing bean, just keep it bound to the view:
test.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<f:view>
<f:metadata>
<f:viewParam name="mode" value="#{mode}" />
</f:metadata>
<h:form rendered="#{mode eq 'test'}">
<h:commandButton value="Run a method" action="#{test.method(mode)}" />
</h:form>
<h:messages />
</f:view>
</html>
Test.java
#Named
#RequestScoped
public class Test {
public void method(String mode) {
System.out.print(mode);
}
}
If you however would like to switch to #ViewScoped, CDI compatible annotation is now available in JSF 2.2 version. The namespaces you're using suggest you do use that version, so go with it. For JSF prior versions, there's also the chance to do it with custom Omnifaces' annotation.
See also:
Omnifaces #ViewScoped annotation
#ViewScoped in CDI with JSF 2.2
Differences between EL 2.1 and 2.2

Related

using javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL causes viewParam to be null

I'm trying to switch an application from WildFly 13 (Java EE 7, JSF 2.2.15) to WildFly 16 (Java EE 8, JSF 2.3.9). Tried both PrimeFaces 6.2 and 7.0
In web.xml javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL is set.
JSF 2.2 version working fine, switching to WildFly 16 this different behavior. A simple example follows:
Instructions:
access: http://localhost:8080/primefaces-test/?tipo=U&test=Bah
click first button, click second button. after ajax the viewParam value in the bean is null, even it is filled within the url.
Sample project (Jetty): https://github.com/erickdeoliveiraleal/primefaces-test/tree/update
XHTML
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://java.sun.com/jsf/html">
<f:metadata>
<f:viewParam name="test" value="#{testView.testString}" />
<f:viewAction action="#{testView.inicializar}" />
</f:metadata>
<h:head>
<title>PrimeFaces Test</title>
</h:head>
<h:body>
<h:form id="cadastro">
<h:commandButton value="click me"
action="#{testView.inserirNaLista()}">
<f:ajax execute="#form" render="#form" />
</h:commandButton>
<p:commandButton
value="click me - 2 (this button causes the null value)"
action="#{testView.inserirNaLista()}" />
</h:form>
</h:body>
</html>
Bean
#ManagedBean(name = "testView")
#ViewScoped
public class TestView implements Serializable {
private String testString;
public void inicializar() {
System.out.println("initializing: " + testString);
}
public void inserirNaLista() {
System.out.println(testString);
}
public String getTestString() {
return testString;
}
public void setTestString(String testString) {
this.testString = testString;
}
}
fixed in WildFly 21 https://github.com/eclipse-ee4j/mojarra/issues/4550 and still pending official release in eclipse-ee4j

Unable to resolve "Managed Bean" issue while working with Java Serves Faces 2.2 [duplicate]

This question already has an answer here:
Eclipse won't autocomplete bean methods in EL when I use javax.annotation.ManagedBean
(1 answer)
Closed 6 years ago.
Template Client.xhtml
<?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://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<body>
<f:view contracts="#{themeSelector.themeName}">
<ui:composition template="/template.xhtml">
<ui:define name="top">
<h:form>
<h:outputLabel value="Theme" for="menu"></h:outputLabel>
<h:selectOneMenu id="menu" label="ThemeMenu" value="#{themeSelector.themeName}">
<f:selectItem itemLabel="Dark" itemValue="dark"></f:selectItem>
<f:selectItem itemLabel="Normal" itemValue="normal"></f:selectItem>
</h:selectOneMenu>
<h:message for="menu"></h:message>
<h:commandButton id="Submit" value="Submit" action="templateClient"></h:commandButton>
</h:form>
</ui:define>
</ui:composition>
</f:view>
</body>
</html>
ThemeSelector.java
package com.rshingha.example;
import javax.annotation.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.SessionScoped;
/**
*
* #author rshingha
*/
#ManagedBean
#RequestScoped
public class ThemeSelector {
private String themeName="dark";
public ThemeSelector()
{
}
public String getThemeName() {
return themeName;
}
public void setThemeName(String themeName) {
this.themeName = themeName;
}
}
Issue:
Following line in TemplateClient.xhtml
<f:view contracts="#{themeSelector.themeName}">
Here value of "contracts" attribute is not getting resolved, even when I am doing "Ctrl+click" on property name "themeName", its not going to that property in bean file
Interesting thing is when I am hardcoding value for "contracts" attribute then its working.
I also tried with #Named annotation , but same is happening in that case with one exception:
When I am doing "Ctrl+click" on property name "themeName", its navigating to that property in bean file
Please suggest anything , I am stuck
You got wrong import for #ManagedBean. Use this one javax.faces.bean.ManagedBean from JSF. If you want to use #Named (which is CDI technology) then you should also change imports for scopes, request scope would be javax.enterprise.context.RequestScoped.

Can't inject the selected value of a selectOneMenu in another bean

I was trying to see exactly how property injection works with ViewScoped beans.
I inject the List from One to Two without problem. When I try to inject the same List from Two to Three nothing is injected but I think that's the intended behavior (I might be wrong though).
However when I try to inject the selected value from the SelectOneMenu of Two into Three nothing is being injected.
Is there something I am missing or is that the normal behaviour? If so, how can I retrieve that value in Three?
One.java
#ManagedBean
#ViewScoped
public class One implements Serializable {
private List<String> oneList;
#PostConstruct
void init() {
setOneList(new ArrayList<String>());
getOneList().add("aaa");
getOneList().add("bbb");
getOneList().add("ccc");
getOneList().add("ddd");
}
//Getters + setters...
}
one.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition template="/WEB-INF/template.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<ui:define name="header">
<h:outputText value="ONE" />
</ui:define>
<ui:define name="content">
<h:form>
<p:commandButton value="two" action="two" ajax="false" />
</h:form>
</ui:define>
</ui:composition>
Two.java
#ManagedBean
#ViewScoped
public class Two implements Serializable {
#ManagedProperty("#{one.oneList}")
private List<String> oneList;
private String twoChoice;
//Getter + setters...
}
two.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition template="/WEB-INF/template.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<ui:define name="header">
<h:outputText value="TWO" />
</ui:define>
<ui:define name="content">
<h:form>
<p:selectOneMenu id="test" value="#{two.twoChoice}">
<f:selectItems value="#{two.oneList}" />
</p:selectOneMenu>
<p:commandButton value="three" action="three" ajax="false" />
</h:form>
</ui:define>
</ui:composition>
Three.java
#ManagedBean
#ViewScoped
public class Three implements Serializable {
#ManagedProperty("#{two.oneList}")
private List<String> oneList;
#ManagedProperty("#{two.twoChoice}")
private String twoChoice;
private String threeChoice;
//Getters + setters...
}
three.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition template="/WEB-INF/template.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<ui:define name="header">
<h:outputText value="THREE" />
</ui:define>
<ui:define name="content">
<h:outputText value="#{three.twoChoice}" />
</ui:define>
<h:form>
<p:selectOneMenu value="#{three.threeChoice}">
<f:selectItems value="#{three.oneList}" />
</p:selectOneMenu>
</h:form>
</ui:composition>
Managed properties are not intended to work like that. Keep in mind that a #ViewScoped bean is designed to keep alive as long as the view doesn't change, which means at the moment you navigate from one page to another using the non-ajax command button (in fact you're specifying the navigation-case to go in the action attribute), they should be destroyed, so you can't get any value from them.
Normally, I use #ManagedProperty notation to inject broader scope values (for example, a session value in a view scoped bean). So what is the solution for your case?
Actually you have different options:
You can use <f:viewParam /> tag to send the GET parameters while changing the view.
You can use flash scope, which keeps your values in a map that survives to a redirection. Not recomended if you are using Mojarra implementation of JSF, they still have to fix some problems with them.
Take care of the params yourself and set them in some data structure in session scope, after, when you recover them in your destination bean you can remove them.

JSF2.0 how do you pass a viewParam to a request scoped backing bean while using a commandButton?

I have the following page:
<?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">
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:o="http://omnifaces.org/ui"
xmlns:thehub="http://java.sun.com/jsf/composite/components/thehub"
template="/templates/masterTemplate.xhtml">
<f:metadata>
<f:viewParam
id="returnToViewParam"
name="returnTo"
value="#{loginMB.returnTo}"
required="true" />
<f:viewParam
id="oauth_verifierViewParam"
name="oauth_verifier"
value="#{loginMB.oauth_verifier}" />
<f:viewParam
id="oauth_tokenViewParam"
name="oauth_token"
value="#{loginMB.oauth_token}" />
<f:event
type="preRenderView"
listener="#{loginMB.preRenderView()}" />
</f:metadata>
<ui:define name="body">
<o:form
id="loginForm"
includeViewParams="true">
<div class="form-vertical well">
<h4>New Users</h4>
<h5>
<h:link outcome="signup">Click here to create an account</h:link>
</h5>
<hr />
<h4>Existing Users</h4>
<h:commandButton
id="googleLoginCommandLink"
styleClass="btn"
action="#{loginMB.redirect()}"
value="Google">
<f:param
name="returnTo"
value="#{param.returnTo}" />
</h:commandButton>
<div class="clearfix"></div>
</div>
</o:form>
</ui:define>
</ui:composition>
And the following bean:
#ManagedBean
#RequestScoped
public class LoginMB implements Serializable {
private static final long serialVersionUID = 1L;
private String returnTo;
public void redirect() {
log.debug("redirect() returnTo:{}", returnTo);
......getter/setters
}
No matter what I do, I can't seem to get returnTo bound once the commandButton is clicked. Since this is a login page, I'd really not like to have LoginMB be a #ViewScoped bean.
Advice? Is there a better way to handle this scenario?
EDIT:
I'm running this on TomEE+ Server v1.5.1 which is served up by MyFaces 2.1.10
Added full page
Clarified the problem: Inside the redirect() function, returnTo is null
Your <f:metadata> is outside <ui:define> and is therefore completely ignored. Add an <ui:insert name="metadata"> to the master template and put the <f:metadata> inside an <ui:define name="metadata"> of the template client.
See also:
When using <ui:composition> templating, where should I declare the <f:metadata>?
Once you fixed that, you can safely remove the <f:param> from the command button. This job is already done by <o:form includeViewParams="true">. If you didn't have it, then the <f:param> would indeed have been mandatory and you'd need to copypaste the same over all command links and buttons in the same form.

#Inject to pass params to a CDI #Named bean via URL

If I cannot use the #ManagedProperty annotation with #Named, because #ManagedProperty doesn't work in CDI(?), then how do you pass params in the URL to the facelets client? In my code, I want to pass javax.mail.getMessageNumber() to details.xhtml through the "back" and "forward" buttons.
I understand that #Inject should be used, but what is being injected and how, please?
From the glassfish logs, id is always 0, which is quite odd. Even when "forward" is clicked, id never gets above 1 no matter how many times the button is clicked. Of course, that's merely a symptom of the problem. The desired output, of course, is to advance to the next Message.
Perhaps put the Message, or at least the int, into the session?
The client as so:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
template="./template.xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core">
<ui:define name="top">
<h:form>
<h:form>
<h:outputLink id="link1" value="detail.xhtml">
<f:param name="id" value="#{detail.back()}" />
<h:outputText value="back" />
</h:outputLink>
</h:form>
</h:form>
<h:form>
<h:outputLink id="link1" value="detail.xhtml">
<f:param name="id" value="#{detail.forward()}" />
<h:outputText value="forward" />
</h:outputLink>
</h:form>
</ui:define>
<ui:define name="content">
<h:outputText value="#{detail.content}"></h:outputText>
</ui:define>
</ui:composition>
and the bean as so:
package net.bounceme.dur.nntp;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.enterprise.context.RequestScoped;
import javax.faces.bean.ManagedProperty;
import javax.inject.Named;
import javax.mail.Message;
#Named
#RequestScoped
public class Detail {
private static final Logger logger = Logger.getLogger(Detail.class.getName());
private static final Level level = Level.INFO;
#ManagedProperty(value = "#{param.id}")
private Integer id = 0;
private Message message = null;
private SingletonNNTP nntp = SingletonNNTP.INSTANCE;
public Detail() {
message = nntp.getMessage(id);
}
public int forward() {
logger.log(level, "Detail.forward.." + id);
id = id + 1;
logger.log(level, "..Detail.forward " + id);
return id;
}
public int back() {
logger.log(level, "Detail.back.." + id);
id = id - 1;
logger.log(level, "..Detail.back " + id);
return id;
}
public Message getMessage() {
return message;
}
public String getContent() throws Exception {
return message.getContent().toString();
}
}
This works only with the in JSF 2.3 introduced javax.faces.annotation.ManagedProperty.
#Inject #ManagedProperty("#{param.id}")
private String id;
The now deprecated javax.faces.bean.ManagedProperty annotation works only in JSF #ManagedBean classes. I.e. in instances which are managed by JSF. It does not work in instances which are managed by CDI #Named. Further, you've made another mistake: you're trying to prepare the Message based on the managed property in the constructor. If it were a real #ManagedBean, that would also not have worked. The managed property is not available during construction, simply because it's not possible to call the setter method before the constructor is called. You should have used a #PostConstruct method for this.
If you cannot upgrade to JSF 2.3, you'd need to create a custom CDI annotation. A concrete example is posted in this blog. Here's an extract of relevance:
The custom #HttpParam annotation:
#Qualifier
#Retention(RUNTIME)
#Target({TYPE, METHOD, FIELD, PARAMETER})
public #interface HttpParam {
#NonBinding
public String value() default "";
}
The annotation value producer:
public class HttpParamProducer {
#Inject
FacesContext facesContext;
#Produces
#HttpParam
String getHttpParameter(InjectionPoint ip) {
String name = ip.getAnnotated().getAnnotation(HttpParam.class).value();
if ("".equals(name)) name = ip.getMember().getName();
return facesContext.getExternalContext()
.getRequestParameterMap()
.get(name);
}
}
An usage example:
#Inject #HttpParam
private String id;
JSF utility library OmniFaces has a #Param for exactly this purpose, with builtin support for JSF conversion and validation.
Alternatively, you can also manually grab the request parameter from the external context in the Detail managed bean. The recommended way to do managed bean initialization is to use a #PostConstruct method, not the constructor, as the constructor could be used for completely different purposes than managed bean creation:
#PostConstruct
public void init() {
String id = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("id");
// ...
}
Another way, IMO also more suitable for this particular case, is to use <f:viewParam> which also allows you to convert the ID to Message directly by a custom converter.
<f:metadata>
<f:viewParam name="id" value="#{detail.message}" converter="messageConverter" />
</f:metadata>
with just
#Named
public class Detail {
private Message message;
// Getter+setter
}
and a
#FacesConverter("messageConverter")
public class MessageConverter implements Converter {
// Convert string id to Message object in getAsObject().
// Convert Message object to string id in getAsString().
}
See also
ViewParam vs #ManagedProperty(value = "#{param.id}")
Communication in JSF 2.0 - processing GET request parameters
First, to explain the alien part - Glassfish uses JBoss Weld as its CDI implementation, Oracle does not develop an implementation of its own.
And concerning the meaning of the error message: FacesContext is simply not injectable via #Inject. There is an rather old feature request for that, and I think Seam or Solder provide a producer. But there's no need to integrate either of the libraries just for that. Access faces context like you would in normal managed bean, via FacesContext.getCurrentInstance().
I was asking a complex way of doing a simple thing. In CDI, to pass params around you cannot use #ManagedProperty, as explained above by BalusC. Instead, you just setup your xhtml files as so:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
template="./template.xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core">
<ui:define name="top">
<h:form>
<h:commandButton action="#{messages.back()}" value="..back" />
</h:form>
<h:form>
<h:commandButton action="#{messages.forward()}" value="forward.." />
</h:form>
</ui:define>
<ui:define name="content">
<h:dataTable value="#{messages.model}" var="m">
<h:column>
<f:facet name="id">
<h:outputText value="id" />
</f:facet>
<h:outputLink id="hmmm" value="detail.xhtml">
<f:param name="id" value="#{m.getMessageNumber()}" />
<h:outputText value="#{m.getMessageNumber()}" />
</h:outputLink>
</h:column>
<h:column>
<f:facet name="subject">
<h:outputText value="subject" />
</f:facet>
<h:outputText value="#{m.subject}"></h:outputText>
</h:column>
<h:column>
<f:facet name="content">
<h:outputText value="content" />
</f:facet>
<h:outputText value="#{m.sentDate}"></h:outputText>
</h:column>
<h:column>
<f:facet name="date">
<h:outputText value="date" />
</f:facet>
<h:outputLink value="#{messages.getUrl(m)}">#{messages.getUrl(m)}</h:outputLink>
</h:column>
</h:dataTable>
</ui:define>
</ui:composition>
to:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
template="./template.xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core">
<ui:define name="top">
<h:form>
<h:outputLink id="back" value="detail.xhtml">
<f:metadata>
<f:viewParam name="id" value="#{detail.id}" />
</f:metadata>
<f:param name="id" value="#{detail.back()}" />
<h:outputText value="back" />
</h:outputLink>
</h:form>
<h:form>
<h:outputLink id="forward" value="detail.xhtml">
<f:metadata>
<f:viewParam name="id" value="#{detail.id}" />
</f:metadata>
<f:param name="id" value="#{detail.forward()}" />
<h:outputText value="forward" />
</h:outputLink>
</h:form>
</ui:define>
<ui:define name="content">
<h:outputText value="#{detail.content}"></h:outputText>
</ui:define>
</ui:composition>
I'm only including this for anyone who comes along, to clarify that, for this simple example, you don't need a Converter, that the default works fine.
The original question is more than a bit mangled, as well. From looking at other questions on this, I think others could benefit from a simple example such as this. So many examples are overly complex, or involve EJB, etc.

Resources