I have a portlet developed in Liferay, in which I want to get query parameter value from URL.
I tried this way but get "null" value from Query parameter:
HttpServletRequest httpReq = PortalUtil.getHttpServletRequest(request);
HttpServletRequest httpOrigReq = PortalUtil.getOriginalServletRequest(httpReq);
String myValue = httpOrigReq.getParameter("idProcessOrigin");
Any advice would be greatly appreciated!
The code you mention in your question should work, however, it's ignoring the peculiarities of a portlet environment. Typically, in a portlet, you'd rather "decorate" the names of parameters with <portlet:namespace/> (or whatever the equivalent in your UI library of choice is to this JSP tag). Instead of submitting a parameter "idProcessOrigin", you'd submit "<portlet:namespace/>idProcessOrigin" (of course, with properly replaced namespace, e.g. rather SOME_RANDOM_STUFF_idProcessOrigin)
If you don't want this, you can also declare the property com.liferay.portlet.requires-namespaced-parameters=<boolean> in your portlet-#Component's property list (as carried over from liferay-portlet.xml)
For the standard way of obtaining the parameters from a portlet request, you don't need to go through the HttpServletRequest at all - just use the PortletRequest's getParameter method. The result of this method depends, however, on properly decorated parameter names (or the deactivated option mentioned above). Note: When you call request.getParameter("idProcessOrigin"), you don't need the decoration any more, provided that request is a PortletRequest, not an HttpServletRequest.
Related
I have a JSP that's accessed from an url like
http://localhost/products.jsp
(thus without a query string), while that page includes other JSP's with:
<jsp:include page="product.jsp">
<jsp:param value="1" name="recordNumber"/>
</jsp:include>
Inside product.jsp there's a call to a Java method that receives the request object:
NavigationUtils.getProductUrl(request)
That method logic is driven by the request parameters.
What I get is that :
request.getQueryString() returns null
request.getParameterMap() has an entry for "recordNumber"
Is this standard behaviour or am I doing something wrong?
I've looked up the docs about HttpServletRequest.getQueryString() and ServletRequest.getParameterMap(), but I can't find that behaviour described nor any reference to a container-dependent handling that may yield different results.
The main issue is that I may break existing code using getParameterMap() instead of getQueryString(), so any advice on that would help.
The query string is nothing more than a mechanism to encode parameters in a request, but it's not the only one. Typically, that's used when a browser sends a GET request to the server. Another mechanism would be in the body of a form-encoded POST request.
In your case, the JSP wants to include the results of another JSP, which all happens server-side. The servlet container can pass parameters from one JSP to the other without having to encode the parameter on the query string (which would be unnecessarily inefficient).
Using getParameter or getParameterMap is the more general solution. Using getQueryString only really makes sense in specific circumstances when that's eexplicitly what you need to look art.
So I'm writing a Spring 3 webapp with JSP views and JSTL tags. They normally work great, but there's this one controller call that doesn't grab the tags properly.
ModelAndView mav = new ModelAndView(
new RedirectView(RequestUtil.getWebAppRoot(request) + clientShortName, false)
);
mav.addObject("status","Session for interface successfully removed");
return mav;
So when I go to reference it in my view, I'll have a line that looks like:
<p>status="${status}"</p>
Which just displays as:
status=""
Now I would normally just dismiss this as something causing my view to render improperly, but I actually found this sitting appended to my URL:
?status=Session+for+interface+zFXDEV3+successfully+removed
So this leaves me with two questions:
Why can't I reference the object from a JSTL tag?
If I can't get it as a part of the tag context, what is it doing in the URL?
and for anyone wondering, the class types are:
org.springframework.web.servlet.view.RedirectView.RedirectView
org.springframework.web.servlet.ModelAndView.ModelAndView(View view)
This is not JSTL but Expression Language (commonly known as EL). The problem is that EL ${status} will look the variable in the request attributes, but when you redirect to your JSP you have status as request parameter but not as request attribute (note that this is normal behavior when you redirect to a page).
For a better example (taken from StackOverflow Expression Language code), this is what is executed:
<%
String status = (String) pageContext.findAttribute("status");
if (status != null) {
out.print(status);
}
%>
You have two possible options here:
As stated by #SotiriosDelimanolis, your #Controller class for this URL should take the request parameters and add them as request attributes. Lot of work if you could add more request parameters in the future.
Use the ${param} object from EL that gives you access to the request parameters. Using this, you should change ${status} to ${param.status}. End of story.
Because it is a RedirectView. The javadoc says:
By default all primitive model attributes (or collections thereof) are
exposed as HTTP query parameters (assuming they've not been used as
URI template variables), but this behavior can be changed by
overriding the isEligibleProperty(String, Object) method.
So your String objects are added as query parameters in the new, redirected, request. They are no longer available as model/request attributes to the new request.
The #Controller that handles the redirected URL should re-add the attribute to the model.
What is the difference between fetching attributes from these implicit objects:
renderRequest.getAttribute("myVar")
actionRequest.getAttribute("myVar")
request.getAttribute("myVar")
Why are they all allowed?
I mean you usually store attribute in actionRequest or renderRequest object but you can get it in request implicit object, why?
What is the correct approach?
How is it possible to get an action object in view time?
Does not it violate the action-render renderParams passing mechanism?
Why are actionRequest/response available as implicit object if they throw NullPointerException when trying to use them in JSP?
Finally when is it useful to store an attribute in the request (PortalUtil.getOriginalServletRequest)?
What is the correct approach for accessing request attributes?
In portlets, the correct approach is to only interact with the renderRequest for retrieving parameter values and for getting or setting request attributes (in JSPs or the portlet class). renderResponse can be used to create new Portlet URLs.
Why can you get request attributes from the request object as well?
request is an HttpServletRequest and renderRequest is a PortletRequest. However, Liferay implemented request as a wrapper of HttpServletRequest in such way that, e.g. for accessing request attributes, it will fallback to the PortletRequest if it doesn't find the attribute in the actual HttpServletRequest.
What's the use of actionRequest and actionResponse at view time?
Like you say, if you follow the principles of MVC, you will only use the JSP for view logic. If you check the DefineObjectsTag from Liferay, you can see that all these xxxRequest and xxxResponse objects are only set if the portlet is in the right lifecycle. Because, normally, you're in the RENDER_PHASE when executing the JSP logic, only renderRequest and renderResponse will be not-null.
When is it useful to store an attribute in the request?
It doesn't really make sense to store attributes in the HttpServletRequest if you're working with portlets. On the other hand, inside a servlet (filter) you could add attributes that can then be retrieved from portlets by using request.getAttribute("xxx").
Is posible for a portlet to read a request parameter of its surrounding page?
E.g. the URL of the page the portlet resides in is http://example.com/mygroup/mypage?foo=bar Is it possible to read the "foo" parameter from a portlet that is on that page?
Portlet Container is Liferay 6.0.5.
P.S.
I have already tried:
com.liferay.portal.util.PortalUtil.getOriginalServletRequest(com.liferay.portal.util.PortalUtil.getHttpServletRequest((javax.portlet.PortletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest())).getParameter("foo")
but I always get null for productId
Thanks!
Have you tried
ExternalContext.getRequestParameterMap()
The following code will do the trick:
javax.portlet.PortletRequest pr = (javax.portlet.PortletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequestMap().get("javax.portlet.request");
java.lang.reflect.Method method = pr.getClass().getMethod("getOriginalHttpServletRequest");
HttpServletRequest httpServletRequest = (HttpServletRequest)method.invoke(pr, new Object[] {});
return httpServletRequest.getParameter(YOUR_PARAM_KEY);
In a partial submit, the icefaces ajax bridge (which replaces a usual jsf portlet bridge) is avoiding the normal portal action/render request, contacting directly the blocking servlet (in order to avoid invalidating other request-scoped portlets and in general, to be faster). Because of this, all those params/attributes which are set in a normal portal request are not set in ajax. They are set only in the initial GET type request for that page. So, actually what you should do is saving those params in the #PostConstruct or some other method of your controlling bean, and then reuse them later. (They wouldn't change in a partial submit anyway, right?).
Keep in mind though, that this will not work if you use IceFaces in conjuction with Spring (and their EL Resolver, since that eliminates your extended request scope).
if you are in JSF environment then try this:
String param = LiferayFacesContext.getInstance().getRequestQueryStringParameter("foo");
I think what I need is called reverse url resolution in Django. Lets say I have an AddUserController that goes something like this:
#Controller
#RequestMapping("/create-user")
public class AddUserController{ ... }
What I want is some way to dynamically find the url to this controller or form a url with parameters to it from the view (JSP), so I don't have to hardcode urls to controllers all over the place. Is this possible in Spring MVC?
Since Spring 4 you can use MvcUriComponentsBuilder.
For the most type-safe method:
String url = fromMethodCall(on(MyController.class).action("param")).toUriString();
Note this example requires that the method returns a proxyable type - e.g. ModelAndView, not String nor void.
Since 4.2, the fromMappingName method is registered as a JSP function called mvcUrl:
Login
This method does not have the proxy restriction.
Have you considered having a bean that aggregates all of the controller URLs you need into a HashMap and then adding this controller/URL Map to any model that requires it? Each Spring controller has the ability to call an init() method, you could have each controller add it's name and URL to the controller/URL map in the init() methods so it would be ready to use when the controllers go live.
Can solve with Java Reflection API. By Creating Custom Tag library. methods looks like this
Class c = Class.forName("Your Controller");
for(Method m :c.getMethods()){
if(m.getName()=="Your Method"){
Annotation cc = m.getAnnotation(RequestMapping.class);
RequestMapping rm = (RequestMapping)cc;
for(String s:rm.value()){
System.out.println(s);
}
}
}
Possible Problem You Can Face is
1.Path Variable > Like this /pet/show/{id} so set of path name & value should be support then replace this String.replace() before return url
2.Method Overriding > only one method is no problem. if Method override Need to give support sequence of Parameter Type That you really want like Method.getParametersType()
3.Multiple Url to Single Method> like #RequestMapping(value={"/", "welcome"}). so easy rule is pick first one.
4.Ant Like Style Url > Like this *.do to solve this is use multiple url by placing ant like style in last eg. #RequestMapping(value={"/pet","/pet/*.do"})
So Possible link tag style is
<my:link controller="com.sample.web.PetController" method="show" params="java.lang.Integer">
<my:path name="id" value="1" />
</my:link>
Where parmas attribute is optional if there is no method override.
May be I left to think about some problem. :)
I would probably try to build a taglib which inspects the annotations you're using in order to find a suitable match:
<x:url controller="myController">
<x:param name="action" value="myAction"/>
</x:url>
Taglib code might be something roughly like
Ask Spring for configured beans with the #Controller annotation
Iterate in some suitable order looking for some suitable match on the controller class or bean name
If the #RequestMapping includes params, then substitute them
Return the string
That might work for your specific case (#RequestMapping style) but it'll likely get a bit hairy when you have multiple mappings. Perhaps a custom annotation would make it easier.
Edit:
AbstractUrlHandlerMapping::getHandlerMap, which is inherited by the DefaultAnnotationHandlerMapping you're most likely using, returns a Map of URL to Handler
Return the registered handlers as an
unmodifiable Map, with the registered
path as key and the handler object (or
handler bean name in case of a
lazy-init handler) as value.
So you could iterate over that looking for a suitable match, where "suitable match" is whatever you want.
You can get access to the request object in any JSP file without having to manually wire in or manage the object into the JSP. so that means you can get the url path off the request object, have a google into JSP implicit objects.
Here is a page to get you started http://www.exforsys.com/tutorials/jsp/jsp-implicit-and-session-objects.html
The problem with this is that there's no central router in SpringMVC where all routes are registered and ordered. Then reverse routing is not a static process and route resolution in the view layer can be hard to integrate.
Check out this project for a centralized router (like rails) and reverse routing in the view layer.