iceface 2.0: How to retain value in icepush? - jsf

I would like to integrate ice push into my web application.
I have a page(placeinfo.jsf) shows information of a place and ui:include weather.jsf for weather information of the place.
Users access to the page at http://xxx.com/xxx/placeinfo.jsf?place=california.
Simple example of code,
placeinfo.jsf
1) ice:output value="placeInfoBean.population"
2) ice:output value="placeInfoBean.language"
3) ui:include src="./weather.xhtml"
weather.jsf
1) ice:output value="weatherBean.humidity"
2) ice:output value="weatherBean.visibility"
PlaceInfoBean.java
#ManagedBean(name="placeInfoBean")
#RequestScoped
public class PlaceInfoBean
{
String population;
String language;
#PostConstruct
public void init()
{
HttpServletRequest request= (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
String place = request.getParameter("place");
setPopulation(PlaceInfoDao.getPopulation(place));
setLanguage(PlaceInfoDao.getlanguage(place));
}
}
WeatherBean.java
#ManagedBean(name="weatherBean")
#RequestScoped
public class WeatherBean
{
String humidity;
String visibility;
#PostConstruct
public void init()
{
HttpServletRequest request= (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
String place = request.getParameter("place");
setHumidity(WeatherDao.getHumidity(place));
setVisibility(WeatherDao.getVisibility(place));
}
public WeatherBean()
{
PushRenderer.addCurrentSession("weather");
}
}
I have another page to update the weather, and the method calls
PushRenderer.render("weather");
WeatherBean actually did a refresh, postconstrust method run again, but found there is no request param of "place" which suppose to be "california", and the page doesn't work properly then.
Question:
1) May I know besides session, how can the page remembers the value before PushRenderer did something?
2) Is it a proper way to get the request param for WeatherBean?
or request param should be passed by ui:param from placeInfo.jsf?
How to get the value of ui:param in WeatherBean?
Thank you!

Have you tried to set the managed beans as #SessionScoped? Or #ApplicationScoped? Did it work?

Related

Create a new FlowScoped bean when other one was not finished

I am working whith JSF (Primeface) and j2ee on weblogic.
So, i have two different flows in my application:
Flow configuration:
public class RequestFlow implements Serializable {
#Produces
#FlowDefinition
public Flow defineFlow(#FlowBuilderParameter FlowBuilder flowBuilder) {
String flowId = "requestFlow";
flowBuilder.id("", flowId);
flowBuilder.viewNode(flowId, "/inside/customer/request/flow/requestFlow.xhtml").markAsStartNode();
flowBuilder.viewNode("requestFlowCart", "/inside/customer/request/flow/requestFlowCart.xhtml");
flowBuilder.viewNode("requestFlowCheckout", "/inside/customer/request/flow/requestFlowCheckout.xhtml");
flowBuilder.returnNode("finishRequest").fromOutcome("/inside/customer/request/requests.xhtml");
return flowBuilder.getFlow();
}
}
CDI's flow bean:
#Named
#FlowScoped("requestFlow")
public class RequestFlowBean implements Serializable {
//some logic
}
Second configuration:
public class OrderFlow implements Serializable {
#Produces
#FlowDefinition
public Flow defineFlow(#FlowBuilderParameter FlowBuilder flowBuilder) {
String flowId = "orderFlow";
flowBuilder.id("", flowId);
flowBuilder.viewNode(flowId, "/inside/customer/order/flow/orderFlow.xhtml").markAsStartNode();
flowBuilder.viewNode("orderFlowSelectRequests", "/inside/customer/order/flow/orderFlowSelectRequests.xhtml");
flowBuilder.viewNode("orderFlowReviewRequests", "/inside/customer/order/flow/orderFlowReviewRequests.xhtml");
flowBuilder.viewNode("orderFlowCheckoutOrder", "/inside/customer/order/flow/orderFlowCheckoutOrder.xhtml");
flowBuilder.returnNode("finishOrder").fromOutcome("/inside/customer/order/orders.xhtml");
return flowBuilder.getFlow();
}
}
CDI's flow bean:
#Named
#FlowScoped("orderFlow")
public class OrderFlowBean implements Serializable {
//some logic
}
My Case:
User opens page where by clicking h:button starts the "requestFlow" (doesn't finish it!)
Using menu navigates to another page, by clicking h:button tries to start the "orderFlow".
Problem:
"OrderFlow" wasn't start without any error in console! And the first flow still in memory, but according documentation it have to be destroyed.
So, I want to be able create a new FlowScoped bean when other one was not finished.
Any suggestions?
So, exactly in 2 month i found the answer.
The trick is how you start your flow. If you want to run new JSF flow, while didn't finish other one, you have to remove from JSF context previous instances of any flow. In order to do it, you have add method in controller:
public String initFlow() {
FacesContext context = FacesContext.getCurrentInstance();
FlowHandler handler = context.getApplication().getFlowHandler();
ExternalContext extContext = context.getExternalContext();
String sessionKey = extContext.getClientWindow().getId() + "_flowStack";
Map<String, Object> sessionMap = extContext.getSessionMap();
if (sessionMap.containsKey(sessionKey)) {
sessionMap.remove(sessionKey);
}
handler.transition(context, null, handler.getFlow(context, "", getFlowName()), null, "");
return getFlowName();
}
And start flow page in the next way:
<p:commandButton value="Start Flow"
action="#{controller.initFlow}"/>
</p:panelGrid>

How to evaluate which page to show in PostConstruct?

Imagine this situation:
I have a SessionScoped bean (named TheSessionBean) that is a ManagedProperty of another bean (named AnotherBean).
#ManagedBean
#ViewScoped
public class AnotherBean implements Serializable {
#PostConstruct
public void init() {
//Evaluate here!
}
#ManagedProperty(value = "#{theSessionBean}")
private TheSessionBean theSessionBean;
//Getter and Setter...
}
I need to evaluate the value of the ManagedProperty (theSessionBean) in order to know if a page can be showed without the user interaction and before the page is shown.
As I understand this must be evaluated in the PostConstruct method (so I can get the value of the Session of the ManagedProperty).
TheSessionBean has only a String property named permission.
So first of all I need to know if:
theSessionBean.getPermission() == null in order to redirect to a page named one
theSessionBean.getPermission().equals("two") in order to redirect to a page named two
More evaluations...
The problem is that the PostConstruct method must be void and I need to redirect to the corresponding page.
How can I do that?
You can use ExternalContext.redirect in your PostConstruct method.
if (someCondition)) {
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ec.redirect(ec.getRequestContextPath() + "/one");
}
Best practice is to use JSF system events- PreRenderViewEvent PostConstructApplicationEvent PreDestroyApplicationEvent
JSF events

More than one session from the same browser

I need a little direction understanding sessions in JSF (2.2.6). I've tried to find some documentation but am still missing something.
I have a #RequestScoped login bean which saves parameters in the session map for reference by other session scoped backing beans. They get the user info when they go through the PostConstruct method and everything works great.
However the logic fails when more than one window is used or the user doesn't logoff and goes directly back to the login page. JSF treats this as the same session and the #PostConstructs are not invoked.
I am pretty sure I could invalidate the session but that doesn't solve the problem of multiple users from different browser windows.
Any guidance or reference sites would be appreciated.
Thanks in advance!
John
session HAS to be same for every browser window, the only exception is when using anonymous mode: i.e. chrome behave like having two browsers opened at the same time.
another way to have multiple sesssions is to use different server name:
http://localhost:8080/app and http://127.0.0.1:8080/app may not share a single session.
however sessions never overlaps.
your problem, if i understand right, is when a logged user access login page and re-login, preserving his old session, that's why session beans are not PostConstructed again (independently from window used).
a general solution is to forbid access to login page for logged users.
and in general, container will throw an AlreadyAuthenticatedException or similar when user re-login without prior logout.
cut a long story short, just a preliminary example waiting for your code:
#ManagedBean
#SessionScoped
public class UserBean implements Serializable
{
private static final long serialVersionUID = 1L;
private User user;
public boolean isLoggedIn()
{
return user != null;
}
public void login(String username, String password)
{
// maybe you want to check isLoggedIn() and either call logout() or throw an exception
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
request.login(username, password);
user = someDAO.loadFromDatabase(username);
}
public void logout()
{
// maybe you want to check isLoggedIn() and either throw an exception or do nothing
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
request.logout();
user = null;
// suggested for another scenario
// request.getSession().invalidate();
}
// getters and setters
}
and
#ManagedBean
#SessionScoped
public class OperationBean implements Serializable
{
private static final long serialVersionUID = 1L;
#ManagedProperty("#{userBean}")
private UserBean userBean;
public void execute()
{
if(!userBean.isLoggedIn())
{
FacesContext.getCurrentInstance().getExternalContext().redirect("login.jsf");
return;
}
User user = userBean.getUser();
// do something
}
// getters and setters
}
with this combination, instead of using OperationBean's #PostContruct i used #ManagedProperty, so that OperationBean contains an always-up-to-date reference to user, without caring multiple re-logins.

