IPC Event - Custom Bean in Spring MVC Portlet

This article demonstrates how to use inter-portlet communication in Liferay Portal Web applications based on JSR 286(Sometimes called Portlet 2.0) events.
 
We have used Spring portlets in the following example. Here we are passing one custom employee bean object from one portlet to another.
 
#Publisher portlet.xml entry:
 
<portlet>
         <portlet-name>SenderPortlet</portlet-name>
<display-name>Sender Portlet</display-name>
   <display-name xml:lang="en">Sender Portlet</display-name>
<portlet-class>org.springframework.web.portlet.DispatcherPortlet</portlet-class>
<init-param>
<name>contextConfigLocation</name>
<value>classpath:context/portlet/senderPortlet.xml</value>
</init-param>
 
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<supported-locale>en</supported-locale>
<supported-locale>es</supported-locale>
<resource-bundle>messages.senderPortlet</resource-bundle>
  <supported-publishing-event>
            <qname xmlns:x="http://liferay.com/events">x:empDetailBean</qname>
   </supported-publishing-event>
</portlet>
 
<event-definition>
       <qname xmlns:x="http://liferay.com/events">x:empDetailBean</qname> 
       <value-type>com.test.personal.EmployeeBean</value-type>
</event-definition>
 
 
# Publisher Controller Code:
 
@ActionMapping(value = "fetchEmpValues")
public void getEmployeeDetails(final Model model, ActionRequest request, ActionResponse response) {
 
//..other codes
EmployeeBean empBeanObj = fetchempDetails(empID);
//...other codes
javax.xml.namespace.QName qName = new QName("http://liferay.com/events", "empDetailBean", "x");
response.setEvent(qName, empBeanObj);
}
 
# Receiver/Processor portlet.xml entry:
 
<portlet>
<portlet-name>ReceiverPortlet</portlet-name>
<display-name>Receiver Portlet</display-name>
   <display-name xml:lang="en">Receiver Portlet</display-name>
<portlet-class>org.springframework.web.portlet.DispatcherPortlet</portlet-class>
<init-param>
<name>contextConfigLocation</name>
<value>classpath:context/portlet/receiverPortlet.xml</value>
</init-param>
 
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<supported-locale>en</supported-locale>
<supported-locale>es</supported-locale>
<resource-bundle>messages.receiverPortlet</resource-bundle>
      <supported-processing-event>
          <qname xmlns:x="http://liferay.com/events">x:empDetailBean</qname>
     </supported-processing-event>
</portlet>
<event-definition>
       <qname xmlns:x="http://liferay.com/events">x:empDetailBean</qname> 
       <value-type>com.test.personal.EmployeeBean</value-type>
</event-definition>
 
In the controller class we need to receive the event and get the event parameters values which has been passed from sender.
 
This processEvent method in the receiver portlet will always get called after the render/processAction method of the receiver class as per the Life cycle defined in JSR 286.
 
# Receiver/Processor Controller Code:
 
import javax.portlet.EventPortlet;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
@Controller
@RequestMapping("VIEW")
public class EventReceiverController implements EventPortlet{
 
private static final Logger logger = LoggerFactory.getLogger(EventReceiverController .class);
 
@EventMapping
public void processEvent(EventRequest request, EventResponse response) throws PortletException, IOException {
javax.portlet.Event event = request.getEvent();
        EmployeeBean empBeanObj = (EmployeeBean) event.getValue();
        logger.info("emp name: "+empBeanObj.getEmployeeName());
        response.setRenderParameter("empDetailObject", empBeanObj.toString());
        response.setRenderParameter("empFirstName", empBeanObj.getEmpFirstName());
        //request.getPortletSession().setAttribute("empDetailObject", empBeanObj);
}
 
Need to implement EventPortlet Interface in your Event Receiver Portlet Controller class.
 
## Note:
The @EventMapping will only applicable to the Single event per portlet. 
For multiple events we need to use
@EventMapping(value ="{http://liferay.com/events}empDetailBean)" 
 
In the above example my Sender and Receiver portlets are in the same page. But if the Sender and Receiver portlets are in different page, then we need add the following entry in the portal-ext.properties file.
 
## portal-ext.properties entry:
portlet.event.distribution=layout-set
 
Blogs
Really very nice and helpful article it is.
I have followed all the steps but my processEvent method is not being called and am not able to send the event data to front side of second portlet.
can you please help me on this? How to debug events in liferay portlets?

Thanks & Regards,
Nrupay Shah
Hi,
Thanks for sharing.
I followed your example and I needed to add a @ModelAttribute method in order to initialize a model and put it into session. This step causes the exception below:
org.springframework.web.bind.annotation.support.HandlerMethodInvocationException: Failed to invoke handler method [public void com.test.SenderController.myAction(org.springframework.web.bind.support.SessionStatus,javax.portlet.ActionResponse)]; nested exception is java.lang.IllegalStateException: Current request is not of type [javax.portlet.RenderRequest]: com.liferay.portlet.ActionRequestImpl@127e27ff

An idea about that ?

Many thanks.

regards,