Need help in sharing the portlet session data in liferay - 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

Related

How to add portlet with redirect to special jsp (edit) in Liferay

I have a portlet in liferay that shows list of items and allow to add/edit (add/save/list of items done by service builder).
Now I need separate liferay page with only add new functionality - can this be done with one portlet or should I copy it to separate portlet?
What I think I need:
way to open portlet with redirection to edit form (edit.jsp)
way to redirect to other liferay page with param (itemId) that would open that page on details.jsp and not standard view.jsp.
====
EDIT:
Now I do have links like that:
details:
<liferay-portlet:renderURL varImpl="rowURL">
<portlet:param name="backURL" value="<%= portletURLString %>" />
<portlet:param name="mvcPath" value="/html/details.jsp" />
<portlet:param name="itemId" value="<%= String.valueOf(item.getId()) %>" />
</liferay-portlet:renderURL>
add:
<liferay-portlet:renderURL varImpl="addURL">
<portlet:param name="mvcPath" value="/html/edit.jsp" />
</liferay-portlet:renderURL>
But they only work in the same portlet/page.
In liferay I have two public pages: "search/details" and "add".
On the "add" page this portlet should render edit.jsp (second url).
Then after an action I should redirect authorized user to "search/details" page with id of the newly created item and show its details.
I can create two portlets but I'm sure there is better and more liferayish solution to this problem.
You could set the default view with portlet preferences / custom configuration. Your portlet, P, can have a configuration parameter for the "type" of portlet A should be (in your case you have two types, "view" and "detail"). Based on this parameter, you can handle the render / action logic accordingly.
That way, with two layouts, L1 and L2, you can put an instance of P on L1 and set its type to "view". You can then put another instance of P on L2.
In P's components (ex. render command) you can check the type (view or detail) and you have control here over the render / action logic as per your use cases (the jsp you want to use, etc.)
For more information on configuration in liferay 7 see:
https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-0/transitioning-from-portlet-preferences-to-the-configuration-api
https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-0/making-your-applications-configurable
if you have a static layout of your site and you know what portlet will be placed where you can use the plid (page layout ID) parameter of the liferay-renderurl tag. That allows you to not only address portlets but also pages. The plid is usually loaded from some configuration.
Another trick how to reuse the existing code is to reuse the actual form and action classes and create only new portlet definitions. This expects that you use Liferay MVC + action command pattern.
your problem is a bit high level, but the solutions are the following techniques:
You can define a friendly URL for your portlet which will transfer the parameters directly in your portlet.
In your portlet you can react on the parameters an display whatever jsp you want.
If you defined the friendly url from 2. you can use it within a link easily:
Edit
If you can provide a bit of example code we can go more into detail.
No hard-n-fast rule to create separate portlets for view / add /
update actions. That totally depends on you.
You can achieve this using single (same) portlet on multiple pages, which default to listing view. Just set target="_blank" on the anchor(s) of the listing view for rowURL and addURL actions to open that link on new tab. The rest will be handled by portlet lifecycle to render specific view based on the portlet:param set for the URL.
The other way around can be the plain redirection to page with itemId=abc and action=add/update as queryString. and in doView of your portlet get that parameter from request and based on those parameters, filter inclusion of jsp.

Sharing session attributes?

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>

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) ;

SharePoint - Custom document library with folder structure

