I have created a little controller of sorts that depending on the input could send it to a number of pages each with a different backing bean. I do this because one page, which takes a case number, verifies that case number and then passes it on to any number of pages which need a valid case number.
Here is my caseSelector page:
<h:form id="form1">
<h:inputText value="#{caseSelectorBean.caseNumber}"/>
<h:inputHidden value="#{caseSelectorBean.nextPage}"/>
<h:commandButton action="#{caseSelectorBean.gotoNext}" value="submit"/>
</h:form>
my bean correctly verifies the casenumber and fills out the bean for the next page and forwards it to that page.
//CaseSelectorBean
public String gotoNext() {
logger.debug("In the caseChooser, going to xpage");
logger.debug("caseNum=" + caseNumber);
if(!validateCaseNumber(caseNumber)) {
return "caseNotFound";
}
if(nextPage.equals("page1")) {
CaseDAO caseDAO = new CaseDAO();
caseInfo = caseDAO.getCaseInfo(caseNumber);
CaseInfoBean caseInfoBean = new CaseInfoBean();
caseInfoBean.setCaseInfo(caseInfo);
caseInfoBean.setCaseNumber(caseNumber);
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(
"caseInfoBean", caseInfoBean);
}
logger.debug("done with gotoNext(), returning " + nextPage);
return nextPage;
}
problem is when I try to access the bean from the next page, it's empty. I can see via the constructor, it created a new one instead of using the one in the session. How would I make the page use the bean I created for it?
Thanks!
The ManagedProperty with #{param} works only for request scoped beans. Use f:viewParam for broader scopes:
<f:metadata>
<f:viewParam name="caseNumber" value="#{caseSelectorBean.caseNumber}"/>
</f:metadata>
Then you need only a simple property caseNumber with getter and setter in your bean.
Related
This question already has answers here:
Retaining GET request query string parameters on JSF form submit
(2 answers)
Closed 6 years ago.
Whenever I make an ajax call, my URL param expires. The workaround I have done is to pass a param request inside every button like in:
<p:commandLink value="Submit" actionListener="#{mybean.dosomething}">
<f:param name="foo" value="#{mybean.bar}"/>
</p:commandLink>
However, in some scenarios I can't do the above workaround. For example when I'm using primefaces rowEditEvent:
<p:ajax event="rowEditCancel" listener="#{mybean.onCancel}"/>
The param expires when I make this ajax call and results in error before invoking #{mybean.onCance} as I'm reading datatable's data from the param in URL.
So how can I maintain the param value when I make such an ajax call?
PS: mybean is ViewScoped
Problem Extension:
The <o:form> has solved part of the problem, but now I can't send params inside the form for dynamic image streaming inside the table. See the following:
<p:dataTable value="#{mybean.data}" var="var">
<p:column headerText="Thumbnail">
<p:graphicImage value="#{streamer.thumbnail}">
<f:param name="id" value="#{var.id}"/>
</p:graphicImage>
</p:column>
</p:dataTable>
Streamer Bean (RequestScoped):
public StreamedContent getThumbnail() throws IOException {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getRenderResponse()) {
return new DefaultStreamedContent();
}
else {
String string = context.getExternalContext().getRequestParameterMap().get("id");
Long id = Long.parseLong(idString);
MyImage img = (MyImage) service.find(MyImage.class, id);//get resource
StreamedContent sc = new DefaultStreamedContent(img.getInputStream(), "image/jpg", img.getName());
return sc;
}
}
Here string is always null and parameter is not passed resulting in error
Register it as a <f:viewParam>
<f:viewParam name="foo" value="#{mybean.bar}" />
and instead of <h:form>, use OmniFaces <o:form> with includeViewParams="true" (which uses under the covers a custom ViewHandler implementation which automatically collects all view parameters and appends them to the outcome of the getActionURL() method which is used as form action URL):
<o:form includeViewParams="true">
...
</o:form>
This way all view params are included in the form's action URL and will therefore end up as request parameters the usual way without the need to fiddle with <f:param> and being clueless inside <p:ajax> (and <f:ajax>).
I have build a login snippet of code that is on the top of menu bar. If a user is in any of the page by navigating and presses all of sudden the login button, I'll like to see that person authenticated and at the same time stay on the page where he originally comes from. so I used this on the backing bean:
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
then if there is let say mypage.htm?a=2&b=2 get a=2&b=2 with the request.getQueryString()
but getQueryString returns null, how can I can have the original URL entirely from the backing bean?
It returned null because the command button does not submit to an URL which includes the query string. Look in the generated HTML output of <h:form>. You'll see that generated HTML <form action> does not include the query string at all.
You need to pass the current query string yourself as a request parameter in the login link/button.
Grab the current request URI and query string and add it as from parameter in login link/button (note: use a normal link/button, it doesn't need to be a command link/button):
<h:button value="login" outcome="/login">
<f:param name="from" value="#{request.requestURI}#{empty request.queryString ? '' : '?'}#{request.queryString}" />
</h:button>
In login page, set the from parameter as view scoped bean property:
<f:metadata>
<f:viewParam name="from" value="#{login.from}" />
</f:metadata>
In login action method, redirect to it:
public void submit() throws IOException {
User user = userService.find(username, password);
if (user != null) {
// ... Do your login thing.
FacesContext.getCurrentInstance().getExternalContext().redirect(from);
} else {
// ... Do your "unknown login" thing.
}
}
<h:commandButton> sends a POST request to the server, more specifically to the Faces Servlet, and the JSF lifecycle starts. As you may know, you can't access to the query string parameters in a POST request.
In case you want to send a GET request from your form or retrieve the query string parameters when accessing to the page, you must map each expected query parameter using <f:viewParam>
<f:metadata>
<f:viewParam id="a" name="a" value="#{bean.a}" />
<f:viewParam id="b" name="b" value="#{bean.b}" />
</f:metadata>
More info:
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
ViewParam vs #ManagedProperty(value = "#{param.id}")
You can also solve this by changing the <h:form> wrapping the <h:commandButton> to an omnifaces form with includeRequestParams set to true: <o:form includeRequestParams="true">. See BalusC's response to this question.
This question already has answers here:
Retaining GET request query string parameters on JSF form submit
(2 answers)
Closed 6 years ago.
Whenever I make an ajax call, my URL param expires. The workaround I have done is to pass a param request inside every button like in:
<p:commandLink value="Submit" actionListener="#{mybean.dosomething}">
<f:param name="foo" value="#{mybean.bar}"/>
</p:commandLink>
However, in some scenarios I can't do the above workaround. For example when I'm using primefaces rowEditEvent:
<p:ajax event="rowEditCancel" listener="#{mybean.onCancel}"/>
The param expires when I make this ajax call and results in error before invoking #{mybean.onCance} as I'm reading datatable's data from the param in URL.
So how can I maintain the param value when I make such an ajax call?
PS: mybean is ViewScoped
Problem Extension:
The <o:form> has solved part of the problem, but now I can't send params inside the form for dynamic image streaming inside the table. See the following:
<p:dataTable value="#{mybean.data}" var="var">
<p:column headerText="Thumbnail">
<p:graphicImage value="#{streamer.thumbnail}">
<f:param name="id" value="#{var.id}"/>
</p:graphicImage>
</p:column>
</p:dataTable>
Streamer Bean (RequestScoped):
public StreamedContent getThumbnail() throws IOException {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getRenderResponse()) {
return new DefaultStreamedContent();
}
else {
String string = context.getExternalContext().getRequestParameterMap().get("id");
Long id = Long.parseLong(idString);
MyImage img = (MyImage) service.find(MyImage.class, id);//get resource
StreamedContent sc = new DefaultStreamedContent(img.getInputStream(), "image/jpg", img.getName());
return sc;
}
}
Here string is always null and parameter is not passed resulting in error
Register it as a <f:viewParam>
<f:viewParam name="foo" value="#{mybean.bar}" />
and instead of <h:form>, use OmniFaces <o:form> with includeViewParams="true" (which uses under the covers a custom ViewHandler implementation which automatically collects all view parameters and appends them to the outcome of the getActionURL() method which is used as form action URL):
<o:form includeViewParams="true">
...
</o:form>
This way all view params are included in the form's action URL and will therefore end up as request parameters the usual way without the need to fiddle with <f:param> and being clueless inside <p:ajax> (and <f:ajax>).
This question is spawned from the partial answer to JSF2: why does empty test in rendered of panelGroup in composite prevent action from being called?
In the following an Element is an #Entity with a name and id. A view.xhtml JSF page takes the id as a viewParam and uses setID(Long id) of the #ManagedBean #RequestScoped ElementController to trigger loading of the corresponding Element by id from database (that plays no further role in the question) and this found Element is set as the 'current' Element available (for historical reasons by a slightly different name) as Element getSelected().
The view.xhtml page performs a rendered attribute test #{not empty elementController.selected}, and has a h:commandButton with action that performs a faces-redirect, along with the id as query parameter, back to the view.xhtml page.
For some reason I do not fully understand, on form submission the test (and thus getSelected) is invoked in both the apply request phase and the process validations phase, before the viewParam id can be set (and thus before the current/selected Element can be found and set) in the update model values phase.
The greatly abbreviated view.xhtml page is:
<f:view>
<f:metadata>
<f:viewParam name="id" value="#{elementController.id}"/>
</f:metadata>
</f:view>
<h:body>
<h:form>
<h:panelGroup rendered="#{not empty elementController.selected}">
<h:outputText value="#{elementController.selected.name}"/>
</h:panelGroup>
<h:commandButton value="Apply" action="#{elementController.action}" />
</h:form>
</h:body>
(The sense of the form submission is lost above, but it does not matter for the this question.)
ElementController extends RequestController:
public void setId(Long id) {
log_debug("setId","id",id);
if (id != null) {
this.id = id;
T found = (T) getAbstractFacade().find(id);
if (found == null) {
String $error = "No object with id(" + id + ") found for class " + getManagedClass().getSimpleName();
log_error($error);
}
setCurrent(found);
}
}
public T getSelected() {
log_debug("getSelected","current",current);
if (current == null) {
log_warn("getSelected","null current Element");
}
return current;
}
public Object action() {
String $i = "action";
log_debug($i);
if (current==null) {
log_warn($i, "can't generate action outcome for null current element");
return null;
}
return "/view?faces-redirect=true&id="+current.getId();
}
Now on form submission, getSelected() happens to get called twice, and when current==null, once during the apply request values phases and once during the process validations phase, due to the test #{not empty elementController.selected} before the setting of the id (and thus loading of the Element entity) can occur thanks to the viewParam in the view.xhtml.
The question is, why is the rendered=#{not empty elementController.selected} invoked at all during the apply request phase and process validations phase ?
It is not invoked during those phases when I perform an initial GET load of the view.xhtml with id parameter, only during a form submission POST and subsequent redirect and GET.
The reason that the rendered attribute is consulted twice or more after a post back is because JSF traverses the component tree in each phase.
The name 'rendered' is perhaps not the best possible name, as it doesn't just make rendering of the component to which it applies conditional, but actually processing it in general.
It's consulted in the first place for 'apply request values' to see if that component and its children should be processed to have those request values applied to them. It's consulted again in 'process validations', since its value might have changed between phases.
It's not invoked 'during those phases when I perform an initial GET load', because when you perform a GET the component tree isn't traversed in those phases (only the metadata is processed, which is the reason view params are put in a special metadata section).
In order to make the id that you received from the GET request available in the action method after the post back, you'd best use the view scope (#ViewScoped) for your backing bean.
When i tried to send some values with h:commandButton... i recieved null value in the bean...
my xhtml code is:
<p:commandButton action="#{favouriteAction.setFavourite}" value="Add as Favorite" rendered="#{favouriteBean.favouriteButton}">
<f:setPropertyActionListener target="#{favouriteAction.ngoID}" value="#{InsertDataDaoService.ngo_id}"></f:setPropertyActionListener>
</p:commandButton>
In the backing bean i just tried to print the value which i passed with my command button,but it becomes null...
In favouriteAction.java(My backing Bean)
public Integer ngoID;
public Integer getNgoID() {
return ngoID;
}
public void setNgoID(Integer ngoID) {
this.ngoID = ngoID;
}
public String setFavourite(){
System.out.println("Ngo id: "+ngoID);
System.out.println("Ngo id: "+getNgoID);
return "";
}
In console i dint get any exceptions, my o/p is
Ngo id: 0
Ngo id: 0
that is null, and it doesnt get passed..
The <f:setPropertyActionListener> is evaluated during the request of the form submit, not during the request of displaying the form. So if its value #{InsertDataDaoService.ngo_id} is not preserved for that request, then it will fail.
You have basically 2 options:
Ensure that #{InsertDataDaoService.ngo_id} is preserved for the request of the form submit. How exactly do to that depends on the functional requirements which are not clear from the question. But generally, putting the #{InsertDataDaoService} bean in the view scope by #ViewScoped and making sure that you aren't doing any business job in the getter method should be sufficient.
Replace <f:setPropertyActionListener> by <f:param> with #ManagedProperty.
<p:commandButton action="#{favouriteAction.setFavourite}" value="Add as Favorite" rendered="#{favouriteBean.favouriteButton}">
<f:param name="ngoID" value="#{InsertDataDaoService.ngo_id}" />
</p:commandButton>
with
#ManagedProperty("#{param.ngoID}")
private Integer ngoID;
This way the value will be retrieved (and inlined as part of a JavaScript helper function of the commandButton) during the request of displaying the form, not evaluated during the request of submitting the form.
See also:
How can I pass selected row to commandLink inside dataTable?
Have you checked that the value of InsertDataDaoService.ngo_id is not NULL?
Try to replace it with a constant value. Does it work?