Sharing session attributes? - liferay

I have two portlets in a liferay portal: an MVC portlet and a Vaadin portlet.
The first one sets a session attribute in this way:
long serviceId = 1;
PortletSession portSession = renderRequest.getPortletSession();
portSession.setAttribute("serviceId", serviceId, PortletSession.APPLICATION_SCOPE);
The second one reads it:
PortletRequest portletRequest = VaadinPortletService.getCurrentPortletRequest();
long serviceId = (long) portletRequest.getPortletSession().getAttribute("serviceId", PortletSession.APPLICATION_SCOPE)
The issue is that the session attribute read by the second portlet is null but not 1.
What am I doing wrong?

Please add <private-session-attributes>false</private-session-attributes> in liferay-portlet.xml for both portlets.
The detail of this tag is this as per DTD:
Element : private-session-attributes Set the
private-session-attributes value to true if the portlet does not
share session attributes with the portal. The default value is true.
The property "session.shared.attributes" in portal.properties
specifies which session attributes are shared even when the
private-session-attributes value is true.
Data Type : #PCDATA

Add
session.shared.attributes = Shared
in your liferay portal-ext.properties file.
All Variables which starts with the keyword 'Shared' will be application scoped.
If this is done, you no need to set
<private-session-attributes>false</private-session-attributes>

Related

How can I use a session bean and deal with many tabs with different parameters?

in a jsf 2.2 application, there is page called test.xhtml that take a paramater called ‘id’ , for example test.xhtml?id=200 . The page is backed by a CDI Session bean named ‘TestBean’. The page has this code to load data:
<f:metadata>
<f:viewAction action="#{testBean.redirectNoParameters}"></f:viewAction>
</f:metadata>
Now based on the id, the application load a set of fields in the session bean with the right values.
public String redirectNoParameters() {
//Code…
//Load fields
test = testDao.find(id);
//Code…
}
Till now is all good.
Except that when the user opens a new tab in the browser and specify a DIFFERENT id, for example test.xhtml?id=300 . the Session bean override the current values of the previous parameter 200, with the new id 300 values.
So my question is how can I use a session bean and deal with many tabs with different parameters? How can I have a session bean for each tab? If this is not possible than what solution do people use for this kind of scenario ? Thanks.
A #SessionScope Bean is living as long as the users Session is active. (hence the name) - It is shared between Requests and Views, which is the "Problem" you are facing.
A #RequestScope Bean will be recreated upon every request (No Matter if first-Access or Ajax-Request), which is possible to use for your usecase (reloading data based on resubmitted IDs), but can be optimized. (This would be a traditional Request/Response-Model as known from PHP - JSF offers a better option)
Your case perfectly matches the #ViewScope. One Bean per View, living as long as the View is present. This would allow you to open an (almost) infinite amount of different Views (hence, the name), each having it's individual set of BackingBeans as long as they are #ViewScope. Multiple "Views" of the same page are possible, each View will maintain the reference to it's dedicated View-Scoped-Beans. (In your example: 2 opened text.xhtml pages and therefore 2 active instances of TestBean, each having its own ID)
The behaviour of your application is correct. Please read the section about Scopes of The Java EE 6 Tutorial.
Your application has created a session scoped bean for the current user and it will be used by all request for such user. Any variable created in such bean will be shared by any tab the user opens.
If you expect the user to interact on multiple tabs with different values for the same variable, consider using a request scoped bean.

display a success message on different portlet

I have form on a porlet, after submission of that form, page is redirecting to another portlet for that i am using actionResponse.sendRedirect("/abc/bcd/newWebPage")
and i am landing on to different page. One that page the same potlet is added with different screen, Now i want to display a success message on next page.
for that i am using portlet session and passing parameter to jsp.
PortletSession session = actionRequest.getPortletSession();
session.setAttribute("SUCCESSA", "Successfully",PortletSession.APPLICATION_SCOPE);
But its not working.
Any help how to achieve that?
When you say One that page the same potlet is added with different screen, I understand that you have another instance of the same portlet in different page. By the way, you haven't explained what is not working for you. I assume you are wondering how to read in the JSP page. It's pretty straight forward:
In Controller:
PortletUtils.setSessionAttribute(request, "SUCCESSA", "Successfully", PortletSession.APPLICATION_SCOPE);
In JSP:
pageContext.setAttribute("succcessa", PortletUtils.getSessionAttribute(renderRequest, "SUCCESSA", PortletSession.APPLICATION_SCOPE));
The PortletUtils does the same as setting the attribute using the PortletRequest object but its preferrable.
To remove the session attribute:
PortletUtils.setSessionAttribute(request, "SUCCESSA", null, PortletSession.APPLICATION_SCOPE);
The implementation of PortletUtils is that it removes the session attribute if value is null, if a session existed at all.

Need help in sharing the portlet session data in liferay

