My question is:
I have two different Portlets (nothing but war file) deployed in a portal server called first and second; whenever user clicks firstportlet (first) I use the following code to set session object!:
Code in first portlet:
String application="Welcome";
PortletRequest portletRequest = (PortletRequest) webAppAccess
.getHttpServletRequest()
.getAttribute(Constants.PORTLET_REQUEST);
portletRequest.getPortletSession(true).setAttribute("application",
sessionValue,
PortletSession.APPLICATION_SCOPE);
log.Info("SESSION hole value:---" + portletRequest.getPortletSession(false));
Whenever user clicks secondportlet(second) I am using follwing code to retrieve the session which was set in firstportlet.
Code in second portlet:
PortletRequest portletRequest = (PortletRequest) webAppAccess
.getHttpServletRequest()
.getAttribute(Constants.PORTLET_REQUEST);
log.Info("SESSION hole value:---"+ portletRequest.getPortletSession(false));
log.Info("SESSION VALUE in second Portlet:----"
+ portletRequest.getPortletSession(false).getAttribute("application",
PortletSession.APPLICATION_SCOPE));
Error:
But in second portlet I am always getting null value, please any solution?
The portletSession.APPLICATION_SCOPE mechanism makes it possible for portlets to share session data if they are within the same portlet application. If you have two portlets that are not in the same war they are not in the same portlet application and thus, the session data is not shared either.
To solve this you need to put the two portlets into the same portlet application (same war, same portlet.xml but still two different portlets).
DanielBarbarian's answer is correct. To share the global session, the portlets need to be in the same war. But there are other ways to share data between portlets on the same page, but not necessarily in the same war. (I'm assuming your portal container supports the JSR286 standard)
Use interportlet communication. This can notify other portlets of events. It is a simple publish/subscribe system that is not difficult to set up.
Use global render parameters.
There are examples on the web for both options.
Related
I'm trying to use Liferay shared session attributes.
I would like to to use the same attribute on two different portlets in different WAR file-s on different URL-s using the following code based on:
Liferay 7 not able to set the global session attribute
Value I want to save: A single string
Setting in portlet 1:
String sharedKey = "LIFERAY_SHARED_" + key;
HttpSession session = PortalSessionThreadLocal.getHttpSession();
session.setAttribute(sharedKey, bean);
Portlet 1 is able to retain, reset and use attribute fine.
Reading in portlet 2:
key = "LIFERAY_SHARED_" + key;
HttpSession session = PortalSessionThreadLocal.getHttpSession();
Object bean = session.getAttribute(key);
This value is always null.
Both portlets are Spring MVC portlets.
Both portlets have:
<instanceable>false</instanceable>
<private-session-attributes>false</private-session-attributes>
<requires-namespaced-parameters>false</requires-namespaced-parameters>
In their liferay portlet XML-s.
Also both portlets extend org.springframework.web.portlet.DispatcherPortlet.
Liferay version:
Liferay DXP Digital Enterprise 7.0.10 GA1
Any help would be greatly appreciated.
Let me know if anyone needs any clarification.
Thanks a lot,
PeTer
Kyle Stiemann has recently written a nice article on using sessions in portlets. TL;DR: You're using the HttpSession with an attribute prefixed "LIFERAY_SHARED_", but you should use the portlet session: That's what Liferay manages, the HttpSession might be "simulated", e.g. it might not be the object that tomcat manages.
To quote one of the options from his article:
Use Liferay session.shared.attributes prefixes (such as
LIFERAY_SHARED_) to share one or more session attributes between
portlets in different applications/WARs.
Liferay exposes certain session attributes to all portlets based on
certain prefix values. Although these prefixes are configurable via
portal-ext.properties, I recommend using one of the default prefixes:
LIFERAY_SHARED_.
For example:
// Portlet A
portletRequest.getPortletSession(true)
.setAttribute("LIFERAY_SHARED_" + CONSTANTS.ATTR_NAME, "value",
PortletSession.APPLICATION_SCOPE);
// Portlet B (in a different WAR)
String attrValue = portletRequest.getPortletSession(true)
.getAttribute("LIFERAY_SHARED_" + CONSTANTS.ATTR_NAME,
PortletSession.APPLICATION_SCOPE);
Pros:
Only exposes the necessary attribute(s) to other portlets (instead of exposing the entire session).
Cons:
Exposes session attribute(s) to all portlets.
Tight coupling without indicating which other portlets might be utilizing this data.
Non-standard method of sharing session data.
Note the strong recommendation to use only primitive types as session attributes. Eliminate the need for custom serialization and classloading problems. Also note that the variant of getPortletSession with the additional scope parameter is required here.
But, as much as this technically provides an answer to your question, you also want to read "Session Storage is Evil".
TL;DR: Don't use the technique above. Rather eliminate the use of sessions.
What I want is different different session bean per tab/ window. I know session bean works but I want to create new sessionbean for new tab. Below is reason why I want new session bean.
Suppose on page1, I have list of users. On clicking user, I get details of user in page2.
Now suppose I have two tab. In both pages I have page1.xhtml.
On tab1, I clicked on User A. I see details of User A on page2.xhtml
Now I come on tab2.
On tab2, I clicked on User B. I see details of User B on page2.xhtml
Problem is here now. Now I come back to tab1 and refresh the page2.xhtml, I see User B details which is incorrect because earlier I was seeing User A details.
Hence what I want is new sessionbean per new tab/ window.
Is there any way to create new sessionbean per tab/ window? In primefaces or icefaces maybe?
I thought ViewScope was solution, but that was not. Referring BalusC article.
#ViewScoped: a bean in this scope lives as long as you're interacting with the same JSF view in the browser window/tab. It get created upon a HTTP request and get destroyed once you postback to a different view.
With SessionBean, I meant Java/ JSF managed session managed beans and not browser session (history).
If you are using CDI Conversation scope could help.
From the Java EE docs: ConversationScoped
These tutorials might help.
CDI Conversations Part 1
CDI Conversations Part 2
Hope this helps !!!
#ViewScoped is the solution to this problem, indeed. The problem looks to be that you're setting the UserX data (id, detail or something else) into session when navigating from page1.xhtml and then loading this session data in page2.xhtml. So, if this is your current situation, not even CDI #ConversationScoped will help you (since it uses cid query string param).
In order to solve this, you should make a GET request of your page2.xhtml and send the userId (or another useful parameter) to recover the details of your UserX.
More info:
How to choose the right bean scope?
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
Note that you can encrypt the parameter (let's say, the ID) to add some security to your parameters. Please refer to the second proposed link in order to achieve this.
In Tomcat Manager on the Page "Sessions Administration", there is a column Guessed User name. How can i set this column from within my Wicket Session?
Note: I have successfully overridden AuthenticatedWebSession.toString() and this value is shown on the sessin details page.
I have tried to set AuthenticatedWebSession.userName as recommended here.
Please mind that Wicket session is a different beast than actual servlet session. Creating a "userName" property in wicket session will not work.
You need to access the raw HttpServletRequest from wicket to set the value properly: this is how you do it.
Add this code to your WebPages:
HttpServletRequest request = getWebRequestCycle().getWebRequest().getHttpServletRequest();
request.getSession().setAttribute("userName", userName);
You can create any Java bean and add it to session like this,
session.setAttribute("user", user);
Tomcat will find the bean and whatever prints in toString will show up.
see image here
How can I pass the session attribute value to another application which is in same web server. The reason why I should know this is because we have a project which is divide by a module. Each module will redirect to another that pass value using session. That session will be used to identify which user is accessing that module.
Suppose I have a LogIn Module that separate from my other module.
Here my sample code:
Sample Url http://localhost:8080/Login
authorization.jsp : This page will call after user input a userId and then submit
page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"
HttpSession sessionid = request.getSession();
String userId = request.getParameter("userId");
sessionid.setAttribute("userId", userId);
System.out.println("SESSION IS :" + sessionid.getAttribute("userId"));
response.sendRedirect("http://localhost:8080/OtherModule");
Sample Url http://localhost:8080/OtherModule
In my Home servlet I will check if the session have a userId
protected void doGet(HttpServletRequest request, HttpServletResponse response){
HttpSession session = request.getSession();
if(session.getAttribute("userId") != null){
System.out.println("SESSION ID # GET: " + session.getAttribute("userId"));
} else {
System.out.println("No Session for userId");
}
}
//I also tried this with post but still I can't get the session
I hope this information may give you idea what's wrong with my code. Please help me with this. Thanks
You will have to configure your web-server accordingly. Tomcat for example provides a valve for that. See here: http://tomcat.apache.org/tomcat-6.0-doc/config/host.html#Single_Sign_On
Note: The localhost-URL you posted, only works on your computer (hence the name "local").
It would be much easier though to just add all of your modules into one Web-Application or to use one of the countless Java Web Application Frameworks.
If your shared data is related to authentication/login, then SSO (single sign on) is the way to go as #Ridcully says - it's managed for you by the application server, and your apps shouldn't need to worry about it.
If the problem is more general - how to share data between webapps - then a very clean approach is to use JNDI. Tomcat (and any other servlet/J2EE server) provide a lookup space that can be common to all webapps, this mechanism is most often used to define database (or other resource) configuration outside apps in a way that can be shared.
So, you could write a class to contain the data, have it in JNDI, and have each application look it up (using explicit JNDI calls or resource injection). If you need more info on this let me know.
Single sign on indeed solves the shared-logged-in-user issue.
It does however not allow for sharing the same session among all deployed webapplications. If that is after all your actual intent, then you need to set emptySessionPath attribute of the <Connector> element in /conf/server.xml to true.
<Connector ... emptySessionPath="true">
See also Tomcat 6.0 HTTP Connector documentation.
I would like to know if there is some way to share a variable or an object between two or more Servlets, I mean some "standard" way. I suppose that this is not a good practice but is a easier way to build a prototype.
I don't know if it depends on the technologies used, but I'll use Tomcat 5.5
I want to share a Vector of objects of a simple class (just public attributes, strings, ints, etc). My intention is to have a static data like in a DB, obviously it will be lost when the Tomcat is stopped. (it's just for Testing)
I think what you're looking for here is request, session or application data.
In a servlet you can add an object as an attribute to the request object, session object or servlet context object:
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
String shared = "shared";
request.setAttribute("sharedId", shared); // add to request
request.getSession().setAttribute("sharedId", shared); // add to session
this.getServletConfig().getServletContext().setAttribute("sharedId", shared); // add to application context
request.getRequestDispatcher("/URLofOtherServlet").forward(request, response);
}
If you put it in the request object it will be available to the servlet that is forwarded to until the request is finished:
request.getAttribute("sharedId");
If you put it in the session it will be available to all the servlets going forward but the value will be tied to the user:
request.getSession().getAttribute("sharedId");
Until the session expires based on inactivity from the user.
Is reset by you:
request.getSession().invalidate();
Or one servlet removes it from scope:
request.getSession().removeAttribute("sharedId");
If you put it in the servlet context it will be available while the application is running:
this.getServletConfig().getServletContext().getAttribute("sharedId");
Until you remove it:
this.getServletConfig().getServletContext().removeAttribute("sharedId");
Put it in one of the 3 different scopes.
request - lasts life of request
session - lasts life of user's session
application - lasts until applciation is shut down
You can access all of these scopes via the HttpServletRequest variable that is passed in to the methods that extend from the HttpServlet class
Depends on the scope of the intended use of the data.
If the data is only used on a per-user basis, like user login info, page hit count, etc. use the session object
(httpServletRequest.getSession().get/setAttribute(String [,Object]))
If it is the same data across multiple users (total web page hits, worker threads, etc) use the ServletContext attributes. servlet.getServletCongfig().getServletContext().get/setAttribute(String [,Object])). This will only work within the same war file/web applicaiton. Note that this data is not persisted across restarts either.
Another option, share data betwheen contexts...
share-data-between-servlets-on-tomcat
<Context path="/myApp1" docBase="myApp1" crossContext="true"/>
<Context path="/myApp2" docBase="myApp2" crossContext="true"/>
On myApp1:
ServletContext sc = getServletContext();
sc.setAttribute("attribute", "value");
On myApp2:
ServletContext sc = getServletContext("/myApp1");
String anwser = (String)sc.getAttribute("attribute");
Couldn't you just put the object in the HttpSession and then refer to it by its attribute name in each of the servlets?
e.g:
getSession().setAttribute("thing", object);
...then in another servlet:
Object obj = getSession.getAttribute("thing");
Here's how I do this with Jetty.
https://stackoverflow.com/a/46968645/1287091
Uses the server context, where a singleton is written to during startup of an embedded Jetty server and shared among all webapps for the life of the server. Can also be used to share objects/data between webapps assuming there is only one writer to the context - otherwise you need to be mindful of concurrency.