First of all, you need a Struts proyect. I created a project with the following tutorial:http://netbeans.org/kb/docs/web/quickstart-webapps-struts.html.
Also, I uploaded this project at http://www.megaupload.com/?d=9EJND8KQ
Download the project.
Extract it.
Now, we have to create a new Portlet App with Eclipse.
Copy the libraries of WEB-INF/lib with the libraries of MyStrutsApp/build/web/WEB-INF/lib
Delete commons-logging-1.0.4.jar, standard-1.0.2 and jstl-1.0.2
You may download the tld files from:http://www.megaupload.com/?d=TFVCGMM2
Also, copy struts-config.xml,tiles-defs.xml,validation.xml,validator-rules.xml from MyStrutsApp/web/WEB-INF to WEB-INF/ of your Portlet Project
Next, copy the files index.jsp, login.jsp, success.jsp of /MyStrutsApp/web in Bridge-portlet/docroot
After that, copy the libraries jstl.jar and standard.jar to Bridge-portlet/docroot/WEB-INF/lib. The libraries are uploaded in:http://www.megaupload.com/?d=MWJ0BFRQ
And refresh your Eclipse project.
Next open liferay-plugin-package.properties. Click source. Replace the code with the following code:
name=Bridge
module-group-id=liferay
module-incremental-version=1
tags=
short-description=
change-log=
page-url=http://www.liferay.com
author=Liferay, Inc.
licenses=LGPL
portal-dependency-jars=\
antlr.jar,\
commons-beanutils.jar,\
commons-collections.jar,\
commons-digester.jar,\
commons-fileupload.jar,\
commons-io.jar,\
commons-lang.jar,\
commons-validator.jar,\
jcommon.jar,\
jfreechart.jar,\
oro.jar,\
portals-bridges.jar,\
struts.jar
portal-dependency-tlds=\
struts-bean.tld,\
struts-bean-el.tld,\
struts-html.tld,\
struts-html-el.tld,\
struts-logic.tld,\
struts-logic-el.tld,\
struts-nested.tld,\
struts-tiles.tld,\
struts-tiles-el.tld
Replace liferay-portlet.xml with the following code:
<?xml version="1.0"?>
<!DOCTYPE liferay-portlet-app PUBLIC "-//Liferay//DTD Portlet Application 6.0.0//EN" "http://www.liferay.com/dtd/liferay-portlet-app_6_0_0.dtd">
<liferay-portlet-app>
<portlet>
<portlet-name>Bridge</portlet-name>
<portlet-url-class>com.liferay.portal.apache.bridges.struts.LiferayStrutsPortletURLImpl</portlet-url-class>
<use-default-template>true</use-default-template>
<restore-current-view>true</restore-current-view>
</portlet>
<role-mapper>
<role-name>administrator</role-name>
<role-link>Administrator</role-link>
</role-mapper>
<role-mapper>
<role-name>guest</role-name>
<role-link>Guest</role-link>
</role-mapper>
<role-mapper>
<role-name>power-user</role-name>
<role-link>Power User</role-link>
</role-mapper>
<role-mapper>
<role-name>user</role-name>
<role-link>User</role-link>
</role-mapper>
</liferay-portlet-app>
After that, change portlet.xml to:
<?xml version="1.0"?>
<portlet-app
version="2.0"
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"
>
<portlet>
<portlet-name>Bridge</portlet-name>
<display-name>Bridge Sample</display-name>
<portlet-class>org.apache.portals.bridges.struts.StrutsPortlet</portlet-class>
<init-param>
<name>ServletContextProvider</name>
<value>com.liferay.util.bridges.struts.LiferayServletContextProviderWrapper</value>
</init-param>
<init-param>
<name>ViewPage</name>
<value>/portlet_action/login</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<portlet-info>
<title>Bridge</title>
<short-title>NewPortlet</short-title>
<keywords></keywords>
</portlet-info>
<security-role-ref>
<role-name>administrator</role-name>
</security-role-ref>
<security-role-ref>
<role-name>guest</role-name>
</security-role-ref>
<security-role-ref>
<role-name>power-user</role-name>
</security-role-ref>
<security-role-ref>
<role-name>user</role-name>
</security-role-ref>
</portlet>
</portlet-app>
Change struts-config.xml to:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_3.dtd">
<struts-config>
<form-beans>
<form-bean name="LoginForm" type="com.myapp.struts.LoginForm" />
</form-beans>
<global-exceptions>
</global-exceptions>
<global-forwards>
<forward name="welcome" path="/Welcome.do" />
</global-forwards>
<action-mappings>
<action path="/bridge_struts_portlet/view" forward="portlet.sample_struts_portlet.view" />
<action name="LoginForm" path="/login" scope="request"
type="com.myapp.struts.LoginAction" validate="false">
<forward name="success" path="/success.jsp" />
<forward name="failure" path="/login.jsp" />
</action>
<action path="/Welcome" forward="/welcomeStruts.jsp" />
</action-mappings>
<controller
processorClass="org.apache.portals.bridges.struts.PortletTilesRequestProcessor" />
<message-resources parameter="com/myapp/struts/ApplicationResource" />
<plug-in className="org.apache.struts.tiles.TilesPlugin">
<set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml" />
<set-property property="moduleAware" value="true" />
<set-property property="definitions-parser-validate"
value="true" />
</plug-in>
<!-- ========================= Validator plugin ================================= -->
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames"
value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml" />
</plug-in>
</struts-config>
Next, change tiles-def.xml to:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/tiles-config_1_1.dtd">
<tiles-definitions>
<definition name="portlet.bridge_struts_portlet.view" >
<put name="portlet_content" value="/portlet/bridge_struts_portlet/view.jsp" />
</definition>
</tiles-definitions>
After that, open web.xml. Change the code to:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>Bridge-portlet</display-name>
<servlet>
<servlet-name>PortletActionServlet</servlet-name>
<servlet-class>com.liferay.util.bridges.struts.LiferayPortletServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>PortletActionServlet</servlet-name>
<url-pattern>/portlet_action/*</url-pattern>
</servlet-mapping>
<jsp-config>
<taglib>
<taglib-uri>http://struts.apache.org/tags-bean</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>http://portals.apache.org/bridges/struts/tags-portlet-html</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-portlet-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>http://struts.apache.org/tags-logic</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-logic.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>http://struts.apache.org/tags-nested</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-nested.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>http://struts.apache.org/tags-tiles</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-tiles.tld</taglib-location>
</taglib>
</jsp-config>
</web-app>
Now, change the code of login.jsp to:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib uri="http://portals.apache.org/bridges/struts/tags-portlet-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
<%@ taglib uri="http://struts.apache.org/tags-nested" prefix="nested" %>
<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<html:form action="/login">
<table border="0">
<tbody>
<tr>
<td colspan="2">
<bean:write name="LoginForm" property="error" filter="false"/>
</td>
</tr>
<tr>
<td><bean:message key="data.name"/></td>
<td><html:text property="name" /></td>
</tr>
<tr>
<td><bean:message key="data.email"/></td>
<td><html:text property="email" /></td>
</tr>
<tr>
<td></td>
<td><html:submit value="Login" /></td>
</tr>
</tbody>
</table>
</html:form>
</body>
</html>
Next, change the code of success.jsp to:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib uri="http://portals.apache.org/bridges/struts/tags-portlet-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login Success</title>
</head>
<body>
<c:out value="${title}"/>
<h1>Congratulations!</h1>
<p>You have successfully logged in.</p>
<p>Your name is: <bean:write name="LoginForm" property="name" />.</p>
<p>Your email address is: <bean:write name="LoginForm" property="email" />.</p>
<logic:messagesPresent message="true">
<html:messages message="true" id="msg">
<bean:write name="msg" ignore="true"/>
</html:messages>
</logic:messagesPresent>
</body>
</html>
After that, open the file loginAction.java. Set the following code:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.myapp.struts;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
/**
*
* @author santiago
*/
public class LoginAction extends org.apache.struts.action.Action {
/* forward name="success" path="" */
private static final String SUCCESS = "success";
private final static String FAILURE = "failure";
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
// extract user data
LoginForm formBean = (LoginForm)form;
String name = formBean.getName();
String email = formBean.getEmail();
ActionMessages actionMessages = new ActionMessages();
actionMessages.add(ActionMessages.GLOBAL_MESSAGE,
new ActionMessage("errors.cancel"));
saveMessages(request, actionMessages);
// perform validation
if ((name == null) || // name parameter does not exist
email == null || // email parameter does not exist
name.equals("") || // name parameter is empty
email.indexOf("@") == -1) { // email lacks '@'
formBean.setError();
return mapping.findForward(FAILURE);
}
request.setAttribute("title", "This is Test");
return mapping.findForward(SUCCESS);
}
}
Run the project.
The messages don't show in the screen. We have to replace the class MessageTag of apache. To replace the class, you have to create a new package(org.apache.struts.taglib.html) . Into the package create the class named MessagesTag with the following apache struts taglib code:
/*
* $Id: MessagesTag.java 471754 2006-11-06 14:55:09Z husted $
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.struts.taglib.html;
import org.apache.struts.Globals;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.taglib.TagUtils;
import org.apache.struts.util.MessageResources;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
import java.util.Iterator;
/**
* Custom tag that iterates the elements of a message collection. It defaults
* to retrieving the messages from <code>Globals.ERROR_KEY</code>, but if the
* message attribute is set to true then the messages will be retrieved from
* <code>Globals.MESSAGE_KEY</code>. This is an alternative to the default
* <code>ErrorsTag</code>.
*
* @version $Rev: 471754 $ $Date: 2005-11-08 23:50:53 -0500 (Tue, 08 Nov 2005)
* $
* @since Struts 1.1
*/
public class MessagesTag extends BodyTagSupport {
/**
* The message resources for this package.
*/
protected static MessageResources messageResources =
MessageResources.getMessageResources(Constants.Package
+ ".LocalStrings");
/**
* Iterator of the elements of this error collection, while we are
* actually running.
*/
protected Iterator iterator = null;
/**
* Whether or not any error messages have been processed.
*/
protected boolean processed = false;
/**
* The name of the scripting variable to be exposed.
*/
protected String id = null;
/**
* The servlet context attribute key for our resources.
*/
protected String bundle = null;
/**
* The session attribute key for our locale.
*/
protected String locale = Globals.LOCALE_KEY;
/**
* The request attribute key for our error messages (if any).
*/
protected String name = Globals.ERROR_KEY;
/**
* The name of the property for which error messages should be returned,
* or <code>null</code> to return all errors.
*/
protected String property = null;
/**
* The message resource key for errors header.
*/
protected String header = null;
/**
* The message resource key for errors footer.
*/
protected String footer = null;
/**
* If this is set to 'true', then the <code>Globals.MESSAGE_KEY</code>
* will be used to retrieve the messages from scope.
*/
protected String message = null;
public String getId() {
return (this.id);
}
public void setId(String id) {
this.id = id;
}
public String getBundle() {
return (this.bundle);
}
public void setBundle(String bundle) {
this.bundle = bundle;
}
public String getLocale() {
return (this.locale);
}
public void setLocale(String locale) {
this.locale = locale;
}
public String getName() {
return (this.name);
}
public void setName(String name) {
this.name = name;
}
public String getProperty() {
return (this.property);
}
public void setProperty(String property) {
this.property = property;
}
public String getHeader() {
return (this.header);
}
public void setHeader(String header) {
this.header = header;
}
public String getFooter() {
return (this.footer);
}
public void setFooter(String footer) {
this.footer = footer;
}
public String getMessage() {
return (this.message);
}
public void setMessage(String message) {
this.message = message;
}
/**
* Construct an iterator for the specified collection, and begin looping
* through the body once per element.
*
* @throws JspException if a JSP exception has occurred
*/
public int doStartTag() throws JspException {
// Initialize for a new request.
processed = false;
// Were any messages specified?
ActionMessages messages = null;
// Make a local copy of the name attribute that we can modify.
String name = this.name;
if ((message != null) && "true".equalsIgnoreCase(message)) {
name = Globals.MESSAGE_KEY;
}
try {
messages =
TagUtils.getInstance().getActionMessages(pageContext, name);
} catch (JspException e) {
TagUtils.getInstance().saveException(pageContext, e);
throw e;
}
// Acquire the collection we are going to iterate over
this.iterator =
(property == null) ? messages.get() : messages.get(property);
// Store the first value and evaluate, or skip the body if none
if (!this.iterator.hasNext()) {
return SKIP_BODY;
}
// process the first message
processMessage((ActionMessage) iterator.next());
if ((header != null) && (header.length() > 0)) {
String headerMessage =
TagUtils.getInstance().message(pageContext, bundle, locale,
header);
if (headerMessage != null) {
TagUtils.getInstance().write(pageContext, headerMessage);
}
}
// Set the processed variable to true so the
// doEndTag() knows processing took place
processed = true;
return (1);
}
/**
* Make the next collection element available and loop, or finish the
* iterations if there are no more elements.
*
* @throws JspException if a JSP exception has occurred
*/
public int doAfterBody() throws JspException {
// Render the output from this iteration to the output stream
if (bodyContent != null) {
TagUtils.getInstance().writePrevious(pageContext,
bodyContent.getString());
bodyContent.clearBody();
}
// Decide whether to iterate or quit
if (iterator.hasNext()) {
processMessage((ActionMessage) iterator.next());
return (1);
} else {
return (SKIP_BODY);
}
}
/**
* Process a message.
*/
private void processMessage(ActionMessage report)
throws JspException {
String msg = null;
if (report.isResource()) {
msg = TagUtils.getInstance().message(pageContext, bundle, locale,
report.getKey(), report.getValues());
if (msg == null) {
String bundleName = (bundle == null) ? "default" : bundle;
msg = messageResources.getMessage("messagesTag.notfound",
report.getKey(), bundleName);
}
} else {
msg = report.getKey();
}
if (msg == null) {
pageContext.removeAttribute(id);
} else {
pageContext.setAttribute(id, msg);
}
}
/**
* Clean up after processing this enumeration.
*
* @throws JspException if a JSP exception has occurred
*/
public int doEndTag() throws JspException {
if (processed && (footer != null) && (footer.length() > 0)) {
String footerMessage =
TagUtils.getInstance().message(pageContext, bundle, locale,
footer);
if (footerMessage != null) {
TagUtils.getInstance().write(pageContext, footerMessage);
}
}
return EVAL_PAGE;
}
/**
* Release all allocated resources.
*/
public void release() {
super.release();
iterator = null;
processed = false;
id = null;
bundle = null;
locale = Globals.LOCALE_KEY;
name = Globals.ERROR_KEY;
property = null;
header = null;
footer = null;
message = null;
}
}
Run again the project