Actually I am trying to share the data between 2 portlets in a 2 different plugin projects
Below are the steps I followed to share the data :
Step1: Create liferay plugin project named as Senderproj and created one portlet under Senderport then write below code in doView method
PortletSession session=req.getPortletSession();
String s="naresh";
session.setAttribute("gates",s,PortletSession.APPLICATION_SCOPE);
step2: Create liferay plugin project named as Receiverproj and created one portlet named as Receiverport then write below code in doView method
PortletSession ps = req.getPortletSession();
String tabName = (String)ps.getAttribute("gates",PortletSession.APPLICATION_SCOPE);
System.out.println("this is from doView of ipc receiver portlet"+tabName);
Step 3: I added the property in liferay-portlet.xml like below
<private-session-attributes>false</private-session-attributes>
When I drop two portlet in a portal page I got session value null in Receiverport.
can any one help out
Fist check that <private-session-attributes>false</...> is correctly set in both portles (sender and receiver).
Then, set and get session attributes using APPLICATION_SCOPE:
renderRequest.getPortletSession().setAttribute(
"name", "some value", PortletSession.APPLICATION_SCOPE
);
renderRequest.getPortletSession().getAttribute(
"name", PortletSession.APPLICATION_SCOPE
);
So far it seems that's what you're already doing.
If they are on the same page, we must ensure that they are loaded in the correct order. In Liferay this can be achieved by setting the render-weight. (In a real case it is better that they do not depend on the order in which they are loaded.)
<!-- Sender -->
<portlet>
<portlet-name>test-a</portlet-name>
<icon>/icon.png</icon>
<instanceable>true</instanceable>
<private-session-attributes>false</private-session-attributes>
<render-weight>3</render-weight>
...
</portlet>
<!-- Receiver -->
<portlet>
<portlet-name>test-b</portlet-name>
<instanceable>true</instanceable>
<icon>/icon.png</icon>
<private-session-attributes>false</private-session-attributes>
<render-weight>2</render-weight>
...
</portlet>
Besides, this link may be helpful:
Liferay Session Sharing Demystified

How to create a RenderURL during action phase in a portlet?

In the method processAction(ActionRequest request, ActionResponse response), I insert a record into database and get the ID and then
I want to redirect to the view page of this record. So I need to create a RenderURL with a parameter value for that ID.
ActionResponse doesn't provide method to create a renderURL. Some codes in Liferay do similar things like:
create renderURL before accessing the actionURL
pass the renderURL as a parameter in the actionURL
However, at that time, I don't know the value of ID.
Other codes also use new PortletURLImpl() directly. My portlet cannot see that class.
Other codes also use new PortletURLImpl() directly. My portlet cannot see that class.
Because this class is in portal-impl.jar and also it is not recommended to use classes from this jar. Starting from Liferay 6.1, you won't be able to build your portlet from plugins-sdk if you classes point to portal-impl.jar.
Now to answer your question:
Any jsp is rendered by the render method or doView method (if using liferay's MVCPortlet) and this method would be called as part of the normal life-cycle of portlets.
Here are the steps you would need to take:
set a render parameter (using response.setRenderParameter() method) in your `processAction' method at the last which would be available in your render method, as follows:
actionResponse.setRenderParameter("myID", 1201);
Just for info: After using setRenderParameter you cannot use sendRedirect method
fetch this "myID" in your render method as you fetch any other request parameter:
//assuming your ID is a long
long myUserName = ParamUtil.getLong(renderRequest, "myID");
or
String strMyID = renderRequest.getParameter("myID");
long myID = Long.parseLong(strMyID);
After this, just use
include(renderPage, renderRequest, renderResponse);
were renderPage is nothing but a string containing the path to your jsp within docroot like /html/yourportlet/view.jsp
Just as an afterthought:
If you are using a Liferay IDE, then you can try creating a simple portlet project with MVCPortlet and then look at the generated portlet.xml's <init-param>
So basically you need to pass information from action-phase to render-phase, the development guide is a good place for explaining this in detail.
That's it.
Hope this helps.
Let me know if you have any confusion regarding this.
In action phase do the following:
ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute (WebKeys.THEME_DISPLAY);
PortletURL url = PortletURLFactoryUtil.create(request, this.getPortletName(), themeDisplay.getPlid(), PortletRequest.RENDER_PHASE);
For example, if you want to redirect to the login page and back, you can do the following:
response.sendRedirect("/c/portal/login?redirect=" + HttpUtil.encodeURL(url.toString()));
Definitely you can add or copy the parameters as required.
Instead of creating the renderURL you can include the view page include(viewTemplate,actionRequest,actionResponse). Or if you want to sent any parameter any want's to get it in doView then use actionResponse.setParameter(name,value) method
I create a RenderURL with a place holder as parameter value, like this:
<portlet:renderURL var="redirect">
<portlet:param name="ID" value="__ID__" />
</portlet:renderURL>`
In processAction:
String redirect = redirectParam.replace("__ID__", "123213");
actionResponse.sendRedirect(redirect) ;

How to get Portlet Id using the portlet name in Liferay?

I have a requirement of getting resource permission using portlet name.
I will have the name of the portlet not the Id.
Resource Permission name for a portlet is that portlet's Id. I checked the Portlet table, it has only the Id and other info. Where will be the other attributes of portlet saved?.
Is there a way I can get portlet's Id by using portlet's name. I have a workaroud to get all portlets and compare, but if I can directly get portlet's Id using portlet's name it will be helpful.
Its urgent, if anyone knows pls reply back, it will be of great help.
Thanks in Advance
If you look closely as to how the Portlet Id is generated based on the Portlet Name, you would get the answer.
It is a constant pattern which is followed, so you can construct the Portlet Id like liferay does it if you have the name. Liferay also constructs the ID with the help of the portlet name.
Pattern of portlet-id: <portletname in xml>_WAR_<servlet context name i.e. the war file without any special characters such as the hyphen>
For example:
If your portlet name is MyWork defined in portlet.xml and the generated file in the webapps folder (if you are using tomcat) is MyWork-portlet then the resultant Id will be MyWork_WAR_MyWorkportlet.
Now if you have liferay source code, you can look at PortletLocalServiceImpl's private _readPortletXML method.
Edit:
If you want to find the portlets on a particular page (given the friendly-url of the page) then you may find this answer helpful.
You can try this:
System.out.println("ID : " + themeDisplay.getPortletDisplay().getId());
System.out.println("InstanceID: " + themeDisplay.getPortletDisplay().getInstanceId());
System.out.println("Portlet Name: " + themeDisplay.getPortletDisplay().getPortletName());
Don't forget:
<% ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);
themeDisplay.getUser().getScreenName(); %>

Resources