Navigation after IPC in Liferay - jsf

we want to navigate in Liferay to an other portlet after receiving a IPC-Event.
So we send the event from one portlet, implemented an second Portlet extends from MVCPortlet, and receive the event with some information!
So we want to navigate in Liferay to the second portlet.
The methode were we receive the event is this
#ProcessEvent(qname = "{http://liferay.com}empinfo")
public void handleProcessempinfoEvent(final javax.portlet.EventRequest request, final javax.portlet.EventResponse response) throws javax.portlet.PortletException, java.io.IOException
Also we override the methods from com.liferay.util.bridges.mvc.MVCPortlet but no one was called after sending the event.
Is there any way to navigate inside liferay (6.1.2)?
Thx Tim

Is the event handled at all? What do you mean with "navigate to the second portlet"?. Events - by default - only get distributed to the portlets that appear on the same page. If you want to receive an event on a portlet that exists on a different page, you'll have to explicitly configure Liferay to distribute events to all pages in the same site. Note that this might dig into your performance. Also - once you navigate to another page - by default the portlet's state on that page is being reset.
Check the following (and related) portal.properties:
#
# Set this property to specify how events are distributed. If the value is
# "layout-set", then events will be distributed to all portlets contained in
# a layout set. If the value is "layout", then events will be distributed to
# all portlets that are present in a layout.
#
portlet.event.distribution=layout
#
# Set this property to specify how public render parameters are distributed.
# If the value is "layout-set", then public render parameters will be
# distributed to all portlets contained in a layout set. This will only work
# correctly if the property "layout.default.p_l_reset" is set to false. If
# the value is "layout", then public render parameters will be distributed
# to all portlets that are present in a layout.
#
portlet.public.render.parameter.distribution=layout
#
# Set the default value for the "p_l_reset" parameter. If set to true,
# render parameters are cleared when different pages are hit. This is not
# the behavior promoted by the portlet specification, but is the one that
# most end users seem to prefer.
#
layout.default.p_l_reset=true
If you intend to navigate to a different page, you'll also have to note that this is not covered by the portlet API. Thus you'll have to identify how to find the relevant page, its URL and how to redirect. It's probably easier to have some more logic in the action-handling portlet and do the redirect there: At least you'll only handle one action. Potentially there might be several Events handled per Action - thus it's undefined which potential redirect will be triggered if they conflict. I'd see a real redirect (any way) as rather unexpected behavior if it comes from an EventHandler, but somewhat understandable from an ActionHandler.

Related

When does mojarra adds a naming container to the list of optional parameters?

In the source of the class AjaxBehaviorRenderer (line 260) there is a line that apparently appends the NamingContainer Id to the list of optional parameters of mojarra.ab(...). I've never come across it so I'm curious as to when it is used:
RenderKitUtils.appendProperty(ajaxCommand, "com.sun.faces.namingContainerId", namingContainerId, true);
line 260
While working on spec issue 790 last week, which should solve a.o. Rendering other form by ajax causes its view state to be lost, how do I add this back?, this was explained to me by Neil Griffin, a portlet guy.
It appears that portlets can have multiple JSF views rendering to the same HTML document, each with its own view state. In portlets, there's a special UIViewRoot instance which implements NamingContainer. During regular rendering, all forms, inputs and commands will have IDs and names prefixed with the view's own client ID. This will work fine during synchronous postbacks. The portlet can this way identify the exact view to restore.
However, during asynchronous postbacks, the jsf.js will create a bunch of additional ajax-specific request parameters such as javax.faces.source, javax.faces.partial.event, etc. Those request parameter names are not prefixed with the view's own client ID. Therefore the portlet cannot associate them with a specific view. Hence the impl issue 3031.
There was another problem of view state identifiers in ajax responses not being properly namespaced this way. Therefore the portlet implementation had to customize the partial response writer in the so-called "JSF bridge". This will be taken into account during implementing spec issue 790. Instead of sniffing a "portlet environment" as in current implementation, there will be checks on UIViewRoot instanceof NamingContainer which is more flexible and portlet-independent. The Mojarra-specific com.sun.faces.namingContainerId will also be removed. Instead, this value will be rendered to <partial-response id="..."> so that the jsf.js can just extract from there.
All in all, not really important if you're only targeting servlet based environments.
As per balusC comment :
It's only interesting for portlet based apps (not servlet based apps).
I can't exactly explain why and what it is used for (a portlet/liferay
guy might), but the portlet specific feature is called "namespaced
parameters". See https://web.liferay.com/web/meera.success/blog/-/blogs/liferay-requires-name-spaced-parameters

