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.
Related
i want to pass GET parameter from URL to a method, that called by clicking on button.
For example i have URL: /someurl/semepage.xhtml?id=1. And i have a button on my page:
<p:commandButton value="say it" action="#{test.sayIt(param['id'])}"/>
The bean looks like:
#ManagedBean
#ViewScoped
public class Test{
public void sayIt(String value){
System.out.println(value);
}
}
But when i am clicking on button, its just not react. Why is this happen ? Method even not called.
If i pass arguments staticaly like here:
<p:commandButton value="say it" action="#{test.sayIt('someword')}"/>
everything is ok.
Here is one way - using the <f:param, like this:
<h:commandButton value="Test The Magic Word" action="#{test.sayIt}">
<f:param name="id" value="#{param['id']}"></f:param>
<f:ajax execute="something" render="something_else"></f:ajax>
</h:commandButton>
And in your bean
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext()
.getRequest();
String id = request.getParameter("id");
#Daniel's response is OK, but here it goes a simpler JSF 2-ish alternative for your case, using <f:viewParam /> and EL parameter passing. Note the <f:ajax /> is not needed in this case, as <p:commandButton /> has ajax behaviour by default.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head />
<h:body>
<f:metadata>
<f:viewParam name="id" />
</f:metadata>
<h:form>
<p:commandButton value="say it" action="#{bean.sayIt(id)}" />
</h:form>
</h:body>
</html>
#ManagedBean
#ViewScoped
public class Bean implements Serializable {
public void sayIt(String value) {
System.out.println(value);
}
}
Tested with JSF 2.2.5 and Primefaces 4. Remember changing tag namespaces in case of using JSF 2.1.x.
Just for the fun of it, have you tried request.getParameter('id')?
I am developing a project using JSF. In an opening popup window, i want to show some details about a product but can not get view scoped bean' s value on a datatable.
Can you help me?
Thanks.
Here is my UrunuDenetlemeSayfasi.xhtml code snippet:
<h:commandLink onclick="window.open('UruneGozAt.xhtml',
'Ürün İçeriği', config='width=700, height=400, top=100, left=100,
scrollbars=no, resizable=no');"
action="#{uruneGozAtBean.urunIdsineGoreUrunIcerigiGetir}" value="Ürün İçeriğine Göz At">
<f:param name="urunid" value="#{urun.urunID}" />
</h:commandLink>
Here is UrunuGozAt.xhtml:
<!DOCTYPE html>
<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">
<h:body>
<h:dataTable class="table table-striped"
value="#{uruneGozAtBean.urunIcerik}" var="urun">
<h:column>
<f:facet name="header">
<h:outputText value="barkod no" />
</f:facet>
<h:outputText value="#{urun.barkodNo}" />
</h:column>
</h:dataTable>
</h:body>
</html>
Here is UruneGozAtBean.java
UrunDenetlemeSayfasiBean urunDenetle = new UrunDenetlemeSayfasiBean();
UrunDenetleService urunService = new UrunDenetleService();
private UrunIcerik urunIcerik = new UrunIcerik();
private Long urunIdParametre;
public UrunIcerik getUrunIcerik() {
return urunIcerik;
}
public void setUrunIcerik(UrunIcerik urunIcerik) {
this.urunIcerik = urunIcerik;
}
public Long getUrunIdParametre() {
return urunIdParametre;
}
public void setUrunIdParametre(Long urunIdParametre) {
this.urunIdParametre = urunIdParametre;
}
public void urunIdsineGoreUrunIcerigiGetir() {
setUrunIcerik(urunService.urunIdsineGoreUrunIcerigiGetir(urunIdEldeEt()));
}
public Long urunIdEldeEt(){
FacesContext fc = FacesContext.getCurrentInstance();
setUrunIdParametre(getUrunIdParametre(fc));
return getUrunIdParametre();
}
public Long getUrunIdParametre(FacesContext fc){
Map<String, String> parametre = fc.getExternalContext().getRequestParameterMap();
return Long.valueOf(parametre.get("urunid")).longValue();
}
EDIT:
This is now my current implementation, it returns null.
i am developing a project using JSF. In an opening popup window, i want to show some details about a product but can not get view scoped bean' s value on a datatable.
Can you help me?
Thanks.
Here is my UrunuDenetlemeSayfasi.xhtml code snippet:
<h:commandLink onclick="window.open('UruneGozAt.xhtml','Ürün İçeriği',
config='width=700, height=400, top=100, left=100, scrollbars=no, resizable=no');"
value="Ürün İçeriğine Göz At"> <f:param name="urunId" value="#{urun.urunID}" />
</h:commandLink>
Here is UruneGozAt.xhtml:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<f:metadata>
<f:viewParam name="urunId" value="#{uruneGozAtBean.urunId}"
required="false" />
<f:viewAction action="#{uruneGozAtBean.urunIdsineGoreUrunIcerigiGetir()}" />
</f:metadata>
<h:head>
<title>Ürün İçeriği</title>
<!-- add this always, even if it's empty -->
</h:head>
<h:body>
<h:dataTable class="table table-striped"
value="#{uruneGozAtBean.urunIcerik}" var="urun">
<h:column>
<f:facet name="header">
<h:outputText value="barkod no" />
</f:facet>
<h:outputText value="#{urun.barkodNo}" />
</h:column>
</h:dataTable>
</h:body>
</html>
Here is UruneGozAtBean.java
#ManagedBean
#ViewScoped
public class UruneGozAtBean {
public UrunDenetlemeSayfasiBean urunDenetle = new UrunDenetlemeSayfasiBean();
public UrunDenetleService urunService = new UrunDenetleService();
private ArrayList<UrunIcerik> urunIcerik = new ArrayList<UrunIcerik>();
private Long urunId;
public Long getUrunId() {
return urunId;
}
public void setUrunId(Long urunId) {
this.urunId = urunId;
}
public ArrayList<UrunIcerik> getUrunIcerik() {
return urunIcerik;
}
public void setUrunIcerik(ArrayList<UrunIcerik> urunIcerik) {
this.urunIcerik = urunIcerik;
}
public void urunIdsineGoreUrunIcerigiGetir() {
setUrunIcerik(urunService.urunIdsineGoreUrunIcerigiGetir(urunIdEldeEt()));
System.out.print("aaa");
}
public Long urunIdEldeEt() {
FacesContext fc = FacesContext.getCurrentInstance();
setUrunId(getUrunId(fc));
return getUrunId();
}
public Long getUrunId(FacesContext fc) {
Map<String, String> parametre = fc.getExternalContext().getRequestParameterMap();
return Long.valueOf(parametre.get("urunId")).longValue();
}
}
#ViewScoped beans are alive per view. If you open a popup window from your current view, then you're opening a new view, so even if it uses the same managed bean to display the data, since they're different views, they use different instances of the same class.
In cases like this, you should pass a parameter through query string, then receive it in your view and process it to load the desired data. In this case, your code would be like this (note: make sure you send the parameter with name "urunId"):
UrunuGozAt.xhtml:
<!DOCTYPE html>
<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">
<h:head>
<!-- add this always, even if it's empty -->
<f:metadata>
<f:viewParam name="urunId" value="#{uruneGozAtBean.urunId}"
required="false" />
<f:viewAction action="#{uruneGozAtBean.loadData}" />
</f:metadata>
</h:head>
<h:body>
<h:dataTable class="table table-striped"
value="#{uruneGozAtBean.urunIcerik}" var="urun">
<h:column>
<f:facet name="header">
<h:outputText value="barkod no" />
</f:facet>
<h:outputText value="#{urun.barkodNo}" />
</h:column>
</h:dataTable>
</h:body>
</html>
UruneGozAtBean managed bean:
#ViewScoped
#ManagedBean
public class UruneGozAtBean {
//your current fields, getters and setters...
private Long urunId;
//getter and setter for this field...
public void loadData() {
if (urunId != null) {
//load the data for the table...
}
}
}
More info:
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
How to choose the right bean scope?
DataTable expects a list to iterate through, but as far as I can see you return an UrunIcerik object.
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
This question already has an answer here:
#ViewScoped calls #PostConstruct on every postback request
(1 answer)
Closed 6 years ago.
ARGH... This seems to have a hundred answers and I haven't found one that works for me, so I guess I will actually ask it again. Here is my scenario:
My site technically has a single page whose contents get swapped out rather than having multiple pages that you navigate to. The starting point is this chunk:
<?xml version="1.0" encoding="UTF-8"?>
<f:view xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head />
<h:body>
<ui:include src="resourceInclude.xhtml" />
<ui:include src="main.xhtml" />
</h:body>
</f:view>
The resourceInclude.xhtml includes my css file:
<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:outputStylesheet library="css" name="test.css" target="head" />
</ui:composition>
And main.xhtml is the view:
<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
<h:panelGroup styleClass="test-container" layout="block">
<h:form id="main-form">
<h:panelGroup styleClass="test-header" layout="block">
<h:panelGroup styleClass="navigation" layout="block">
<ul>
<li><h:commandLink action="#{viewSelector.setModeHome}">
<h:outputText value="Home" />
</h:commandLink></li>
<li><h:commandLink action="#{viewSelector.setModeReports}">
<h:outputText value="ASAP Reports" />
</h:commandLink></li>
<li><h:commandLink action="#{viewSelector.setModeSupport}">
<h:outputText value="Technical Support" />
</h:commandLink></li>
<li><h:commandLink action="#{viewSelector.setModeHelp}">
<h:outputText value="Help" />
</h:commandLink></li>
</ul>
</h:panelGroup>
</h:panelGroup>
<h:panelGroup styleClass="test-content" layout="block">
<ui:include src="#{viewSelector.modeName}-view.xhtml" />
</h:panelGroup>
<h:panelGroup styleClass="test-footer" layout="block">
<h:messages />
</h:panelGroup>
</h:form>
</h:panelGroup>
</ui:composition>
It consists of three h:panelGroups. The first is a set of four general navigation links, each link changes the viewSelector.modeName value which is used to include the contents in the second h:panelGroup thusly <ui:include src="#{viewSelector.modeName}-view.xhtml" />. I have stripped this down for this example so each view is basically this:
<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
<h:panelGroup styleClass="test-home-view">
<p>home</p>
</h:panelGroup>
</ui:composition>
The third h:panelGroup is a footer for all the messages to debug what is going wrong.
Anyway, every time I click one of the navigation links, the constructor of the viewSelector bean gets called. This is what my viewSelector bean looks like:
package org.mitre.asias.aires.controller;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import org.apache.log4j.Logger;
#ManagedBean( name="viewSelector" )
#ViewScoped
public class ViewSelector {
protected static Logger log = Logger.getLogger( ViewSelector.class );
private Mode mode = Mode.HOME;
public static final String PORTLET_NAME = "Test";
public static enum Mode {
HOME(1, "home"),
REPORTS(2, "reports"),
SUPPORT(3, "support"),
HELP(4, "help");
private int value;
private String name;
private Mode( int value, String name ) {
this.value = value;
this.name = name;
}
public int getValue() {
return value;
}
public String getName() {
return name;
}
}
public ViewSelector() {
log.trace( "constructing new ViewSelector" );
}
public Mode getMode() {
log.trace( "getting mode" );
return mode;
}
public String getModeName() {
log.debug( "in getmodename" );
return getMode().getName();
}
public String getPortletName() {
return PORTLET_NAME;
}
public boolean isModeReports() {
return getMode() == Mode.REPORTS;
}
public void setMode( Mode mode ) {
this.mode = mode;
}
public void setModeHelp() {
setMode( Mode.HELP );
}
public void setModeHome() {
setMode( mode = Mode.HOME );
}
public void setModeReports() {
setMode( mode = Mode.REPORTS );
}
public void setModeSupport() {
setMode( mode = Mode.SUPPORT );
}
}
I know I must be doing something the wrong way, or else I missing something central as to how JSF works. Any Input?
The EL in <ui:include src> is causing that.
If disabling the partial state saving in web.xml as per issue 1492 is not an option,
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>true</param-value>
</context-param>
then you need to replace
<ui:include src="#{viewSelector.modeName}-view.xhtml" />
by something like
<h:panelGroup rendered="#{viewSelector.mode == 'HOME'}">
<ui:include src="home-view.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{viewSelector.mode == 'REPORTS'}">
<ui:include src="reports-view.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{viewSelector.mode == 'SUPPORT'}">
<ui:include src="support-view.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{viewSelector.mode == 'HELP'}">
<ui:include src="help-view.xhtml" />
</h:panelGroup>
A similar question has at least been asked once before :)
How to ajax-refresh dynamic include content by navigation menu? (JSF SPA)
As soon as a composite which encapsulates a commandButton is included in my .xhtml, the viewscoped bean is reinitialized no matter which commandButton is used. Is my composite wrong? Please let me know because I realy would like to use composites for my buttons.
Simplyfied testcase:
#ManagedBean
#ViewScoped
public class Test implements Serializable {
private static final long serialVersionUID = 123456L;
private static int i = 0;
private int counter;
private String table;
private transient DataModel<String> model;
#PostConstruct
public void test() {
System.out.println(".......... PostConstruct");
i++;
List<String> modelData = new ArrayList<String>();
modelData.add("hello");
modelData.add("world");
model = new ListDataModel<String>(modelData);
}
public int getCounter() {
return counter;
}
public String getTable() {
return table;
}
public DataModel<String> getModel() {
return model;
}
public void tableListener() {
String data = model.getRowData();
table = data.toUpperCase();
}
}
No matter which button is clicked (2nd or 3th column), the postConstruct method is called over and over again
<h:form>
<h:dataTable style="width: 40em" var="line" value="#{test.model}">
<h:column>
<f:facet name="header">string</f:facet>
#{line}
</h:column>
<h:column>
<f:facet name="header">actie...1</f:facet>
<h:commandButton value="toUpper" immediate="true" >
<f:ajax event="click" execute="#form" render=":testTable" listener="#{test.tableListener}" />
</h:commandButton>
</h:column>
<h:column>
<f:facet name="header">actie...2</f:facet>
<cmp:rowAction managedBean="#{test}" label="button" listener="tableListener"
tooltip="test via composite" img="stop.png" render=":testTable"/>
</h:column>
</h:dataTable>
</h:form>
As soon as the last column (header actie...2) is removed, then the #PostConstruct is called only once, as expected.
Why does the presence of my composite forces to reinitialize the viewscoped bean? What's wrong with my composite, it works, but it shouldn't reinitialize the managed bean:
<?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:cc="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<!-- INTERFACE -->
<cc:interface>
<cc:attribute name="label" required="true"/>
<cc:attribute name="render"/>
<cc:attribute name="tooltip"/>
<cc:attribute name="img"/>
<cc:attribute name="listener" required="true"/>
<cc:attribute name="managedBean" required="true"/>
</cc:interface>
<!-- IMPLEMENTATION -->
<cc:implementation>
<h:commandButton id="btn_#{cc.attrs.label}" title="#{cc.attrs.tooltip}" immediate="true"
image="/resources/img/#{cc.attrs.img}">
<f:ajax event="click" execute="#form" render="#{cc.attrs.render}" listener="#{cc.attrs.managedBean[cc.attrs.listener]}" />
</h:commandButton>
</cc:implementation>
based on this post, JSF 2 - How can I add an Ajax listener method to composite component interface? i've found a solution. The problem was the declaration of the listener attribute cc:attribute name="listener" required="true"/> it should be cc:attribute name="listener" method-signature="void listener()" required="true"/>
There is still one (in my case minor) problem as mentioned by BalusC in the previously mentioned post: I can't us the AjaxBehvaiorEvent. I'm using Netbeans 6.9.1, Gfish3.1 and Mojarra2.1.1