Thursday, June 14, 2012

Spring MVC3 Portlets with Websphere Portal 7 Client Side Aggregation

This note summarises the Action ID missing issue and solution found when running Spring MVC3 portlets with Websphere Portal 7 Client Side Aggregation (CSA).

The issue can be reproduced with a simple Spring portlet as shown in below. When the form is submitted, the "This portlet is unavailable" message is displayed, and the ffdc log shows an Action ID missing error message.

<%@page
    language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1" session="false"%>
    
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>   
<%@taglib prefix="spring" uri="http://www.springframework.org/tags"%> 
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0"%>

Hello ${demoBean.message}

<portlet:actionURL var="actionURL"/>

<div>

<form:form action="${actionURL}"  method="post" modelAttribute="demoBean">
 <form:input size="20" path="message" />
 <input type="submit"/>
</form:form>  

</div>

[30/05/12 16:53:06:418 EST] 0000004e PortletInvoke W com.ibm.wps.wsrp.producer.provider.pc.waspc.impl.PortletInvokerImpl 
 newBlockingInteractionResponse Action execution refused due to a security violation. Action ID missing.
[30/05/12 16:53:06:425 EST] 0000004e WSRPEngine    E com.ibm.wps.wsrp.producer.impl.WSRPEngine performBlockInteraction 
 EJPWC1109E: Normal execution of the operation failed.
 com.ibm.wps.wsrp.exception.WSRPException: EJPWC1109E: Normal execution of the operation failed.
 at com.ibm.wps.wsrp.producer.provider.pc.waspc.impl.PortletInvokerImpl.handleActionProtection(PortletInvokerImpl.java:1083)
 at com.ibm.wps.wsrp.producer.provider.pc.waspc.impl.PortletInvokerImpl.invokePerformBlockingInteraction(PortletInvokerImpl.java:833)
 at com.ibm.wps.wsrp.producer.provider.pc.impl.PortletInvokerImpl.invokePerformBlockingInteraction(PortletInvokerImpl.java:170)
 at com.ibm.wps.wsrp.producer.impl.WSRPEngine.performBlockingInteraction(WSRPEngine.java:833)
 at oasis.names.tc.wsrp.v2.bind.WSRP_v2_Markup_Binding_SOAPImpl.performBlockingInteraction(WSRP_v2_Markup_Binding_SOAPImpl.java:213)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at com.ibm.ws.webservices.engine.dispatchers.java.JavaDispatcher.invokeMethod(JavaDispatcher.java:178)
 at com.ibm.ws.webservices.engine.dispatchers.java.JavaDispatcher.invokeOperation(JavaDispatcher.java:141)
 at com.ibm.ws.webservices.engine.dispatchers.SoapRPCProcessor.processRequestResponse(SoapRPCProcessor.java:481)
 at com.ibm.ws.webservices.engine.dispatchers.SoapRPCProcessor.processMessage(SoapRPCProcessor.java:427)
 at com.ibm.ws.webservices.engine.dispatchers.BasicDispatcher.processMessage(BasicDispatcher.java:134)
 at com.ibm.ws.webservices.engine.dispatchers.java.SessionDispatcher.invoke(SessionDispatcher.java:204)
 at com.ibm.ws.webservices.engine.PivotHandlerWrapper.invoke(PivotHandlerWrapper.java:263)
 at com.ibm.ws.webservices.engine.handlers.jaxrpc.JAXRPCHandler.invoke(JAXRPCHandler.java:153)
 at com.ibm.ws.webservices.engine.handlers.WrappedHandler.invoke(WrappedHandler.java:64)
 at com.ibm.ws.webservices.engine.PivotHandlerWrapper.invoke(PivotHandlerWrapper.java:263)
 at com.ibm.ws.webservices.engine.PivotHandlerWrapper.invoke(PivotHandlerWrapper.java:263)

Look at the portlet page html source, the form action attribute values is a Websphere Portal javascript in which the portlet action URL is encoded.

<form method="post" action="javascript:
    com.ibm.portal.csa.PortletIWidget.Z7_EIH60VH40GNPF0ITR3BKO410I2.onActionLink(
      com.ibm.portal.csa.PortletIWidget.Z7_EIH60VH40GNPF0ITR3BKO410I2.urls.url0.tokens);" 
  id="demoBean">
 <input type="text" size="20" value="" name="message" id="message">
 <input type="submit">
</form>

This solution is to add a htmlEscape attribute to the spring form tag and set its value to false to disable html escape so that the portal engine can encode the action URL correctly.

<form:form action="${actionURL}"  method="post" modelAttribute="demoBean"
 htmlEscape="false">
  ...   
</form:form>

The solution is verified in Websphere Portal 7.0.0.2 with WAS Application Server 7.0.0.21 and Spring MVC 3.1.0.

No comments:

Post a Comment