We will discussion here to get started with the JSR 286 Wicket portlet development on WebSpere Portal 6.1. Wicket release 1-4-rc2 has been updated to support the JSR 286: Upgrade Wicket Portlet Support to only use native Portlet API 2.0 . And have a look at later releases Upgrade wicket to fully support portlet 2.0 for more information. It seems to work fine in case of other portal containers like Liferay as mentioned steps Portal How To.
Lets have a look how to make it work for WS Portal. We will start with setting the environment first and will try to resolve the compatibility issues. Follow the below steps:
- Update wicket release 1.4-rc2 with patch.
- Configure WebSphere Portal to work with wicket filter
- Develop JSR 286 eventing system based wicket portlet
- Configure the portlet wiring in WS Portal
Update Wicket 1-4-rc2:
Have to look at wicket latest release 1-4-rc2 does not support IBM Websphere Portal Server 6.1 to understand the problem in case of WS Portal.
To fix it, update the jar with the patch:
Configuring WebSphere Portal Server:
It seems like WebSphere doesn’t handle the servlet filters porperly and you may get this error while deploying the wicket portlets on WebSphere 6.1: Error 404: SRVE0190E: File not found:
Setting the “com.ibm.ws.webcontainer.invokefilterscompatibility” property to true in Servers > Server > Web Container Settings > Web Container > Custom Properties, may help solve the issue.
Developing JSR 286 Wicket Portlets:
We will take JSR 86 eventing system as an example to work for wicket portlets.
Lets develop two portlets say TestPortlet and TestDetailsPortlet to publish and process events and spring integration for bean management.
Update deployment descriptor web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext.xml</param-value>
</context-param>
<context-param>
<param-name>org.apache.wicket.detectPortletContext</param-name>
<param-value>true</param-value>
</context-param>
<filter>
<filter-name>wicket.testPortlet</filter-name>
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
<init-param>
<param-name>applicationClassName</param-name>
<param-value>com.test.portlet.testproject.TestPortletApplication</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>wicket.testPortlet </filter-name>
<url-pattern>/testPortlet/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
<filter>
<filter-name>wicket.testPortletDetails</filter-name>
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
<init-param>
<param-name>applicationClassName</param-name>
<param-value>com.test.portlet.testproject.TestPortletDetailsApplication</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>wicket.testPortletDetails </filter-name>
<url-pattern>/testDetailsPortlet/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Now configure the portlet.xml :
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" xmlns:test="http://www.test.com/portlets/testing" ...
<portlet>
<description>Test Portlet</description>
<portlet-name>TestPortlet</portlet-name>
<display-name>TestPortlet</display-name>
<portlet-class>com.test.portlet.test.TestPortlet</portlet-class>
<init-param>
<name>wicketFilterPath</name>
<value>/testPortlet</value>
</init-param>
<supports>
<mime-type>*/*</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<portlet-info>
<title>Test Portlet</title>
</portlet-info>
<supported-publishing-event>
<qname>test:test_selected</qname>
</supported-publishing-event>
</portlet>
<portlet>
<description>Test Details Portlet</description>
<portlet-name>TestDetailsPortlet</portlet-name>
<display-name>TestDetailsPortlet</display-name>
<portlet-class>com.test.portlet.testdetails.TestDetailsPortlet</portlet-class>
<init-param>
<name>wicketFilterPath</name>
<value>/testDetailsPortlet</value>
</init-param>
<supports>
<mime-type>*/*</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<portlet-info>
<title>Test Details Portlet</title>
</portlet-info>
<supported-processing-event>
<qname>test:test_selected</qname>
</supported-processing-event>
</portlet>
<event-definition>
<qname>test:test_selected</qname>
<value-type>java.lang.String</value-type>
</event-definition>
Note: Put the event-definition entries in the end after all the portlet entries, cross check with portlet 2 xsd for validation.
For each portlet, we will be specifying separate application class (eg. TestPortletApplication and TestDetailsPortletApplication) where each one will have different home page (eg. TestPage and TestDetailsPage).
TestPortletApplication:
public class TestPortletApplication extends WebApplication {
@Override
protected void init() {
super.init();
addComponentInstantiationListener(new SpringComponentInjector(this));
}
@Override
public Class<? extends Page> getHomePage() {
return TestPage.class;
}
}
TestDetailsPortletApplication:
public class TestDetailsPortletApplication extends WebApplication {
@Override
protected void init() {
super.init();
addComponentInstantiationListener(new SpringComponentInjector(this));
}
@Override
public Class<? extends Page> getHomePage() {
return TestDetailsPage.class;
}
}
TestPage:
Lets say this wicket WebPage submits some value on selection/click. Here lets say
it submits some parameter “test_value” which we are using to set the event value.
TestDetailsPage:
public class TestDetailsPage extends WebPage {
@SpringBean(name = "testService")
private TestService testService;
...
public TestDetailsPage() {
//Get parameter value set by the process event and use in the wicket page
String testSelectedValue = getRequest().getParameter("test_selected_value");
....
//Do whatever you need to do, find or store.
testService.findTestDetails(testSelectedValue);
}
...
}
Update TestPortlet to publish the event:
public class TestPortlet extends WicketPortlet {
@Override
public void processAction(ActionRequest request, ActionResponse response) throws PortletException, IOException {
super.processAction(request, response);
//set the event and value, here we are getting value from request and setting as event value.
QName name = new QName("http://www.test.com/portlets/testing","test_selected");
response.setEvent(name, request.getParameter(“test_value”));
}
}
Qname is same which you mentioned in the portlet definition file for the test-selected event. And “test_value” is the parameter value which you want to pass to this event. Here in this example we will use only string values to pass otherwise it can be any serialized object.
Update TestDetailsPortlet to procees the event:
public class TestPortlet extends WicketPortlet {
@ProcessEvent(qname = "{http://www.test.com/portlets/testing}test_selected")
public void processTestSelectedEvent(EventRequest request, EventResponse response) throws PortletException, IOException {
//Do whatever you want to do with the event handling part.
response.setRenderParameter("test_selected_value", request.getEvent().getValue().toString());
}
}
Configuring Portlet Wiring:
Once you are done with the deployment, you need to wire the two portlet otherwise you will get the error:
“EJPKB0991E: The propertybroker encountered a problem finding a communication source with name…”.
Have a look at Using portlet wires for WS Portal 6.1.
To access the wiring Tool portlet, proceed as follows:
1.Access the Manage Pages portlet.
2.Locate the page for which you want to add wires.
3.Click the Edit Page Layout icon for that page. This takes you to the Edit Layout panel.
4.Click the Wires tab. You can now start working with wires.
The same example of Developing Inter Portlet communication (IPC) portlets can be achieved using the JSR 268 Public Render Parameters also but this example demonstrates how it works using the JSR 268 eventing support.
Hope this will help you to get things started on WebSphere Portal. Feel free to share your experiences and lets hope it gets fixed either by Wicket or IBM in future.