JSR286 : The Eventing feature (updated)

When the Java Portlet Specification(JSR 286) early draft was released last year, i had written a blog on the Eventing. Recently the proposed final draft was released, it has some changes in the eventing feature. In this blog i will explain the feature with an example.

To create portlets that use the eventing feature, follow these steps(snippets from EventingMap sample application):

1.Declare the events in the portlet.xml

    1.1 Set the event definition at the portlet application level. This specifies the event name and the object type.
        Note: The object must be serializable and must be instrumented with valid JAXB annotation

   <portlet-app xmlns="http://java.sun.com/xml/ns/portlet/
portlet-app_2_0.xsd"
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="myPortletApp" version="2.0">
<portlet>
. . .
. . .
</portlet>

<event-definition>
<qname xmlns:x="http:sun.com/mapevents">x:Continent</qname>
<value-type>com.sun.portal.portlet.mapevent.Continent</value-type>
</event-definition>

</portlet-app>


@XmlRootElement
public class Continent implements Serializable {
public Continent() {
}
private String name;
private String description;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getDescription() {
return description;
}

public void setDescription(String description)
this.description = description;
}
}

  1.2 In the portlet section, specify the event name defined above for those portlets that want to publish this event.

        <portlet>
<description>ContinentPortlet</description>
<portlet-name>ContinentPortlet</portlet-name>
            .................
<supported-publishing-event>
<qname xmlns:x="http:sun.com/events">x:Continent</qname>
</supported-publishing-event>

        </portlet>


    1.3 In the portlet section, specify the event name defined above for those portlets that want to process this event.

    <portlet> 
<description>ContinentMapPortlet</description>
<portlet-name>ContinentMapPortlet</portlet-name>
. . .
<supported-processing-event>
<qname xmlns:x="http:sun.com/events">x:Continent</qname>
</supported-processing-event>

</portlet>
  <portlet>
<description>ContinentInfoPortlet</description>
<portlet-name>ContinentInfoPortlet</portlet-name>
. . .
<supported-processing-event>
<qname xmlns:x="http:sun.com/events">x:Continent</qname>
</supported-processing-event>

</portlet>
. . .
</portlet-app>

    
2. Issue an event in the portlet that was specified as supported-publishing-event in the portlet.

public class ContinentPortlet extends GenericPortlet {

public void processAction(ActionRequest request, ActionResponse response)
throws PortletException,IOException {

QName qname = new QName("http:sun.com/mapevents" , "Continent")
String value = request.getParameter("continent");
Continent continent = new Continent();
continent.setName(value);

ResourceBundle rb = getPortletConfig().getResourceBundle(request.getLocale());
continent.setDescription(rb.getString(value));
response.setEvent(qname, continent);
}
. . .
}

3. Process the event in the portlet that has specified as supported-processing-event in the portlet

public class ContinentInfoPortlet extends GenericPortlet {

public void processEvent(EventRequest request, EventResponse response) {

Event event = request.getEvent();
if(event.getName().equals("Continent")){
Continent payload = (Continent)event.getValue();
response.setRenderParameter("continentDescription",
payload.getDescription());
}

}

. . .

}


public class ContinentMapPortlet extends GenericPortlet {
public void processEvent(EventRequest request, EventResponse response) {

Event event = request.getEvent();
if(event.getName().equals("Continent")){
Continent payload = (Continent)event.getValue();
response.setRenderParameter("continentName", payload.getName());
}

}
. . .
}

You can download the binary file EventingMap.war to deploy and run the sample application in OpenPortal Portlet Container 2.0 Beta2(or latest). You can also get the source for the sample.

The figure shows the World Map, Continent Information, and Continent Map Portlets that participate in the event. Clicking on any continent in the World Map triggers an event. This event is processed by the Continent Information and Continent Map Portlets to show the relevant information.


Comments:

Thank you for the example and explanation of eventing.
Can you please explain how the text that appears in the Continent Information paragraph is obtained? The WAR file correctly deployed and the application works. I also downloaded all the source code. But I don't see where the information comes from that shows continent information (getResourceBundle() in ContinentPortlet.java??).

Posted by GeoInt on April 21, 2008 at 01:46 PM IST #

Good to know that it was useful.
See the following snippet of code in ContinentPortlet.java
-------------------------------------------------------------
String value = request.getParameter("continent");
....
ResourceBundle rb = getPortletConfig().getResourceBundle(request.getLocale());
continent.setDescription(rb.getString(value));
-------------------------------------------------------------
The call getResourceBundle(..) returns the resource bundle specified in the portlet.xml for the portlet, ContinentPortlet. As you can see from portlet.xml(<resource-bundle>ContinentPortlet</resource-bundle>), this is ContinentPortlet.properties. The "value"(i.e value of the request parameter "continent") is a key in ContinentPortlet.properties. So rb.getString(value) will return the description of the continent. I hope i am clear. Let me know if you need more info.

