Passing Complex Objects using portlet events

In the Hello Portlet Events entry, i built a sample to demonstrate how you can pass simple String using as value of event from one portlet to another. But if you want to pass a custom/ complex object and source and target portlets are not packaged in the same .war file then you will have to follow some additional steps.

I built 2 sample portlets to demonstrate how you can pass complex object from one portlet to another. The EventSourcePortlet passes object of com.webspherenotes.portlet.events.Contact type to TargetSourcePortlet.

You can download the sample code for this project from here

  1. Contact

  2. EventSource

  3. EventTarget



I had to follow these steps


  1. I started by creating Contact Java project, this project has Contact.java class like this

    public class Contact implements Serializable{
    private static final long serialVersionUID = -1637774642655976822L;
    private String firstName;
    private String lastName;
    private String email;
    public Contact(){
    }
    public Contact(String firstName, String lastName, String email) {
    super();
    this.firstName = firstName;
    this.lastName = lastName;
    this.email = email;
    }
    public String getFirstName() {
    return firstName;
    }
    public void setFirstName(String firstName) {
    this.firstName = firstName;
    }
    public String getLastName() {
    return lastName;
    }
    public void setLastName(String lastName) {
    this.lastName = lastName;
    }
    public String getEmail() {
    return email;
    }
    public void setEmail(String email) {
    this.email = email;
    }
    }

    The Contact class is simple POJO class and it implements Serializable interface. That is because the setEvent() method takes object of Serializable type as argument for event value

  2. Compile the Contact java source into contact.jar and copy it into shared library of your portal. In case of WebSphere portal it will be WebSphere/PortalServer/shared/app

  3. Create EventSourcePortlet project and in that create EventSourcePortlet.java like this

    public class EventSourcePortlet extends javax.portlet.GenericPortlet {
    public void init() throws PortletException {
    super.init();
    }
    protected void doView(RenderRequest request, RenderResponse response)
    throws PortletException, IOException {
    System.out.println("Entering SourcePortlet.doView()");
    response.setContentType("text/html");
    if (request.getPortletSession().getAttribute("contact") != null) {
    request.setAttribute("contact", request.getPortletSession()
    .getAttribute("contact"));
    }
    getPortletContext().getRequestDispatcher("/source.jsp").include(
    request, response);
    System.out.println("Exiting SourcePortlet.doView()");
    }
    public void processAction(ActionRequest request, ActionResponse response)
    throws PortletException, IOException {
    System.out.println("Entering SourcePortlet.processAction()");
    String fName = request.getParameter("fName");
    String lName = request.getParameter("lName");
    String email = request.getParameter("email");
    Contact contact = new Contact(fName, lName, email);
    response.setEvent("hello", contact);
    request.getPortletSession().setAttribute("contact", contact);
    System.out.println("Exiting SourcePortlet.processAction()");
    }
    }

    The doView() method of the EventSourcePortlet is forwarding control to contact.jsp for rendering. The contact.jsp displays a simple form to user where user can input firstName, lastName and email.

    The processAction() method of EventSourcePortlet gets control when user enters values on the form and clicks submit. In this method, I am reading values submitted by user and then creating a Contact object and then setting and event with name equal to hello and value equal to the Contact object.


  4. Create EventTargetPortlet and inside that create EventTargetPortlet.java like this

    public class EventTargetPortlet extends javax.portlet.GenericPortlet {
    protected void doView(RenderRequest request, RenderResponse response)
    throws PortletException, IOException {
    System.out.println("Entering TargetPortlet.doView()");
    response.setContentType("text/html");
    Contact contact = (Contact) request.getPortletSession().getAttribute(
    "contact");
    if (contact != null) {
    response.getWriter().println(
    "First Name " + contact.getFirstName() + "
    Last Name "
    + contact.getLastName() + "
    Email "
    + contact.getEmail());
    } else {
    response.getWriter().println("Contact not found in session ");
    }
    System.out.println("Exiting TargetPortlet.doView()");
    }

    public void processEvent(EventRequest request, EventResponse response)
    throws PortletException, IOException {
    System.out.println("Entering TargetPortlet.processEvent");
    Event event = request.getEvent();
    System.out.println("Event Name " + event.getName());
    Contact contact = (Contact) event.getValue();
    System.out.println("Contact First Name " + contact.getFirstName());
    System.out.println("Contact Last Name " + contact.getLastName());
    System.out.println("Contact Email " + contact.getEmail());
    request.getPortletSession().setAttribute("contact", contact);
    System.out.println("Exiting TargetPortlet.processEvent");
    }
    }

    The processEvent() method of the EventTargetPortlet get control whenever it receives event, in this method it is reading the Contact object that was sent as event payload and then setting it as attribute in PortletSession.
    In the doView() method it reads the Contact object from PortletSession and prints those values

  5. This is how the portlet.xml file for the EventSourcePortlet looks like

    <?xml version="1.0" encoding="UTF-8"?>
    <portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
    id="com.webspherenotes.portlet.event.EventSourcePortlet.1a884b6b82">
    <portlet>
    <portlet-name>EventSourcePortlet</portlet-name>
    <display-name xml:lang="en">EventSourcePortlet</display-name>
    <display-name>EventSourcePortlet</display-name>
    <portlet-class>com.webspherenotes.portlet.event.EventSourcePortlet</portlet-class>
    <init-param>
    <name>wps.markup</name>
    <value>html</value>
    </init-param>
    <expiration-cache>0</expiration-cache>
    <supports>
    <mime-type>text/html</mime-type>
    <portlet-mode>view</portlet-mode>
    </supports>
    <supported-locale>en</supported-locale>
    <resource-bundle>com.webspherenotes.portlet.event.nl.EventSourcePortletResource</resource-bundle>
    <portlet-info>
    <title>EventSourcePortlet</title>
    <short-title>EventSourcePortlet</short-title>
    <keywords>EventSourcePortlet</keywords>
    </portlet-info>
    <supported-publishing-event>
    <name>hello</name>
    </supported-publishing-event>
    </portlet>
    <default-namespace>http://wpcertification.blogspot.com</default-namespace>
    <event-definition>
    <name>hello</name>
    <value-type>com.webspherenotes.portlet.events.Contact</value-type>
    </event-definition>
    </portlet-app>

    As you can see the value-type of the event is com.webspherenotes.portlet.events.Contact to indicate that we want to send object of Contact class as event payload

No comments: