JSF passing parameter to session bean in url - jsf

I'm a JSF beginner and I have an easy JSF question but I couldn't solve the logic here.
I open new mv.xhtml page via commandbutton like this:
<p:commandButton value="#{grBean.protocolName(item)}"
onclick="window.open('/SearchMap/faces/mv.xhtml?url=#{item}')">
</p:commandButton>
And I have mvBean which is a session scope. I get the url parameter with a function which is called in postconstructed init method. The method is like:
Map <String, String>tempMap= FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
if(tempMap.get("url") !=null)
url=tempMap.get("url");
The problem is here, as mvBean is session scoped, the init method is called only once so I can't get a new url parameter naturally.
I want to use mvBean as a sessionScoped coz I want to keep all the passing urls in an ArrayList.
So, how can I get the url parameter when I use session bean? Or do you have any suggestion or solution?
Thanks for help.

You don't have to do it in init(), here is a quick solution. Put this on your mv.xtml page, somewhere inside <h:form>
<p:remoteCommand name="onload" action="#{mvBean.checkUrl()}" autoRun="true" />
and move your logic from init() to public void checkUrl().

Related

PropertyNotFoundException EL Expressions not resolving?

I have code similar to this in my facelet...
<c:foreach items=#{myBean.listOfA} var="a">
<c:foreach items=#{myBean.listOfB} var="b">
<c:set var="aName" value="#{a.name}">
<c:set var="component" value="#{b.associatedComponent(aName)}">//this wont resolve
//do stuff with component
</c:foreach>
</c:foreach>
myBean is a session scoped bean. Both A and B classes are maintained in lists inside the bean but are just model objects not managed beans.
That being said the method b.associatedComponent(a) I am assuming should resolve to b.getAssociatedComponent(A a) which I have checked many times. All methods are public. What can I do to make the method accessible to EL?
No matter what I try I get a PropertyNotFoundException on associatedComponent.
P.S. I also tried moving the method to the bean like this...
<c:set var="component" value="#{myBean.associatedComponent(b, aName)}">
This also does not work and throws the same PropertyNotFoundException.
This will not work, as the c:set tag expects a ValueExpression for the value attribute.
This means that you are only able to use properties - not methods.
If you use arguments like here #{b.associatedComponent(aName)} then what you have is a method call, not a property call. This however is a valid MethodExpression and can be used in places like the action attribute of a command link.
See the API documentation and spec for more details on this.

JSF pass Object to another page

I'm trying to pass an object to another site. So i have my Gallery.xhtml where I set an object as current and redirect to another page:
<h:form>
<a4j:commandButton value="Edit Skin"
action="#{helloBean.setCurrentSkin(skin)}"
onclick="window.location.href = 'resources/html/Editor.xhtml';" />
</h:form>
But when the getter on the second page is called, the current object is null again.
Is the bean generated for each page? How could I achieve this?
My Problem was that I declared my bean as #ViewScoped, but the proper Tag is #SessionScoped. This makes sure that the Bean holds its values for the whole session and not only one view.

CommandButton open new tab with FlashScope parameters