Posted by Deepak Gothe on April 22, 2008 at 05:03 AM IST #

Yes, thank you, now I understand how the ResourceBundle works. I am trying to modify your example to use an openlayers.org dynamic map. There is an OpenLayers javascript function that will capture the coordinates where the user clicks on the map. I need to pass these coordinates as parameters in the portlet:actionURL tag. All examples I can find show parameter values as strings. Is there a way to pass a value that is not a string, ie, a double or float? I have tried using string concatenation to build the string like I would for a regular URL that had parameters that were not strings. But I can't seem to get the syntax correct within the portlet:actionURL tag.

Posted by GeoInt on April 22, 2008 at 11:08 AM IST #

It would help the community if you pose the questions on the alias(https://portlet-container.dev.java.net/servlets/ProjectMailingListList)

Yes parameters are always Strings..

try..

<portlet:actionURL>
<portlet:param name="int1" value="10" />
<portlet:param name="float1" value="10.02" />
</portlet:actionURL>

Posted by Deepak Gothe on April 23, 2008 at 07:08 AM IST #

Thank you. I am still unable to get my application to work. I will pose my questions elsewhere, as you suggest. However, I cannot access the link you gave for the alias. Would this be the same as posting to the forum: http://forum.java.sun.com/category.jspa?categoryID=111 You had suggested posting to that forum last week when I posted a question about EventingMap to the wrong forum.

Posted by GeoInt on April 23, 2008 at 07:03 PM IST #

There was an extra ), so the URL was not accessible. Try https://portlet-container.dev.java.net/servlets/ProjectMailingListList

If you pose questions to the alias, you might responses from community you might have faced similar issues. Sure you can also try posting to the forum. While posting the question to the alias/forum, can you provide code snippets so that we know what problem you are facing. Thanks.

Posted by Deepak Gothe on April 24, 2008 at 05:38 AM IST #

Hi Deepak,
I am getting an exception while setting the event in response object.
The code is :
response.setEvent(qName, EventsData);
Where EventsData class stores a Map of <String, MyObjects>.MyObjects class has properties of objects type (arrays) say obj1 [] ,obj2 etc.
when I call response.setEvent(qName, EventsData), the application throws
exception:
Cannot serialize to xml for the value type:com.portlet.Events of event: {http://sunevents.com}myEvents
com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 117 counts of IllegalAnnotationExceptions
Class has two properties of the same name "obj1"
and same for the other properties.
All of the objects implements Serializable.
Please help me out

Posted by Hariom Tiwari on March 06, 2009 at 04:28 AM IST #

Hi Hariom,
We use JAXB serialization for eventing. Check this thread for possible clues to your issue.

http://forums-beta.sun.com/thread.jspa?messageID=9798273

Posted by Deepak Gothe on March 06, 2009 at 06:34 AM IST #

Hi Deepak,
If we want to make this test of eventing in the liferay Is there is a need to add portal.container.impl=sun in the Portal-ext.properties

is it compulsary to add

Posted by srinivas on July 21, 2009 at 02:17 PM IST #

Hi Srinivas,
Not required to add portal.container.impl=sun in the portal-ext.properties. As the eventing sample mentioned in this blog is basic. It should work with portlet-container.impl=internal(which is the default).

Posted by Deepak on July 23, 2009 at 03:29 AM IST #

Hi,

The link: https://portlet-container.dev.java.net/files/documents/5463/80971/EventingMap.war , doesnt working.
Can anybody send me a sample on a email: boobu@go2.pl, or give my some other link..

Thanks!

Posted by Beata on October 21, 2009 at 10:38 AM IST #

I am trying to make a sample with two war files, communicating via events.
One portlet is a producer and the second is a customer. Both have defined the same data model, eg. Order.class - so the producer has a Order class, and the customer has a Order class.
I am trying to send event from producer to customer, with Order object attached. Customer recives the event, gets the object of the event. The Order object is a POJO class marked with JAXB annotation. The object is properly send and recived:

javax.portlet.Event event = eventRequest.getEvent();
Order order = (Order) event.getValue(); << but during the class cast I get the ClassCastException, because the Order.class is loaded with different class loader, and I cannot cast it.

I do not know if this exception is caused because the serialization mechanism is not working, and I have something misconfigure, or maybe deploying the same classes in 2 portlets is not good solution.

I could externalize common classes to separate jar and deploy it on the server common class loader (on the server class path), but maybe there is some other way?

I would appreciate any clues.

Posted by Beata on October 21, 2009 at 11:59 AM IST #

I forgot to write, that I am using: Liferay & Tomcat 6.0 bundle, and Java JDK 6.0.

Posted by Beata on October 21, 2009 at 12:27 PM IST #

If you are using Liferay & Tomcat 6.0 bundle, and Java JDK 6.0, then the option of having a separate jar for common classes in server classpath is the only solution. But if you don't want to do it, you can change the portlet container implementation in liferay to use OpenPortal Portlet Container 2.x. This can be done by setting setting the property "portlet.container.impl=sun" in portal-ext.properties. You need for Liferay 5.2.3 for this to work. After doing the change you need to redploy the portlet wars. As Portlet Container 2.x uses JAXB serialization for eventing, you don't need a separate jar in server classpath.

Posted by Deepak on October 22, 2009 at 07:29 AM IST #

Thank you very much for the reply. I did set the property: portlet.container.impl=sun" in portal-ext.properties file. It switch on the JAXB serialization. But then, I have a problem with JSF:

java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.lifecycle.LifecycleFactory
at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:725)