JSF request scope with get parameter

i know there are many similar threads but no like mine:
I have a requestscope bean:
#ManagedBean
#RequestScoped
public class Bean implements Serializable{
private String username = ""; //managed by textbox
private String password = ""; //managed by textbox
private String id ="-";
//Load the Parameter as usual:
#PostConstruct
public void fetchParams(){
System.out.println("FETCH PARAMS");
FacesContext facesContext = FacesContext.getCurrentInstance();
String id = facesContext.getExternalContext().getRequestParameterMap().get("id");
if(id == null || id.length() == 0) return;
setId(id);
}
// getters & setters
public void doSomething(){ //executed when clicked on the sumbit-button on the jsf-site
StaticFunctions.doSomething(this);
}
}
The code does following:
it retrieves the get-parameter "id" and saves it into String id (confirmed by string.out....).
But when the method doSomething() is executed and the previously stored "id" is read and returns "-" (like nothing happened).
why is this so?
Your ManagedBean is #RequestScoped and will be destroyed at the end of the request. When doSomething() is executed the user submitted the form and started a new request.
So you should see "FETCH PARAMS" twice in the console because two Beans are created but for the second request id is null.
You can find a detailed explanation about the four JSF-Scopes here.

Iceface 2.0 commandLink partial submit doesn't work

I have a page which takes in request params for place, then generate information,
for example, http://example.com/xxx/weather.jsf?place=california.
The purpose of doing this is to let user bookmark the link.
In the weather.jsf, there are two outputtext and a commandlink:
Humidity : <ice:outputText value="#{weatherBean.humidity}"/>
Visibility : <ice:outputText value="#{weatherBean.visibility}"/>
<ice:commandLink id="likeButton"
value="Like"
actionListener="#{weatherBean.doLike}" />
In the managedBean:
#ManagedBean(name="weatherBean")
#RequestScoped
public class WeatherBean
{
String humidity;
String visibility;
int numLike;
#PostConstruct
public void init()
{
System.out.println("init called");
HttpServletRequest request= (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
String place = request.getParameter("place");
setHumidity(WeatherDao.getHumidity(place));
setVisibility(WeatherDao.getVisibility(place));
setNumLike(GeneralDao.getNumLike());
}
public void doLike(ActionEvent event)
{
System.out.println("doLike called");
GeneralDao.addNumberLike();
}
}
Alright, the page generated perfectly.
However, when I click the doLike commandLink,
it always triggers the init method first, then call doLike method.
Since the request param is empty, all the other values reset.
Is there any way to prevent a refresh of the page or calling of init method?
I tried partialsubmit or immediate, but no luck.
Your bean is #RequestScoped, so after executing the JSF lifecycle, your bean instance is lost, until the next request comes in, at which point you get a new instance of your bean, and the PostContruct re-executes.
Try changing the scope of your bean to something longer lived, like #ViewScoped.

Resources