Using session to send params to a Liferay Portlet - java

I need to make a Servlet which will manage some information and, after that, will go to a Liferay 6.2 Portlet. Both in the same server.
I need the Servlet to send a parameter, but I don't want to send it GET, but POST method. So, I try to put it in the session to retrieve it from the Portlet.
At the Servlet, I have:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
request.getSession().setAttribute("param1", "TEST 1");
url = "http://myServer/";
response.sendRedirect(response.encodeRedirectURL(url));
} catch (Exception e) {
e.printStackTrace();
}
}
And at the Portlet I manage the information at render method, as I want to get param1 before I render the page:
public void render (RenderRequest renderRequest, RenderResponse renderResponse)
throws PortletException, IOException {
super.render(renderRequest, renderResponse);
//Try to retrieve from getOriginalServletRequest
HttpServletRequest servletReq = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(renderRequest));
String param1 = servletReq.getSession().getAttribute("param1").toString();
//Try to retrieve from getHttpServletRequest
HttpServletRequest servletReq_ = PortalUtil.getHttpServletRequest(renderRequest);
String param1_ = servletReq_.getSession().getAttribute("param1").toString();
}
As you can see, I tried to retrieve from getHttpServletRequest and from getOriginalServletRequest, but I always get the param1 null.
Any suggestion?
Thank you in advance!
Update question:
I'm being called from a third part, and I'm receiving a GET parameter I want to evaluate.
After that, and not rendering a page in the middle, I want to redirect to one or another Portlet, depending of that evaluation.
I need to send some personal information to those Portlets, so I want to send some parameters in POST method.
A Servlet doesn't fit as doesn't share session with Portlets.
I've tried to implement a landing Portlet, but the redirect can only be done in action phase, so I'd need to render a (empty) page before the redirect, don't like that part. Render phase doesn't allow redirect (even getting PortalUtil.getHttpServletResponse(), doesn't work)
Any suggestion? Thanks!

A servlet and a portlet will not share the same session. The portlet is living within the portal server, e.g. Liferay. The servlet is typically in its own web application, thus completely separated by design.
If you need to communicate between the two, here are two possible solutions/workarounds:
reimplement your servlet as a portlet, potentially utilizing the resource-phase of a portlet
use a request parameter instead of a session attribute
Edit after all of the comments:
It seems best to take a step back and look at the underlying problem - what is the problem that you're actually trying to solve? The content of your question is how you're trying to solve it, and obviously there are challenges. It looks like the problem needs a different solution in the first place.
My answer describes why your solution can't work, but that obviously doesn't help solving the underlying problem.

Related

How to pass values from JSP to Servlet without performing event?

I have crated a portlet, Where I am doing my business logic in servlet. But I am getting the liferay login user details in the jsp page. So Now I need to pass the user details while hitting the servlet. This is my JSP code,
<%
String fullname= user.getFullName();
out.println("Full name is: "+fullname+ "...");
long id = themeDisplay.getLayout().getGroupId();
out.println("Site ID is: "+id+ "...");
long userId = themeDisplay.getUserId();
out.println("User ID is: "+userId+ "...");
%>
I need to access the above details in the servlet. How can I do that? Each login user has some different credentials, So all the values should update in and need to access in the servlet. what is the best way to access these values without performing any event. I am hitting the servlet from another web service. I need to access in Get OR Post method,
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
//I need to access those login user information here..
}
This will be really hard to do ("really hard" as in "almost impossible"): When you're in a servlet, all the portal's code of identifying the actual user won't run.
In fact, when you look at the HttpServletRequest for a portlet: This will be directed towards the portal and only later be forwarded to the portlet, with the properly constructed context (e.g. logged in user).
When you look at the servlet, this will be directed to your servlet. Your servlet typically lives in a totally different application context. Thus - by servlet specification - it will be totally separated from the portal environment.
Everything that you find to mitigate this limitation will be somewhat of a hack. Some people use cookies or request parameters. But they all are introducing more or less problems. Especially when you speak of webservices that access your servlet, you can't go with cookies.
In the interest of a well maintainable implementation, my recommendation is to change your architecture. Unfortunately you don't give enough context to recommend what to change your architecture to.

Using only one servlet