My web.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="MyWPSRFPortletConsumerProj" version="2.5" metadata-complete="true"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>MyWPSRFPortletConsumer</display-name>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>/WEB-INF/faces-config.xml</param-value>
</context-param>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.jsp</param-value>
</context-param>
<context-param>
<param-name>com.ibm.ws.jsf.JSP_UPDATE_CHECK</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>com.ibm.ws.jsf.LOAD_FACES_CONFIG_AT_STARTUP</param-name>
<param-value>true</param-value>
</context-param>

<context-param>
<param-name>javax.portlet.faces.renderPolicy</param-name>
<param-value>ALWAYS_DELEGATE</param-value>
</context-param>
<context-param>
<param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
<param-value>org.jboss.portletbridge.application.FaceletPortletViewHandler</param-value>
</context-param>
<context-param>
<param-name>org.ajax4jsf.RESOURCE_URI_PREFIX</param-name>
<param-value>rfRes</param-value>
</context-param>
<context-param>
<param-name>org.ajax4jsf.SKIN</param-name>
<param-value>renewal</param-value>
</context-param>
<context-param>
<param-name>org.richfaces.LoadStyleStrategy</param-name>
<param-value>DEFAULT</param-value>
</context-param>
<context-param>
<param-name>org.richfaces.LoadScriptStrategy</param-name>
<param-value>DEFAULT</param-value>
</context-param>

<context-param>
<param-name>com.ibm.faces.DISABLE_JWL_MULTIPART_CONTEXT</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>com.ibm.faces.RESOURCE_EXPIRE_MS</param-name>
<param-value>31536000000</param-value>
</context-param>
<context-param>
<param-name>com.ibm.faces.DATETIME_ASSIST_STRICTNESS</param-name>
<param-value>1</param-value>
</context-param>
<context-param>
<param-name>com.ibm.faces.NUMBER_ASSIST_STRICTNESS</param-name>
<param-value>1</param-value>
</context-param>
<context-param>
<param-name>com.ibm.faces.USE_UNENCODED_CONTEXT_PATH</param-name>
<param-value></param-value>
</context-param>
<context-param>
<param-name>com.ibm.faces.JS_RESOURCE_SERVLET_URL_PATTERN</param-name>
<param-value>/.ibmjsfres/\*</param-value>
</context-param>
<context-param>
<param-name>com.ibm.faces.JS_RESOURCE_SERVLET_CACHE</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>com.ibm.faces.ENCODING_MAPPING</param-name>
<param-value>converter.properties</param-value>
</context-param>
<context-param>
<param-name>com.ibm.faces.USE_HXCLIENT_FULL</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>com.ibm.faces.ENCODE_DATA</param-name>
<param-value>true</param-value>
</context-param>

<context-param>
<param-name>com.ibm.faces.TURN_OFF_AJAX_PORTAL_60_PATH</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>com.ibm.faces.MAX_REQUEST_CONTENT_SIZE</param-name>
<param-value>0</param-value>
</context-param>
<context-param>
<description>
Number of Views to be stored in the session when Enhanced State Saving is being used.
Default is 15.</description>
<param-name>com.ibm.faces.ENHANCED_SERVER_STATE_SAVING_SESSION_STORED_VIEWS</param-name>
<param-value>15</param-value>
</context-param>

<filter>
<filter-name>richfaces</filter-name>
<filter-class>org.ajax4jsf.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>richfaces</filter-name>
<url-pattern>/\*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>richfaces</filter-name>
<url-pattern>/faces/rfRes/\*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>

<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
<!--listener>
<listener-class>pagecode.MyListener</listener-class>
</listener-->

<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>JavaScript Resource Servlet</servlet-name>
<servlet-class>com.ibm.faces.webapp.JSResourceServlet</servlet-class>
<load-on-startup>-1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>
/faces/\*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>JavaScript Resource Servlet</servlet-name>
<url-pattern>/.ibmjsfres/\*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>

