
Developing Struts-based Portlets
Table of Contents [-]
Introduction #
Lots of developers want to get StrutsPortlet working on Liferay portal. Here are the steps you have to follow in order to develop your own Struts based portlet. This however is not 100% truly JSR168 compliant as this depends on StrutsPortlet class of liferay is only recommended for development in the ext environment.
Prerequisites- #
This document assumes that you have setup your extension environment. If you want to make your portlets deployable as web-apps, you can study the sample_struts_portlet available in the /portal/portlets folder in the Liferay source distribution. To get Struts .war applications to work, follow the instructions in the article about How to access the full Liferay API from a portlet application.
Steps #
For the ext environment follow these steps:
1. Create a folder called test_struts_portlet under {EXTN_HOME}\ext-web\docroot\html\portlet\
2. Add init.jsp into this folder; this file will have most of the imports. Following is the code for init.jsp
<%@ include file="/html/portlet/init.jsp" %>
Note that this step is not mandatory, but it follows the guidelines set by the portlets bundled with Liferay. If it is your first StrutsPortlet we recommend that you follow this and other suggestions next. Afterwards you can decide to develop your own guidelines.
3. Add a simple JSP called view.jsp into test_struts_portlet folder. copy and paste following code into the JSP page.
<%@ include file="/html/portlet/test_struts_portlet/init.jsp" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My First Struts Portlet</title> </head> <body> <form action="<portlet:actionURL windowState="<%= WindowState.MAXIMIZED.toString() %>"> <portlet:param name="struts_action" value="/test_struts_portlet/say_hello" /> </portlet:actionURL>" method="post" name="<portlet:namespace />fm"><br /> <table border="0" cellpadding="0" cellspacing="0"> <tr> <td valign="top"><%= LanguageUtil.get(pageContext, "your_name") %></td> <td style="padding-left: 10px;"></td> <td><input type="text" name="guest_name"/></td> </tr> <tr> <td colspan="3"><button type="submit" name="<%= LanguageUtil.get(pageContext, "submit_button") %>"/></td> </tr> </table> </form> </body> </html>
4. Modify portlet-ext.xml file to add Struts portlet entry into it. Copy and paste following code into portlet-ext.xml
<portlet> <portlet-name>EXT_4</portlet-name> <display-name>Struts Sample Portlet</display-name> <portlet-class>com.liferay.portlet.StrutsPortlet</portlet-class> <init-param> <name>view-action</name> <value>/test_struts_portlet/view</value> </init-param> <expiration-cache>300</expiration-cache> <supports>text/html</supports> <portlet-info> <title>Struts Sample Portlet</title> </portlet-info> <resource-bundle>com.liferay.portlet.StrutsResourceBundle</resource-bundle> <security-role-ref> <role-name>Power User</role-name> </security-role-ref> <security-role-ref> <role-name>User</role-name> </security-role-ref> </portlet>
5. Add following line into struts-config.xml for mapping action with a view page
<action path="/test_struts_portlet/view" forward="portlet.struts.test.view"/>
6. Add following lines into tiles-def.xml. Make sure that forward from struts-config.xml and definetion name are exactly same
<definition name="portlet.struts.test.view" extends="portlet"> <put name="portlet_content" value="/portlet/test_struts_portlet/view.jsp"/> </definition>
7. Edit liferay-portlet-ext.xml file and add our new portlet entry into it.
<portlet> <portlet-name>EXT_4</portlet-name> <struts-path>test_struts_portlet</struts-path> <use-default-template>false</use-default-template> </portlet>
IMPORTANT: When developing with Liferay's StrutsPortlet, you need to ensure that the struts-path above equals the substring between the first and last slash of every Struts action-mapping defined in your struts-config.xml (step 5). The reason for this is to prevent URL manipulation. For instance, imagine that a regular user sees that he can delete a user by using the struts-config mapping of "/enterprise_admin/edit_user". Liferay looks at the struts_action parameter passed in the querystring, takes the substring of the first and last slash, and then maps it to the portlet-name by matching the substring to the struts-path (in this case Enterprise Admin portlet 79). When the portal sees that the regular user does not have access to the Enterprise Admin portlet, the user will be returned a security exception.
8. Now edit liferay-display.xml file to add the category where this newly developed portlet must go. We will enter newly created portlet into test category by adding <portlet id="EXT_4" /> line along with others
<category name="category.test"> <portlet id="47" /> <portlet id="48" /> <portlet id="50" /> <portlet id="53" /> <portlet id="66" /> <portlet id="69" /> <portlet id="EXT_1" /> <portlet id="EXT_4" /> </category>
9. Create a package called com.liferay.portlet.struts.test in {EXTN_HOME}\ext-ejb. Add new class called SayHelloAction which extends PortletAction in to this package. Write a method called processAction() in this class. Following is the code for processAction() method
public void processAction(ActionMapping mapping, ActionForm form, PortletConfig config, ActionRequest req, ActionResponse res) throws Exception {<br/> String userName = ParamUtil.getString(req, "guest_name"); PortletSession session = req.getPortletSession(); session.setAttribute("guest_name", userName); setForward(req, "portlet.struts.test.say.hello"); }
10. Now Make sure that you add respective struts-config.xml entry for the action.
<action path="/test_struts_portlet/say_hello" type="com.liferay.portlet.struts.test.SayHelloAction"> <forward name="portlet.struts.test.say.hello" path="portlet.struts.test.say.hello"/> </action>
11. add another entry into tiles-defs.xml for the forward mapping
<definition name="portlet.struts.test.say.hello" extends="portlet"> <put name="portlet_content" value="/portlet/test_struts_portlet/hello.jsp"/> </definition>
12. create hello.jsp and with in this JSP access the session attribute and get the guest name and display it on to page.
13. Run deploy from build.xml located at the root folder of extension environment.