I'am making a web page with a login system and backoffice page. The problem is, both use the method "doPost" (the login use to autenticate and the backoffice use to insert data in db). How can I use only one servlet for both? I'am asking this because both use doPost, so I made two servlet's.
In case you want to use a single servlet, you should implement Front Controller Pattern. For this, you will parse the request URL and decide which action should be performed:
public class MySingleServlet extends Servlet {
#Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
String url = request.getPathInfo();
//returns the action to handle
Action action = ActionFactory.getAction(url);
action.process(request, response);
}
}
This involves an Action interface/abstract class and an ActionFactory that will parse the URL and return the right implementation to handle the actions to do.
Another more naive and harder-to-maintain implementation is by sending an action parameter. This may be a problem because an attacker may use a proxy and change the action parameter before sending the request to the URL. If this is a recognized valid action, and the attacker knows what to send, then you're in trouble.
Note that there are MVC frameworks that already implement Front Controller Pattern like Spring MVC and JSF, so there's no need to reinvent the wheel unless it is for learning purposes (otherwise, you should use a library that already implements this).
You could add an extra parameter (e.g. action) in your post method
retrieved from a hidden form field, if you are using forms, or
added with a simple &action='value' to your request if using xml http request
and based on its value perform the appropriate actions:
if (action.equals("auth"))
{
// authenticate
}
else if (action.equals("backoffice"))
{
// db update
}
You can get pathInfo from request object based on that you route the request.

Java Servlet POST action not receiving parameters from request