How can I open new tab when user clicks p:commandButton? I also want to pass some parameters to new page using FlashScope. Here's the code:
<h:form>
<p:commandButton value="open new tab" action="#{myBean.newTab}"/>
</h:form>
public String newTab() {
Faces.setFlashAttribute("foo", bar);
return "otherView";
}
On the otherView page I use f:event type="preRenderView" to read Flash parameters.
Two notes:
I need to use FlashScope, not URL parameters.
If possible, I don't want to change newTab() and preRenderView() methods.
Thanks for help
Use target="_blank" on the form to tell the browser that the synchronous response of the form should be presented in a new (blank) tab/window. You only need to turn off ajax behaviour of the <p:commandButton> in order to make it a synchronous request.
<h:form target="_blank">
<p:commandButton value="open new tab" action="#{myBean.newTab}" ajax="false" />
</h:form>
No changes are necessary in the backing beans, it'll just work as you intented. I would only recommend to use POST-Redirect-GET pattern in the action method.
return "otherView?faces-redirect=true";
Otherwise the new tab would show the URL of the originating page and a F5 would re-invoke the POST. Also, this way the flash scope is also really used as it is been designed for (if you didn't redirect, just storing in request scope was been sufficient).
Update: as per the comments, the view scoped bean in the initial tab/window get killed this way. by returning a String navigation case outcome. That's right, if you'd like to keep the view scoped bean alive, replace the navigation case by a Faces#redirect() call (assuming that it's indeed OmniFaces which you're using there for Faces#setFlashAttribute()). You only need to set Flash#setRedirect() to true beforehand to instruct the flash scope that a redirect will occur.
public void newTab() throws IOException {
Faces.setFlashAttribute("foo", bar);
Faces.getFlash().setRedirect(true);
Faces.redirect("otherView.xhtml");
}

Reset JSF Backing Bean(View or Session Scope)

I want to reset by JSF backing bean when some method is invoked. Assume that there is a command button, someone press it and after succesfull transaction, my View or Session scope JSF bean should be reseted. Is there a way to do that?
Thank
I found the solution for View scope.
public static void removeViewScopedBean(String beanName)
{
FacesContext.getCurrentInstance().getViewRoot().getViewMap().remove(beanName);
}
A view scoped bean will be recreated when you return non-null or non-void from the action method, even if it would go back to the same view. So, just return a String from the action method, even if it's just an empty string:
public String submit() {
// ...
return "";
}
To make it complete, you could consider sending a redirect by appending the ?faces-redirect=true query string to the returned outcome.
public String submit() {
// ...
return "viewId?faces-redirect=true";
}
A session scoped bean is in first place the wrong scope for whatever you're currently trying to achieve. The bean in question should have been be a view scoped one. Ignoring that, you could just recreate the model in the action method, or very maybe invalidate the session altogether (which would only also destroy all other view and session scoped beans, not sure if that is what you're after though).
just clear all views:
FacesContext.getCurrentInstance().getViewRoot().getViewMap().clear();
and remember to implements Serializable in all views
You could also refresh the page from javascript, so the ViewScoped Bean will be reseted, for example in a primefaces commandButton:
<p:commandButton value="Button" action="#{bean.someAction()}" oncomplete="location.reload()"/>
I solve the problem with code like this:
((HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest()).getSession().removeAttribute("bean name");
By this way I enter to session scoped bean and reset it without the data that was there before

Set bean property from JSF page

I need to do very simple thing - pass current URL from JSF (2.0) page to the managed bean. This is needed to get URL of the login form which will redirect user back to the current page after login. (I use GAE and the bean is the wrapping around its user service, if it does matter). Any obvious way I tried doesn't work
<c:set /> - doesn't work (w/o any error or warning message)
getter which takes current URL as a parameter - doesn't work.
So many questions and many recipes, but all are complex and not elegant. Why? May be I (as other who asking) missed a key design principle? I'll appreciate any answer - simple and straightforward recipe or explanation why not to do so.
It's available by #{request.requestURL} (or if you only want the domain-relative path, use #{request.requestURI}). Use f:param to pass it and #ManagedProperty to handle it.
<h:commandButton action="#{bean.submit}" value="submit">
<f:param name="url" value="#{request.requestURL}" />
</h:commandButton>
with
#ManagedProperty("#{param.url}")
private String url;
Noted should be that f:param inside a h:commandButton doesn't work in JSF 1.x. You'd like to use h:commandLink instead.
Update as per the comments: I understood that you wanted to "pass current URL to the managed bean". But you actually want to "access current URL in managed bean".
In that case, either replace #{param.url} by #{request.requestURL}:
#ManagedProperty("#{request.requestURL}")
private String url;
Or obtain the raw HttpServletRequest instance from under the JSF hoods by ExternalContext#getRequest():
HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
String requestURL = request.getRequestURL();

Resources