I have a JSF page that loads a User and allows me to assign Roles to that particular User. The Backing Bean, AssignRolesBean is #RequestScoped, and I would like for it to remain so. However, here's my problem...
When the form submits, it calls AssignRolesBean.execute(). This then returns the path to the confirmation page. On this confirmation page, I want to show what new roles will be assigned and which role will be removed. However, I'm having trouble getting the User loaded on the confirmation page.
On the initial AssignRoles page, the userId is set using a GET parameter. It is then added as an h:inputHidden element on the page. It does get submitted. But, again, on the next page, the userId is not set (which loads the User). Is there any way I can keep the RequestScope and not have to store the userId in the SessionMap? I've been told that using hidden inputs will allow you to take data across pages. But, I'm having trouble with that.
if you develop jsf2 app, you can use flash scope to pass the parameters.
For more information about flash scope you can look at Learning JSF2: Using Flash scope
or you can put the parameters into session map
code snippet to get sessionMap:
FacesContext.getCurrentInstance().getExternalContext().getSessionMap()
Add the following to your view to execute an action upon a GET request:
<f:metadata>
<f:event type="preRenderView" listener="#{bean.init}" />
</f:metadata>
with
public void init() {
// Request parameters which are set by h:inputHidden, #ManagedProperty
// or f:viewParam are available here.
// You can just do e.g:
this.user = userService.find(userId);
}
Related
My application is in struts2.
I have requirement that I am storing my application details in session. I cannot remove those attributes from session. After I log-in I have to choose an object to work on. Now I open a new tab and choose another object for working. Due to which my first object values are over written. Hence if in my first tab I do some work wrong information is updated for that action.
This is how I am planning to solve the issue.
I am trying to set a value in setter method in interceptor class but I cannot access that value in my index.jsp.
This interceptor is called on all the actions and index.jsp is also included in every jsp.
I will maintain a hashtable which will store the userid and a random string of 40 characters. This id will be unique and I will update the userid after comparing the value present in jsp to value stored against the value stored in hastable.
If I find that value matches then I will generate another value and store in jsp and hastable. If value does not matches I will destroy the session.
Kindly advice how can I proceed or is there any other work around to achieve the same.
code
Interceptor class
String strFrom = (String)aContext.get(ServletActionContext.ACTION_NAME);
HttpServletRequest httpReq = (HttpServletRequest)aContext.get(ServletActionContext.HTTP_REQUEST);
HttpSession session = httpReq.getSession();
String sessionValue = (String)httpReq.getSession().getAttribute("sessionValue");
String test = httpReq.getParameter("sessionValue");
if(strFrom.equals("ValidateUser")){
// Do nothing
}else if(sessionValue == null && strFrom.equals("HomePage")){
session.setAttribute("sessionValue", getRandomString(20));
}else if (sessionValue.equals(session.getAttribute("sessionValue"))){
session.setAttribute("sessionValue", getRandomString(20));
}else{
httpReq.setAttribute("message","Session Expired. Please Login Again");
return "loginAgain";
}
index.jsp
<body>
<s:hidden id="hidBidType" value="%{#session.tenderBidType}"/>
<s:property value="%{#session.sessionValue}"/>
<s:hidden name="sessionValue" id="sessionValue" value="%{#session.sessionValue}"/>
</body>
login.jsp
<form name="loginPage" method="post">
<s:hidden name="sessionValue" id="sessionValue" value="1"/>
</form>
For your randomly generated value of 40 characters, why not use timestamp?
Well, I don't see much advantages of your aproach (but I could be wrong, of course). You still can register a SessionListener and check if the user has session, cant't you? So, do you realy need to do all this kind of stuff is up to you, but I wouldn't do it that way - Interceptor for all pages, store value in the page, check if is the same... Just register one SessionListener and put your user ID or some otrher user's unique value in session, compare and destroy session (or whatelse you need).
Hope this helps.
EDITED
I'm working on a web application with a similar requirements. What we do (and I'm sure is not the best choice) is after logging open new window without navigation bar and close the loggin window. Then we capture all the events on the window and disable many features like ctrl+tab, right click etc. In this application the user is not allowed to open more than one window. I repeat - this is probably not the best choice. Just an idea.
I'm a bit confused about how MVC actually works.
So far this is the type of thing I have:
Static jsp page has a form that posts to the controller servlet.
Controller uses a database access object to grab the appropriate information from a database and stores it into a java bean.
Set that java bean as a request attribute, forward to some other jsp page for display.
What I'm confused about is what to do when the first jsp page I'm accessing isn't static and I need to retrieve a java bean for display without having some form to post to the controller to retrieve it.
It seems like if I call the database access object to generate the java bean I need from within my jsp page it'll be going against what MVC is.
So my question is how should this be handled? How should I retrieve the java bean I need in this case while sticking to MVC principles?
Thanks!
EDIT: I'll add some code to make it clearer:
At the moment I've got a page called owner.jsp which is supposed to display a list of hotels. Within that page I'm grabbing the list of hotels like this:
<%
HotelDAO hotelDAO = new HotelDAO();
List<HotelBean> hotels = hotelDAO.getHotels();
pageContext.setAttribute("hotels", hotels);
%>
Then using EL to display each hotel using a forEach loop.
This isn't going through a controller at all. How would I adapt this to work with the MVC model?
It doesn't seem logical to me to have do a check if the "hotels" bean is set and forward to a controller page that then sets the "hotels" bean and forwards back to the owner.jsp page.
How does MVC make sure the user always goes through the controller in cases like this? The other pages I've written previously were all static, and only when you submitted some form did it go to the controller, set some beans and forward to some page for display.
Suppose portlet X is deployed to Liferay and has a friendly URL mapped. Suppose a user enters the Liferay Portal via a the mapped URL but the portlet is not present in the portal - it's deployed but not added to the page.
My problem is that when the user uses the mapped URL nothing happens - the portal gives no visual feedback, that the target portlet is not present.
How can I change that? I need some kind of an alert / notice to the user...
-- edit --
I need not use a second portlet to check the presence of yet another portlet.
Kindest regards,
AFAIK, there is no natual way to make that happen. A portlet need not always be installed on a page. So, the behaviour is quite normal.
One rather hacky solution I could think of:
Get hold of the ThemeDisplay object in a JSP using <liferay-theme:defineObjects /> which would expose the implicit object themeDisplay in the JSP scope.
Get hold of the type settings string using:
String typeSettings = themeDisplay.getLayout().getTypeSettings();
Type settings will have values like the below:
layout-template-id=foobar_2column
sitemap-include=1
column-1=foo_WAR_barportlet,abc_WAR_barportlet,56_INSTANCE_K4Vv,
column-2=baz_WAR_xyzportlet,
sitemap-changefreq=daily
So if you have a non-instanceable portlet with ID foo inside WAR
file bar, the portlet's unique ID on the layout will be
foo_WAR_barportlet.
Once you know the portlet ID that you're expecting to be present,
it's just a matter of string contains check.
<% if(!typeSettings.contains("foo_WAR_barportlet")) { %>
<h3 style="color: red">Alert! Portlet foo_WAR_barportlet not installed.</h3>
<% } %>
You can do the above steps even inside a theme, but you'll have to do it in Velocity instead of Java then. Hope that helps.
EDIT
You can add this line inside your portal_normal.vm
#if(!$layout.getTypeSettings().contains("foo_WAR_barportlet"))
<h3 style="color: red">Alert! Portlet foo_WAR_barportlet not installed.</h3>
#end
Yes you can achieve that using Inter-portlet communication, for notifying the user whether the portlet is added to the page or not. you need to create another portlet(lets call it ListenerPortlet) which by default sits on the page.
you can add the Listener portlet to the theme, so that it is by default added to every page.
Now, when you add your portlet to your page, your portlet should trigger a client-side javascript event and notify your Listener portlet that your portlet is added to your page.
From your portlet call,
Liferay.trigger(eventName, data)
and bind your Listener portlet to the event
Liferay.bind(eventName, function, [scope]) //make the scope as page
This way your Listener portlet will know if your portlet is added to the page or not. and you can display a message to the user if the portlet is not added.
For further reference check the IPC
and more specifically client-side Inter portlet communicaton
It would be better if we try this,
ThemeDisplay themeDisplay = request.getAttribute(WebKeys.THEME_DISPLAY);
Layout layout = LayoutLocalServiceUtil.getLayout(themeDisplay.getLayout().getPlid());
LayoutTypePortlet layoutTypePortlet = (LayoutTypePortlet)layout.getLayoutType();
List allPortletIds = layoutTypePortlet.getPortletIds();
If the list is empty then the page doesnt contain any portlets.
Gettings the LayoutTypePortlet ensures that page the user has been redirected to is layout type portlet.
i'm doing a JSF2 project.
1 . i have a form with some checkbox. Look the following code
<ui:repeat>
<h:selectManyCheckbox value="#{wagent.selectedPra}">...
</h:selectManyCheckbox>
</ui:repeat>
So i use selectManyCheckbox inside ui:repeat and i want that the value of the different selectManyCheckbox point to the same value.
But when the form is submit i didn't have all the selected boxs.
How i can do that ?
2 . I have a form with some inputs. On my action i want to merge some pdf files, stay on the same page and that a pop-up appear to offer to download the merged files.
3 . Does all the managed beans with request scope are created for each request or just if i used them in the xhtml page?
4 . I have a commandlink to logout. On my action i use session.invalidate() and return "login". So i go back to the login, but when validating the login, my session managed bean doesn't seem to be created. Error is something like yourSessionBean is null. What's wrong ?
1: So i use selectManyCheckbox inside ui:repeat and i want that the value of the different selectManyCheckbox point to the same value. But when the form is submit i didn't have all the selected boxs. How i can do that ?
Let them point to a different value instead. With the given example the bean value will be overridden everytime until end of the loop. As an example, use a List<List<Pra>> in a bean (or whatever Pra means in your question):
<ui:repeat value="#{wagent.allSelectedPra}" var="selectedPra">
<h:selectManyCheckbox value="#{selectedPra}">
...
</h:selectManyCheckbox>
</ui:repeat>
2: I have a form with some inputs. On my action i want to merge some pdf files, stay on the same page and that a pop-up appear to offer to download the merged files.
At least two things needs to be done:
facesContext.getExternalContext().addResponseHeader("Content-Disposition", "attachment;filename=name.pdf"); // Force "Save As" dialogue.
facesContext.responseComplete(); // Prevent JSF from taking response in hands.
3: Does all the managed beans with request scope are created for each request or just if i used them in the xhtml page?
They are created for every HTTP request. The scope which you described only applies on view scope (if I understand you right).
4: I have a commandlink to logout. On my action i use session.invalidate() and return "login". So i go back to the login, but when validating the login, my session managed bean doesn't seem to be created. Error is something like yourSessionBean is null. What's wrong ?
You are probably accessing the session scoped managed bean the wrong way. You need to either inject it as #ManagedProperty or to grab it by Application#evaluateExpressionGet().
I am using JSF 2.0 and attempting to pass values between different pages in my App.
The setup is as follows:
I have a page called userSelect that has a backing bean userSelectBacking. On this page I display a list of users that can be selected and submit using an h:commandbutton, when the page is submit the navigation goes to a userEdit page.
I have a page called userEdit, that has a backing bean userEditBacking which displays the information for a user
and allows that user to be edited.
I would like to pass the user selected from the userSelect page into the userEdit page.
I am currently using f:setPropertyActionListener to set the user in my userEdit backing from the userSelect page, however when I navigate to the userEdit page, it loses the information I set.
is there a way that I can pass the values between the two pages/backing beans?
thanks
I am currently using f:setPropertyActionListener to set the user in my userEdit backing from the userSelect page
It should work.
however when I navigate to the userEdit page, it loses the information I set.
This will happen if the data loading logic is wrong, or you fire a redirect afterwards while the bean is request scoped.
To fix the data loading logic, just ensure that in case of a request scoped bean the same datamodel is preserved in the subsequent request. Usually you use the bean's constructor or lazy loading in the getter for this. If that is not an option, then you need to put the bean in a bit broader scope, e.g. #ViewScope or #SessionScope.
To fix the redirect issue, either just don't fire a redirect (i.e. remove <redirect/> from navigation case, or don't call ExternalContext#redirect()), or put bean in a broader scope.