Yesterday I tried using Tomcat and Servlets for the first time (I come from IIS/C#/MVC).
I'm also using AngularJS and Guice.
I've made a Servlet that has a single method:
#Singleton
#SuppressWarnings("serial")
public class CommandServlet extends HttpServlet {
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println(req.getParameterMap());
}
}
I've made a service in Angular that looks like the following:
app.factory('console', [ '$http', function($http) {
var console = {};
console.execute = function(gameId, command) {
$http.post("Command/", {
gameId : gameId,
command : command
}).success(function(data, status, headers, config) {
}).error(function(data, status, headers, config) {
});
};
return console;
} ]);
In my controller I inject the service and expose it to the view via an "execute" function on the scope:
app.controller('PlayController', function($scope, console) {
$scope.consoleIn = "";
$scope.gameId = 1;
$scope.execute = function(command) {
$scope.consoleOut = console.execute($scope.gameId, command);
};
});
And in my view I have a button which calls the function and passes in text from an input element:
<input ng-model="consoleIn" type="text">
<button class="btn" type="button" ng-click="execute(consoleIn)">Go!</button>
For some reason the console on my Tomcat server is printing an empty Map ({}) without the parameters being passed with the POST request. When I look at the network tab in Chrome's Console thingy and see that the parameters are being sent ({"gameId":1,"command":"a"}), so my question is 1) Am I doing the right thing to get the values out of the POST request (getParameterMap() ?) and 2) if I am doing the right thing, what am I doing wrong so that the request my browser makes isn't getting to my servlet properly?
EDIT:
I ended up using Jersey as my container (I think it's called) instead of Java's default Servlets. I did this after seeing Jersey popping up with Guice often on Google, thinking there would be sufficient documentation to get the two of them working together. There are several examples and I sort of drew on several, especially this one.
The snag I ran into getting it to work was this, but now everything's good to go.
Overall I'd say that if you like Guice for your DI and want to make a Java website, Jersey is good. It appears to be for a different more specialized functionality of RESTful services than regular servlets - but that's what I needed, anyway. From my un-scientific Googling observations besides Tomcat there's Grizzly and Jetty that are popular as well - you may want to look into them if you're having trouble with Tomcat.
I hope this edit saves someone the hours I spent yesterday and today getting it to work.
What does it actually print? Some of the Tomcat Map implementations don't print their contents in their toString() method. Try another way of seeing what's in it. You'll find its all there.

Alternative of URL parameter for deciding which method to call

Right now based on the site name in the URL parameter, we decide the appropriate actions to take(method calls etc) in the Java (Standard Jsp/Servlet web applications). For example, the request would be something like www.oursite.com?site=Ohio
Wondering what would be the alternative of doing this without having to provide URL parameter.
You could use POST instead of GET.
GET appends request parameters to the end of the URL.
POST sends encoded data using a form.
http://www.tutorialspoint.com/jsp/jsp_form_processing.htm
Why not just code it into the path?
www.oursite.com/Ohio
If you're just using straight servlet api, you can just do something of this nature:
String path = request.getPathInfo();
String site = path.split("/")[0];
That being said, most web frameworks have some support for helping with this.
For example, in spring mvc:
#RequestMapping(value="/{site}/blah/blah", method=RequestMethod.GET)
public ModelAndView blahBlah(HttpServletRequest req,
HttpServletResponse resp,
#PathVariable("site") String site) {
// do stuff here
}
Of course you could do this at the controller level too if all your methods need that sort of mapping:
#Controller
#RequestMapping(value="/{site}")
public class MyController {
#RequestMapping(value="/blah/blah", method=RequestMethod.GET)
public ModelAndView blahBlah(HttpServletRequest req,
HttpServletResponse resp,
#PathVariable("site") String site) {
// do stuff here
}
}
I believe this is cleaner than a query param, though it still shows up in your URL. There's other, more complex methods like using apache's reverse proxying and virtual host capabilities to switch based on site names. You could do something at login, and store the site in session. It all depends on your requirements.
You could use an alternate URL, like ohio.oursite.com. This process could be automated by having your server respond to *.oursite.com. I would probably set up a filter that looked at what the subdomain was and compared that with a predefined list of allowed sites. If it didn't exist, you could redirect back to the main (www) site. If it did, you could set a request attribute that you could use in a similar way that you currently use the request parameter now.

How to call servlet from java

I've a third-party servlet inside a JAR that I cannot change. I've extended that servlet and been using it normally as a servlet should be used, the client side makes an HTTP request that invokes my servlet.
But now the client wants an automatic service, that is, I will need to do some requests to that third party servlet from the same webapp where the servlet is.
I looked at the the third party servlet code but I didn't found a place to bypass the servlet because the HttpServletRequest and HttpServletResponse objects are passed from method to method... Basically it seems that I would need to re-implement all the third party code.
Solutions I found but do not satisfy me:
Call servlet from URL with HttpURLConnection: My common sense says that calling the third party servlet from a url is not the best way to
go, besides the overhead added, I don't want to expose the third party
servlet. Calling my servlet from a url also brings problems with
sessions and other things.
Call the doGet directly: This seems to be out of the question because there is no implementation for the HttpServletRequest and
HttpServletResponse.
Use jMock or something like that: Didn't explore this solution yet, but it seams wrong to use a test-driven library in the real
environment.
Anyone has an idea how to interact with that third party servlet?
EDIT:
Since my English is not very good and I'm finding difficult to explain myself here goes a schematic to try to explain better
EDIT2: After a meeting the third party maker they offer to isolate the methods I need to avoid calling the servlet. If you don't have the same luck I did check out both gigadot and BalusC answers.
If I understand your question correctly, you have implemented or have a third party servlet that generate the report for you.
Now what you want to do is to periodically generate the report and store in session so that when user want to get the report they can retrieve it using another servlet.
If this is the case then you want the task to be running periodically on your server. You will need some sort of task scheduler to run on your server and what the task does is just make a http request to your servlet (this can be http GET or POST).
Calling my servlet from a url also brings problems with sessions and other things.
If that's the sole problem, then just use the CookieManager to maintain the cookies (and thus also the session) in subsequent URLConnection calls.
// First set the default cookie manager.
CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
// All the following subsequent URLConnections will use the same cookie manager.
URLConnection connection = new URL(url).openConnection();
// ...
connection = new URL(url).openConnection();
// ...
connection = new URL(url).openConnection();
// ...
See also:
Using java.net.URLConnection to fire and handle HTTP requests
You could try to separate out your servlet logic into several phases. The entry point that takes the request/result, the action that processes parameters sent and generates the output.
public void doGet(HttpServletRequest req, HttpServletResponse rsp){
relay(rsp,act(req.getParameter("a"));
}
public static String act(String a){
return "You provided: " + a;
}
public static void relay(HttpServletResponse rsp, String content){
rsp.setResponseCode(200);
rsp.getOutputStream().write(content.getBytes());
}
This lets you call act(whatever) to do what you want, and then do what you want with the response. If returning a string is not enough, you could make any return type you want, probably something that could contain a list of headers, response code, and content template.

Categories