True difference between pageContext.getSession().setAttribute() and pageContext.setAttribute() - java

I have been going crazy about resetting some validation error on one of my jsp pages. This is a project inherited from people I cannot reach anymore (dead or unavailable). I have a jsp page with lots of custom taglibs where further pages are added as tabs and the parent page has action buttons to open things like forms. There is a validation error and some configuration parameter being set/modified both in the tabs section and the parent page. But the interesting thing is that I can see the heavy use of pageContext.setAttribute(), session.setAttribute() and pageContext.getSession().setAttribute(). If my initial knowledge is right, pageContext is quite heavily used in servlet-based implementations. but how different things would be if I use those following three on my JSp pages to set attributes?
** Example Scenario (my problem): **
I have some attributes set in the parent page, which are also being set/modifed in the tabs page (embedded in the parent page). I want to remove them such that if there is a validation error, I will simply remove what I have in the tabs page i.e. next time the page will simply load those attributes from the parent page. Do I use pageContext.setAttribute() in the tabs page, but use pageContext.getSession().setAttribute() in the parent page?
KR,

Page scope
When we put in our JSP page, scope is available only for the JSP page that put it.
This is the default scope, so is the same to call pageContext.setAttribute("", "", PageContext.PAGE_SCOPE); same as pageContext.setAttribute("", "");
Session scope
session.setAttribute() and pageContext.getSession().setAttribute() both are same.
What you put on your session scope is available across all requests on the same user session.
Is the same to call pageContext.setAttribute("", "", PageContext.SESSION_SCOPE); same as session.setAttribute("", "");

Related

Freemarker - Reload Template

I have a page whereby I am including a freemarker FTL in this way:
<#include "header.ftl">
Now, the page that it is in does not reload as it's a one pager. However, I would like that at a certain point I refresh header.ftl without doing a full page refresh. Is this possible by any chance? I am new to FTL.
You'll need two serverside endpoints, one for the whole page and another for the fragment(s).
You can then use an ajax request to refresh the fragment (eg jquery)

Retaining session variables on page redirect

I have a JSP page from which I'm calling another JSP page using response.sendRedirect(recordUrl2). I have some session variables from the first JSP page which get lost after the redirect. Is there anything that can be done in the web.xml configuration xml file to preserve the session variables?
I added the following in the xml, but the variables weren't maintained:
<session-descriptor>
<persistent-store-type>memory</persistent-store-type>
<sharing-enabled>true</sharing-enabled>
</session-descriptor>
I also tried response.encodeRedirectURL(recordUrl2) instead, but sessions variables weren't maintained.
Are you by any chance redirecting to a JSP hosted in a different JavaEE container or within a different WAR/deployment than the one doing the redirect? That's the only reason, short of you having code somewhere that clears the session, that the second JSP would not be able to access the session.

Liferay Page redirection

I have developed a theme in liferay 6.1. I have a page named "localhost:8080/home" but now i want that on clicking this link of the page, it should be redirected to localhost:8080
Any suggestions are welcomed.
Thanks in Advance.
I think you are confused a little bit, so just some things you should know:
You can't (normally and without hacks) have a page named "localhost:8080". Every Page (or 'Layout' in Liferay) has a short name, that takes it's part of the url. This is often called "friendly url" but it's often confused with the "friendly url feature", which is a way to shorten your url request data.
So you're always going to have urls like 'localhost:8080/something'. The same holds for the 'home' page
You can partially shorten the Url by using 'virtual host'. It removes the part of the url before your page's name (like removing the web/guest or user/username ) suffix
You can use the 'friendly url' feature to shorten the part of the url that goes after the page's name, and contains request information like lifecycle state info or custom request parameters

Liferay alert user when portlet not present

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.

JSF, How to set a property in a different page/backing bean and then navigate to that page?

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.

Categories