I am using RhichFaces 3.3.1., and PortletBride :my faces-config.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
"http://java.sun.com/dtd/web-facesconfig_1_1.dtd">

<faces-config>
<application>
<view-handler> org.jboss.portletbridge.application.PortletViewHandler</view-handler>
<state-manager>org.jboss.portletbridge.application.PortletStateManager</state-manager>
</application>
<factory>
<faces-context-factory>org.jboss.portletbridge.context.FacesContextFactoryImpl</faces-context-factory>
</factory>

<managed-bean>
<managed-bean-name>producerBean</managed-bean-name>
<managed-bean-class>com.nsn.ProducerManagedBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>

</faces-config>

So you say that the only way is to externalize the jar? Because on the other hand I would have problems with JSF.
Maybe I have something configure wrong.

Best Regards
Beata

Posted by Beata on October 26, 2009 at 07:46 AM IST #

Its not clear how enabling JAXB would affect JSF initialization.

Posted by Deepak on October 26, 2009 at 08:27 AM IST #

Can someone please help me with this issue ? (I'm new to JSR-286 )

I am unable to call setEvent method from within processAction of my portlet. It says method is undefined for type ActionResponse.

Thanks,

Josh

Posted by Josh on November 23, 2009 at 02:42 PM IST #

Which version of OpenPortal Portlet Container are you using? Are you seeing the problem during compilation. If that is the case, looks like you are compiling with JSR168 portlet jar. Compile with JSR286 portlet jar.

Posted by Deepak on November 24, 2009 at 03:36 AM IST #

Yes, I had both the old JSR168 portlet jar and the new 286 jar in my WEB-INF/lib directory. I got rid of 186, and it worked..!!

Appreciate your help...!!!

- Josh

Posted by Josh on November 28, 2009 at 02:44 PM IST #

i already did this screen cast but the render action doesent work
so i want to find the problem

i downloaded the source but when it was deployed doesent show the render action neither

thanks for ur help

Posted by juan on February 15, 2010 at 03:14 PM IST #

i already did this screen cast but the render action doesent work
so i want to find the problem

i downloaded the source but when it was deployed doesent show the render action neither
http://contrib.netbeans.org/portalpack/demos/evtstoryboard/eventing-story-board.htm

thanks for ur help

Posted by juan on February 15, 2010 at 03:22 PM IST #

Which version of OpenPortal Portlet Container are you using? On which webcontainer is it running? What is the JDK version? Are there any exceptions in the logs?

Posted by Deepak on February 16, 2010 at 08:21 AM IST #

open portal 3.0
Sun Java System Portal Server 7.x ver 3.0
OpenPortal Portlet Container ver 3.0

all of the portal pack of netbeans

JDK 1.6

no log exceptions(just not render even with the example source)

PSPL_PCCSPCPCI0002 : Invoking AppName:DatosEmpleadoConsumidor, PortletName:DatosEmpleadoConsumidor, PortletWindowName:DatosEmpleadoConsumidor.DatosEmpleadoConsumidor, Action:RENDER

Deployment of application InformacionDeEmpleado completed successfully
All operations completed successfully
PortalPack Message : Deployed Successfully.

thanks im noob in posting

Posted by juan on February 17, 2010 at 12:19 PM IST #

When you access http://host:port/portletdriver , what do you see? Do you see a Welcome Portlet that mentions the version? Are you saying that eventing is not working? Can you try the eventing sample from https://portlet-container.dev.java.net/public/Samples.html

Posted by Deepak on February 18, 2010 at 05:22 AM IST #

sort of that. i can see the portlet in the portlet container
but the problem is :

when i make an action in one portlet
i want to the another portlet handle the action

in this case i only tried to ask for a name in the firts one
and in the second one show the name

but the name in the second portlet didnt change the value of null for the name i put in the first one (render action)

so thats it i made the demo
but it doesent work properly (the null name doesent change)

then i prove to deploy the example .war of the site but it doesent change the null name neither

this is the example site:
http://contrib.netbeans.org/portalpack/demos/evtstoryboard/eventing-story-board.htm

ill try the another demos thanks

Posted by juan on February 18, 2010 at 02:08 PM IST #

Looks like there may be some issues with your application. Can you send your application to dev@portlet-container.dev.java.net

Posted by Deepak on February 19, 2010 at 06:27 AM IST #

In what cases are eventing better than passing data via public render parameters and portlet session?

Posted by will on December 02, 2011 at 01:19 PM IST #

Public render parameters can be considered as light weight eventing, where you can pass only string data. But if you want to pass complex objects, you will require eventing. Complex object can also be passed across portlets via portlet session using Application Scope, but the problem is even the other portlets that are not part of eventing can also see the data.

Posted by Deepak on December 05, 2011 at 05:58 AM IST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Deepak Gothe

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today