How to update Layout in PortletLayoutListener

The goal is to implement a Tab Portlet - portlet for displaying and managing tabs containing nested portlets (similar to Nested Portlets Portlet).
One of the requirements is to remove the nested portlet references from Layout on Tab Portlet removal.
I implemented PortletLayoutListener and indeed, method onRemoveFromLayout is called on Tab Portlet removal. The listener updates the layout. While debugging the listener, I can verify that the changes were written to Liferay database (to LAYOUT table).
The Layout instance is obtained through LayoutLocalServiceUtil.getLayout(plid) method.
The update is performed with LayoutLocalServiceUtil.updateLayout method.
The problem is that the listener is called from UpdateLayoutAction, which afterwards updates the Layout itsef and overwrites my changes (it reverts them).
The question is - is it possible to update Layout in PortletLayoutListener.onRemoveFromLayout method? If not, is there other option I could use?
Hi the PortletLayoutListeners are intended to be used in relation to the portlet. So if you want to react on a change on the page in your portlet.
If you want to change the portal, I would have a look at the model listeners. Create a hook with a Layout model listener and try to make you changes in the afterUpdate method. But be careful not to affect the performance.
You may even require both of the classes one to make an indication and the second one to make a change.

how to set portlet load order in liferay portlets

I have around 4 portlets and 2 web content on my page. Among 4 portlets, one is custom portlet. my requirement is like I need to load my custom portlet at the end.
I got to know we can set this by adding following entry in liferay-portlet.xml
<render-weight>0</render-weight>
from liferay-portlet-app_6_2_0.dtd I got to know
, The default value of render-weight is 1. If set to a value less than 1, the
portlet is rendered in parallel. If set to a value of 1 or greater, then the
portlet is rendered serially. Portlets with a greater render weight have greater
priority and will be rendered before portlets with a lower render weight.
My question is, how can i set render weight of liferay portlets. Do i need to do entry in some properties file or i can achieve this using control panel.
There is no guarantee of render order and you shouldn't change any state in the render phase - in fact no state change (e.g. public render parameter etc) is propagated, if only because you can't even change them on RenderRequest/RenderResponse.
If you rely on the assumption of a specific rendering order, you should rather change the architecture so that this assumption is no longer required. If your portlet takes some time to render, you can have it display asynchronously (e.g. like the built-in RSS portlet). If I remember correctly this is done by setting <render-weight> to 0 and <ajaxable> to true in liferay-portlet.xml

Send parameter from Portlet doView to portal_normal.vm

I'm trying to send a parameter from Portlet doView function to portal_normal.vm
Is it possible? How can I send and receive it?
Sorry, but I can't see the way to do through request.
In doView I wrote
HttpServletRequest httpRequest = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(renderRequest));
httpRequest.setAttribute("hola", "hola");
And in the portal normal I tried with:
#set ($holas =$request.get('attributes').get('hola'))
#set ($holas2 = $request.getSession().getAttribute("hola"))
$holas
$holas2
but Velocity only shows $holas $holas2
This sounds like an overly specific plan to display some information outside of the portlet - but also well outside the portlet spec. Is it possible? Yes. Does it have limitations? Yes.
I didn't try it, but I'd argue that you don't have any guarantee that all render phases of all portlets have been finished before portal_normal.vm starts to be evaluated. Technically it's only necessary to have them finished once they are actually about to render. Render is not allowed to change any state - and you're implying that in your case it might do - because on render something else will be displayed.
It might make sense to rather assume that your theme has some DOM element that is available on the page. Then render some javascript that manipulates this DOM element. The dependency on the theme is the same, but you could also fall back to some default rendering in case you can't find the DOM element.
Alternatively, if you insist on your mode of operation. you might try to go through the servlet-session (portlet session won't help) as you have access to the HttpServletRequest from portal_normal.vm. Be warned though: Access to HttpServletRequest is nonstandard and not really portal-thinking

JSF Page Navigation

I want to enable or disable component based on navigation rule. For example, I want to enable a component when I traverse from a particular page otherwise it should be in disabled state.
Probably the easiest way if you're using JSF 2.0, is to put a parameter in your navigation rule. If you use an f:viewParam on the target page that you bind to some bean, you can just check whether the property to which you bound the view parameter is empty or not.
If your navigation rule does not cause a redirect, you can also put some marker in request scope. The initial rendering of the target page will happen within the same request and easily pick this up. In that case, you do have to store it in some appropriate place (e.g. view scope in JSF 2) to retain the info on postbacks.

Resources