I have problem with parameter at my web application. At some page (index.xhtml) i have:
...
<f:metadata>
<f:viewParam name="backurl"/>
</f:metadata>
<h:form>
<h:outputLabel value="backurl: #{backurl}"/>
<h:commandButton image="/resources/graphics/poland.gif" action="#{userController.setLanguage('pl', param['backurl'])}"/>
</h:form>
setLanguage() method in userController managed bean:
public void setLanguage(String language, String backurl) {
setLang(new Locale(language));
...
}
when i run application and go to index.xhtml page i see backurl: /pages/login.xhtml
but at setLanguage method second parametr (backurl) is null when i click and debug application
Where is problem ?
why dont you use this?
<h:commandButton action="#{userController.setLanguage}">
<f:param name="param1" value="value1" />
<f:param name="backurl" value="#{backurl}" />
</h:commandButton>
and then in your method
public String setLanguage() {
Map<String,String> params =
FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
String param1= params.get("param1");
String backurl= params.get("backurl");
}
#{userController.setLanguage('pl', backurl)}
this should work. (didn't test it)
there are many ways to pass parameters to a backing bean. Here is a useful article
You can store the view-param value in the managed-bean (provide accessors for the introduced backurl member, also).
<f:metadata>
<f:viewParam name="backurl" value="#{userController.backurl}" />
</f:metadata>
And then you can get rid of the second method parameter and get the backurl value from the variable in the managed-bean.
action="#{userController.setLanguage('pl')}"/>
The managed bean should look like this:
public class UserController {
private String backurl;
public String getBackurl() { return backurl; }
public void setBackurl(String backurl) { this.backurl = backurl; }
public void setLanguage(String language) {
setLocale(new Locale(language));
System.out.println(backurl); //this refers the variable in the managed-bean
}
}
Related
I'm using JSF 2.0 and I want to invoke a function defined in a Java controller when I click on an ace:textEntry.
I tried in this way:
<ace:textEntry readonly="true" value="#{myController.getValue()}"
onclick="#{myController.myFunc()}"/>
but when my page is open, the click event is called instantly.
So, I tried with:
<ace:textEntry readonly="true" value="#{myController.getValue()}">
<ace:ajax event="click" listener="#{myController.myFunc()}"/>
</ace:textEntry>
but my page is not rendered.
Is there another way to implement this behaviour ?
PS: I can use similar JSF components instead of ace:textEntry too.
First, you do not access getters directly in JSF for value backing - you access the property. Secondly, you should call the listener with the correct signature. To correct your example I would first rewrite the call like this,
<ace:textEntry readonly="true" value="#{myController.value}">
<ace:ajax event="click" listener="#{myController.myFunc}"/>
</ace:textEntry>
Then define MyController, like this;
#Named
#ViewScoped
public class MyController {
private value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public void myFunc(javax.faces.event.AjaxBehaviorEvent event) {
/* Do somethinig here... */
}
}
I want to use one html page with two ManagedBeans. Depending on the parameter in the URL, I want to set the bean name through JSTL variable. For example:
<c:set var="bean" value="#{webModule1}" scope="request" />
or
<c:set var="bean" value="#{webModule2}" scope="request" />
I have class which was use all this time, so for sure this works:
#ManagedBean(name = "webModule1")
#ViewScoped
public class WebModule1 implements Serializable {
protected WebModulesFormBean form;
#PostConstruct
public void init() {
if (!firstInit()){
this.form= new WebModulesFormBean();
}
//some code
}
public void process() {
if(this.form.isActive()){
//some code
}
}
}
And new one:
#ManagedBean(name = "webModule2")
#ViewScoped
public class WebModule2 extends WebModule1 {
public void process() {
if(this.form.isActive()){
//code with some changes
}
}
}
This solutions works with value attribute and form in not null, for example:
<p:treeTable value="#{bean.form.root}" var="node" id="modulesTree">
But I have problem with this piece of code:
<p:poll listener="#{bean.process()}" widgetVar="documentOutcome" autoStart="#{bean.form.start}" update="modulesTree" async="false"
interval="1" id="myPoll2" />
When listener is called, NullPointerException appears.
And this problem is with all p:polls (I have a few), so this is not a problem with method code.
Problem is that 'form' is null, although at the beginning variable 'form' is initialized and treeTable is shown at the page. So 'form' starts to be null when the listener is called.
Thanks!
I have a solution!
The problem was with:
<c:set var="bean" value="#{webModule1}" scope="request" />
scope="request" was not enough and in my understanding this scope meant that when poll was called, a new bean reference was created and form variable was null because it was not a firstInit().
scope="view" is the solution.
Thank you for comments!
I am beginner in java server faces (JSF), I need to pass the content of text input to second page to display it, the same applies for the second page: I want to pass radio buttons values to a third page. I searched and tried a lot without success.
For example I tried
<h:commandButton value="Next" action="#{myBean.execute(input_id.value)}"/>
Execute method is:
public void execute(String value) {
// ...
try{
FacesContext.getCurrentInstance().getExternalContext().dispatch("/Quizy.xhtml?faces-redirect=true");
}
catch(Exception e){
System.out.println("err");
}
}
Any suggestions?
Here are 4 other ways to pass a parameter value from JSF page to other page JSF :
1- Method expression (JSF 2.0)
2- f:param
3- f:attribute
4- f:setPropertyActionListener
1. Method expression
Since JSF 2.0, you are allow to pass parameter value in the method expression like this #{bean.method(param)}.
JSF page
<h:commandButton action="#{user.editAction(delete)}" />
ManagedBean
#ManagedBean(name="user")
#SessionScoped
public class UserBean{
public String editAction(String id) {
//id = "delete"
}
}
2- f:param
Pass parameter value via f:param tag and get it back via request parameter in backing bean.
JSF page
<h:commandButton action="#{user.editAction}">
<f:param name="action" value="delete" />
</h:commandButton>
ManagedBean
#ManagedBean(name="user")
#SessionScoped
public class UserBean{
public String editAction() {
Map<String,String> params =
FacesContext.getExternalContext().getRequestParameterMap();
String action = params.get("action");
//...
}
}
3. f:atribute
Pass parameter value via f:atribute tag and get it back via action listener in backing bean.
JSF page
<h:commandButton action="#{user.editAction}" actionListener="#{user.attrListener}">
<f:attribute name="action" value="delete" />
</h:commandButton>
ManagedBean
#ManagedBean(name="user")
#SessionScoped
public class UserBean{
String action;
//action listener event
public void attrListener(ActionEvent event){
action = (String)event.getComponent().getAttributes().get("action");
}
public String editAction() {
//...
}
}
4. f:setPropertyActionListener
Pass parameter value via f:setPropertyActionListener tag, it will set the value directly into your backing bean property.
JSF page
<h:commandButton action="#{user.editAction}" >
<f:setPropertyActionListener target="#{user.action}" value="delete" />
</h:commandButton>
ManagedBean
#ManagedBean(name="user")
#SessionScoped
public class UserBean{
public String action;
public void setAction(String action) {
this.action = action;
}
public String editAction() {
//now action property contains "delete"
}
}
There are several ways for doing this, but here is one of them.
You will need to save the inputText value into a property of your bean and both your h:inputText and your h:commanButton should be in the same h:form element
Here is a sample code
In your view
<h:form>
...
<h:inputText value={myBean.someValue} />
....
<h:commandButton value="Next" action="#{myBean.execute()}"/>
</h:form>
Your managed bean should be at least session scoped if you want your property (someValue) to be available in different pages. The content of the managed bean should look like this also:
private String someValue;
// Getter and setter for `someValue`
public String execute() {
// ...
return "/Quizy.xhtml?faces-redirect=true";
}
In the second page if you want to retrieve that value, just use #{myBean.someValue}
to have this done, you just need to set the Value of Your component here inputText or radioButton to a Property of your Managed bean or Cdi bean called on the page of course you won't forget to have getter and setter method for ur property in ur bean. Finally be sure that the scope of Ur bean allow it to be alive (with all its properties' value) across the session. Then, from ur end page you may call ur Managed bean or Cdi bean proprety as value of page components
I am going through an example in Anghel Leonard book Mastering Java Server Faces 2.2.
The author demonstrates with an example on how preserve data for the next request on redirection when the bean is made is #RequestScoped.
This is the code for index.xhtml-
<h:body>
<f:metadata>
<f:event type="preRenderView"
listener="#{playersBean.pullValuesFromFlashAction}"/>
</f:metadata>
<h:messages />
<h:form>
Name: <h:inputText value="#{playersBean.playerName}"/>
Surname: <h:inputText value="#{playersBean.playerSurname}"/>
<h:commandButton value="Register"
action="#{playersBean.addValuesToFlashAction()}"/>
</h:form>
</h:body>
terms.xhtml-
<h:body>
<h:messages />
Hello, <h:outputText value="#{flash.keep.playerName} #{flash.keep.playerSurname}"/>
<br/><br/>Terms & Conditions ... ... ... ... ...
<h:form>
<h:commandButton value="Reject"
action="#{playersBean.termsRejectedAction()}" />
<h:commandButton value="Accept"
action="#{playersBean.termsAcceptedAction()}" />
</h:form>
</h:body>
done.xhtml-
<h:head>
<title></title>
</h:head>
<h:body>
<f:metadata>
<f:event type="preRenderView"
listener="#{playersBean.pullValuesFromFlashAction}"/>
</f:metadata>
<h:messages />
<h:outputText value="#{playersBean.playerName} #{playersBean.playerSurname}"/>
successfully registered!
</h:body>
And the backing bean-
#ManagedBean
#RequestScoped
public class PlayersBean {
private final static Logger logger = Logger.getLogger(PlayersBean.class.getName());
private String playerName;
private String playerSurname;
public PlayersBean() {
}
public String getPlayerName() {
return playerName;
}
public void setPlayerName(String playerName) {
this.playerName = playerName;
}
public String getPlayerSurname() {
return playerSurname;
}
public void setPlayerSurname(String playerSurname) {
this.playerSurname = playerSurname;
}
public String addValuesToFlashAction() {
Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
flash.put("playerName", playerName);
flash.put("playerSurname", playerSurname);
return "terms?faces-redirect=true";
}
public void pullValuesFromFlashAction(ComponentSystemEvent e) {
Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
playerName = (String) flash.get("playerName");
playerSurname = (String) flash.get("playerSurname");
}
public String termsAcceptedAction() {
Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
flash.setKeepMessages(true);
pullValuesFromFlashAction(null);
//do something with firstName, lastName
logger.log(Level.INFO, "First name: {0}", playerName);
logger.log(Level.INFO, "Last name: {0}", playerSurname);
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Terms accepted and player registered!"));
return "done?faces-redirect=true";
}
public String termsRejectedAction() {
Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
flash.setKeepMessages(true);
pullValuesFromFlashAction(null);
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Terms rejected! Player not registered!"));
return "index?faces-redirect=true";
}
}
I think there was no need for these 2 lines-
flash.setKeepMessages(true);
pullValuesFromFlashAction(null);
as flash.keep on terms.xhtml page serves the same purpose.
The author seems to be confused here.
Or am I completely wrong & they do definitely serves a purpose over here.
The code chosen by the author is a bit confusing, from my point of view, however, it does what it is intended to do.
flash.setKeepMessages(true);
This line tells JSF you want to keep the FacesMessage in the flash scope. That's a requirement when making a redirection, because more than one subsequent requests are involved and the messages would die from one request to another otherwise. The line is necessary.
pullValuesFromFlashAction(null);
The line does nothing special, just grabs the name and the surname from the flash scope. It's just right to call it from preRenderView to load bean data from the flash scope, but it's redundant to invoke it from the action methods (unless you want to do some logging to see parameters are properly set). Anyway, if you're starting with JSF I encourage you to use JSF 2.2 which has a parameterless replacement for the preRenderView methods, called viewAction.
Last but not least, I would recommend you going through an answer I made some time ago showing an example for dealing with the flash scope, you might find it interesting.
See also:
JSF Keep Messages docs
How to show faces message in the redirected page
In my composite component, I iterate a list<list<javaDetailClass>>. I get all my <h:commandButon> attribute's values through value expression like #{iterator.value}. But the problem comes with attribute action, where action accepts only method expression. whereas I can assign only value expression there, resulting in MethodNotFoundException
<cc:interface>
<cc:attribute name="formElements" />
</cc:interface>
<cc:implementation>
<c:forEach items="#{cc.attrs.formElements}" var="element">
<c:forEach items="#{element}" var="iterator">
<h:commandButton id="#{iterator.id}"
value="#{iterator.value}"
action="#{iterator.action}">
</h:commandButton>
</c:forEach>
</c:forEach>
</cc:implementation>
Can anyone help me in fixing this?
Thanks in advance.
UPDATE
this will be the detail class in my situation,
package com.stackoverflow.test;
public class TestData {
/*Properties based on the implementation of your composite.
Change type where it is needed*/
private String id;
private String value;
private String attributeName;
private String action;
public TestData() {
}
/*Getters and setters omitted*/
}
Bean.java simply holds an ArrayList of ArrayList. The constructor simply created five TestData objects and assigns some default value to its attributes.
package com.stackoverflow.test;
import java.util.ArrayList;
import javax.faces.bean.*;
#ManagedBean
#RequestScoped
public class Bean {
private ArrayList<ArrayList<TestData>> list = new ArrayList<ArrayList<TestData>>();
public Bean() {
ArrayList<TestData> testDataList = new ArrayList<TestData>();
TestData data;
for(int i = 0; i < 5; i++) {
data = new TestData();
data.setId("ID" + i);
data.setValue("VALUE" + i);
data.setAttributeName("ATTRIBUTE" + i);
/**this sets the action attribute of TestData with a API from some other managed bean**/
data.setAction("someOtherManagedbean.someactionAPI");
testDataList.add(data);
}
list.add(testDataList);
}
public ArrayList<ArrayList<TestData>> getList() {
return list;
}
public void setList(ArrayList<ArrayList<TestData>> list) {
this.list = list;
}
}
index.html simply calls the composite by assinging the value of "#{bean.list} to the name attribute
I'm assuming that your TestData.java has the following method public String getAction() (since I'm seeing a setAction(String)) and not
public String action(). Therefore, the reason why you are getting a MethodNotFoundException is because you are supplying the wrong method name to the action attribute. In your case it should be iterator.getAction and not iterator.action. You only supply the abbreviated names when an attribute is expecting a value expression. The interface below has been modifed.
<cc:interface>
<cc:attribute name="formElements" />
</cc:interface>
<cc:implementation>
<c:forEach items="#{cc.attrs.formElements}" var="element">
<c:forEach items="#{element}" var="iterator">
<h:commandButton id="#{iterator.id}"
value="#{iterator.value}"
action="#{iterator.getAction}">
</h:commandButton>
</c:forEach>
</c:forEach>
</cc:implementation>