I have a custom document library template with content types. This works fine but the only thing that I would like to add is that when a user instantiates a new document library based on that template, that is has a predefined folder structure already in place.
I have tried adding Module tags in my schema.xml but this doesn't seem to work.
I know that it is possible to provision a document library with files and folders with a ListInstance feature but this is not possible in this case. I would like that the predefined folder structure is part of the document library template.
Is this possible?
Thanks
Maarten
If You want to achieve this using Document Library Definition. I don't think that would be achievable. What you can do is take help of list /document library templates.
1 Create a custom Doclibary the way you want.
2. create the desired folder structure. without uploading any documents.
3, Save the doc library as template by going to Doclibray settings ( make sure you store the template along with content stored into it)
Another method (which I must blog on soon) is to fake a list creation event. I add an empty view definition with a custom aspx page to the list template. The custom page simply executes some custom functionality on the list, deletes the initialisation view, then redirects to the normal view. It's a little messy, and it will only work if the list is created through the UI, but it works.
Here is a very quick example. You already have your list template. In the schema.xml file, add a new View to the Views element like so:
<Views>
<!-- Below is a blank view used to kick of initialisation after list creation. -->
<View DisplayName="Initialise" Type="HTML" DefaultView="TRUE" WebPartZoneID="Main" SetupPath="pages\Scratch\init.aspx" Hidden="TRUE" Url="_init.aspx">
<Toolbar Type="Standard" />
<ViewHeader />
<ViewBody />
<ViewFooter />
<ViewEmpty />
<ViewFields />
<ViewData />
<Query />
</View>
<!-- standard views would be here -->
</Views>
You may be able to go without the empty elements in there. That was something I was going to test further before blogging on it. But this will get the job done. The important things are:
This view is the first view and DefaultView is set to TRUE.
The SetupPath is set to a custom page that you will provision with your solution.
For the custom page (init.aspx in my example), I just made a copy of ...\12\TEMPLATE\Pages\viewpage.aspx and changed what the page inherits from. You could do this with inline code, but I used a codebehind assembly. So first line of that file becomes:
<%# Page language="C#" MasterPageFile="~masterurl/default.master" Inherits="SharePointScratch.InitPage,SharePointScratch,Version=1.0.0.0,Culture=neutral,PublicKeyToken=xxxxxxxxxxxxxxxx" %>
And then the codebehind:
using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
namespace SharePointScratch
{
public class InitPage : System.Web.UI.Page
{
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
SPList list = SPContext.Current.List;
list.ParentWeb.AllowUnsafeUpdates = true;
// Create you folder structure here...
// Fix the views by deleting the initialisation view.
SPView view = SPContext.Current.ViewContext.View;
list.Views.Delete(view.ID);
list.Update();
list.ParentWeb.AllowUnsafeUpdates = false;
// Redirect to the new default view.
SPUtility.Redirect(list.DefaultViewUrl, SPRedirectFlags.Default, this.Context);
}
}
}
Basically, we are relying on the SharePoint default behavior to display the default view of a list after creation. A custom view is inserted in the schema with the sole intention of firing off some custom code. The custom code does, well, whatever you want. After this, you clean up by deleting the special view from the template and redirecting back to the view.

ICEFaces + Liferay : how to set value for public-render-parameter

ICEFaces + Liferay : I created two war file firstApp.war and secondApp.war file and deployed on liferay.
I want to implement, when I click submit button on firstApp.war application’s page , firstAppBacking bean should set some value in public-render-parameter so that I can get that value in secondApp.war application something like IPC. Please sugeest me how can i set the valiue in firstAppText.
<portlet-app ....>
<portlet>
<portlet-name>firstApp</portlet-name>
<display-name>First App</display-name>
<portlet-class>com.icesoft.faces.webapp.http.portlet.MainPortlet</portlet-class>
<init-param>
<name>com.icesoft.faces.VIEW</name>
<value>/jsp/firstApp.iface</value>
</init-param>
....
**<supported-public-render-parameter>firstAppText</supported-public-render-parameter>**
</portlet>
<public-render-parameter>
<identifier>firstAppText</identifier>
<qname xmlns:x="http://www.liferay.com/public-render-parameters">x:firstAppText</qname>
</public-render-parameter>
There are several ways to do that. First of all, the basic concepts are well described here.
As you can see, you can share data in different "contexts". One way is to share the data via the session by declaring shared-portlet-session-attribute in portlet.xml, e.g.
<shared-portlet-session-attribute>
<name>someName</name>
<java-class>com.some.class</java-class>
<shared-portlet-session-attribute>
Other ways to share data are:
- PortletSession
- PortletContext
- Page Parameters
- Portlet Events
The different ways are described in this book. I haven't yet tried all of them, therefore I cannot give more details now.

Resources