Debug the Liferay plug-in Projects from Eclipse

Debug the Liferay plug-in Projects from Eclipse

In the part 4 of the series will see how to debug the Liferay Portlet from Eclipse. Most of the developers will like to step through the code
when the rendering or action happens.

Need some changes in Tomcat and Eclipse to enable debugging. This assumes the project is deployed as an exploded war file as in Part 3.

1. Tomcat Setup, Enable debugging in the Tomcat instance for Liferay.

NOTE: This step is required if you only if you are planning to start Liferay Tomcat from command prompt by running “startup.bat”. If tomcat is started from IDE skip this step.


a. Edit the setenv.bat file at: D:\liferay-portal-5.2.3\tomcat-6.0.18\bin .Add these lines after set JRE_HOME
set JPDA_ADDRESS=5005

set JPDA_TRANSPORT=dt_socket

b. Edit the startup.bat file and add “jpda” to the last line, the file is located at, D:\liferay-portal-5.2.3\tomcat-6.0.18\bin
Edit the line call "%EXECUTABLE%" start %CMD_LINE_ARGS% , Add jpda to that so that the modified script look like

call "%EXECUTABLE%" jpda start %CMD_LINE_ARGS%

1. b. Modify VM arguments from Eclipse (If Liferay server is started from Eclipse IDE)

Double click on the server created, Click on “Open Configuration”, Select “Arguments” tab,


Add the following line to the “VM Arguments”

-Xdebug -Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=n


2. Eclipse, Configure Debugger

1. Select the menu item Project -> Run->Debug Configurations
2. Click on Remote Java Application and select New

3. Name it like say, Liferay Debugger


4. Browse and pick your Project

5. Set the port to 5005
6. Click on the Source tab and select Add
7. Pick Java Projects and select your source project(s)



8. Click Apply and Debug to start the debugger.
9. From the Eclipse IDE, add break points to the source code.

See Part 1 (Start-Stop Liferay from Eclipse) , Part 2 (Develop Spring MVC Portlet), Part 3 (Deploy to Maven)

Deploy to Liferay from a Maven Project

In the Part 3 of the series will see how to deploy to Liferay from Maven Project

For a Maven plug-in project Eclipse, the project will be built as an exploded WAR file
For a Maven project the exploded WAR will be under “target” directory.
Ex; E:\MyWorkspace\adx-portlet\target

1. Create a portlet context file with the same name as your portlet in Eclipse. Liferay uses this context file in its hot deploy feature: If the Portlet name is Hello, xml will be
E:\MyWorkspace\adx-portlet\Hello.xml

Add the following to this file:

<?xml version="1.0" encoding="UTF-8"?>
<Context path="mypath"
docBase="E:/MyWorkspace/hello-portlet/target/adxportal"></Context>

2, Liferay’s has the auto-deploy feature .Create an Ant task that copies this file out to the Liferay deploy directory. Create the following Ant task and add to your build.xml or create a new build.xml for it in the base directory (E:/MyWorkspace/adx-portlet/build.xml).

<?xml version="1.0"?>
<project name = "HelloWorldPortlet" default="redeploy-my-portlet" basedir=".">
<target name="redeploy-to-Liferay">
<copy file="E:/MyWorkspace/ hello -portlet/ Hello.xml" todir="D:/liferay-portal-5.2.3/deploy"/>
</target></project>

E:/MyWorkspace/adx-portlet/target/adxportal , this is the path where the contents of the WAR is in the exploded form.

3. Run the Ant Script
Keep the Liferay running and run the Ant script which will deploy the Plugin Portlet in Liferay as an exploded WAR File

This way Liferay will run class files from with in the Eclipse workspace which will help in debugging. This will be explained in the last part of the series.

See Part 1 (Start-Stop Liferay from Eclipse) and Part 2 (Develop Spring MVC Portlet)

Spring MVC Portlet on Liferay


Continuing my post of Liferay this the Part 2 of the series, developing a Spring MVC portlet on Liferay.

1.Spring MVC Portlet


From version 2.0, Spring Framework ships with Portlet MVC Framework, which is a replica of its Web MVC Framework which can be used for developing JSR-168-compliant portlet applications.

2.Advantages

* Portlets Portlet MVC Framework developed can be deployed in any JSR-168-compliant portlet container without making any changes. IBM Frameworks (Struts/JSF) have a dependency on IBM WebSphere Portal runtime.


* The portlet’s two phase request processing is handled by providing an interface which defines handleActionRequest() and handleRenderRequest() methods.

* Spring Portlet MVC Framework provides easy integration with popular view-rendering technologies such as JSTL, Apache Tiles, Apache Velocity, and FreeMarker.


* Provides a testing framework that you can use for test-driven development of your portlet.


3. Maven Project Setup

Spring POM dependency for will be like

<properties>
<spring.version>3.0.0.RELEASE</spring.version>
</properties>

Spring dependency,

<dependency>
<groupId>org.springframework</groupId>
<artifactId>org.springframework.jdbc</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>org.springframework.orm</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>org.springframework.web</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>org.springframework.web.servlet</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc-portlet</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>org.springframework.js</artifactId>
<version>2.0.8.RELEASE</version>
</dependency>
<dependency>

<groupId>org.springframework.security</groupId>
<artifactId>org.springframework.security.web</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>org.springframework.security.config</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>org.springframework.security.taglibs</artifactId>
<version>${spring.version}</version>
</dependency>

4. Developing Portlet

4.1 Developing portlet.xml


1. Create the portlet.xml file in the /src/main/webapp/WEB-INF/ folder

<?xml version="1.0" encoding="UTF-8"?>
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"
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>Books</portlet-name>
<portlet-class>org.springframework.web.portlet.DispatcherPortlet</portlet-class>
<init-param>
<name>contextConfigLocation</name>
<value>/WEB-INF/context/portlet/adx-controller-mappings.xml</value>
</init-param>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<resource-bundle>messages</resource-bundle>
</portlet>
</portlet-app>

DispatcherPortlet is responsible for handling every client request. When it receives a request, it finds out which Controller class should be used for handling this request, and then it calls its handleActionRequest() or handleRenderRequest() method based on the request processing phase. The Controller class executes business logic and returns a View name that should be used for rendering markup to the user. The DispatcherPortlet then forwards control to that View for actual markup generation.

DispatcherPortlet is the central dispatcher for use within Spring Portlet MVC Framework. A portlet application can define more than one DispatcherPortlet. Each of these portlets operates its own namespace, loading its application context and handler mapping.

The DispatcherPortlet is also responsible for loading application context (Spring configuration file) for this portlet. First, it tries to check the value of the configLocation portlet initialization parameter. If that parameter is not specified, it takes the portlet name (that is, the value of the <portlet-name> element <portlet-name>Books</portlet-name>), appends-portlet.xml to it, and tries to load that file from the /WEB-INF folder;Books-portlet.xml in this case.

But in the example contextConfigLocation is mentioned, so any name can be defined. <name>contextConfigLocation</name><value>/WEB-INF/context/portlet/adx-controller-mappings.xml</value>

Also create a bundle messages.properties with values for Portlet title, key word etc. Once deployed this file should go inside the classes folder.
Ex: messages.properties
javax.portlet.title=SOME NAME
javax.portlet.short-title=SOME NAME
javax.portlet.keywords=key1

4.2 Developing the Controller class

Spring 2.5 introduces an annotation-based programming model for MVC controllers, using annotations such as @RequestMapping, @RequestParam, @ModelAttribute, etc. This annotation support is available for both Servlet MVC and Portlet MVC. Controllers implemented in this style do not have to extend specific base classes or implement specific interfaces

The @Controller annotation indicates that a particular class serves the role of a controller. There is no need to extend any controller base class or reference the Portlet API.

The @RequestMapping annotation is used to map portlet modes like 'VIEW'/'EDIT' onto an entire class or a particular handler method

@RequestMapping at the type level may be used for plain implementations of the Controller interface as well. In this case, the request processing code would follow the traditional handle(ActionRender)Request signature, while the controller's mapping would be expressed through an @RequestMapping annotation



The code here shows annotation at the method level.

@Controller

public class AdxController {

/**

* @param request

* @param response

* @throws Exception

*/

public void handleActionRequest(ActionRequest request,

ActionResponse response) throws Exception {

System.out.println("handleActionRequest >>");

}

/**

* @param request

* @param response

* @return

* @throws Exception

*/

@RequestMapping("view")

public ModelAndView handleRenderRequest(RenderRequest request,

RenderResponse response) throws Exception {

Map<String, Object> model = new HashMap<String, Object>();

model.put("helloWorldMessage", "List of Books");

return new ModelAndView("displayBooks", model);
}
}

4.3 Developing the mapping for Controller class

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
<bean class="org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="order" value="10" />
</bean>

<!--Adx Controllers -->
<bean id="adxController" class="lab.liferay.AdxController" />
<bean id="portletModeHandlerMapping"
class="org.springframework.web.portlet.handler.PortletModeHandlerMapping">
<property name="portletModeMap">
<map>
<entry key="view">
<ref bean="adxController" />
</entry>
</map>
</property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.InternalResourceView" />
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
adxController: bean definition

portletModeHandlerMapping: The PortletModeHandlerMapping class is a simple implementation of the HandlerMapping interface and is used by DispatcherPortlet to find a suitable Controller for every request. The PortletModeHandlerMapping class uses Portlet mode for the current request to find a suitable Controller class to use for handling the request. The portletModeMap property of portletModeHandlerMapping bean is the place where we map the Portlet mode name against the Controller class.

Here adxController is responsible for handling View mode requests

4.4 Developing web.xml

According to Portlet Specification 1.0, every portlet application is also a Servlet Specification 2.3-compliant Web application, and it needs a Web application deployment descriptor (that is, web.xml).

Main configurations in web.xml

* ViewRendererServlet. The ViewRendererServlet is acting as the bridge servlet for portlet support. During the render phase, DispatcherPortlet wraps PortletRequest into ServletRequest and forwards control to ViewRendererServlet for actual rendering. ContextLoaderListener. The


* ContextLoaderListener class takes care of loading Web application context at the time of the Web application startup. The Web application context is shared by all the portlets in the portlet application. Default location is /WEB-INF/applicationContext.xml.


<?xml version="1.0"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>view-servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.ViewRendererServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>view-servlet</servlet-name>
<url-pattern>/WEB-INF/servlet/view</url-pattern>
</servlet-mapping>
</web-app>

4.5 applicationcontext.xml

Spring beans can be defined here.

Now the application is ready for deployment. But to deploy in liferay 2 more xml’s to be configured, liferay-portlet.xml and liferay-display.xml

5. Configuring the application for Liferay

5.1 liferay-portlet.xml

This xml defines the portlets. Portlet name is defined using portlet-name tag. <portlet-name>Books</portlet-name>.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE liferay-portlet-app PUBLIC "-//Liferay//DTD Portlet Application 5.2.0//EN" "http://www.liferay.com/dtd/liferay-portlet-app_5_2_0.dtd">
<liferay-portlet-app>
<portlet>
<portlet-name>Books</portlet-name>
<instanceable>true</instanceable>
</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>

5.2 liferay-display.xml

Here the category under which the portlets in the application must be grouped is defined. By default the portlets will come under “Samples”. As in the example the Portlet Books will come under “My Spring Portlet” category.

<?xml version="1.0"?>
<display>
<category name=" My Spring Portlet">
<portlet id="Books" />
</category>
</display>

See Part 1 (Start-Stop Liferay from Eclipse) and Part 3 (Deploy from Maven Project)



Start and stop Liferay from Eclipse

When started the work on Liferay initial issue faced is setting up the development environment in Eclipse.

This is part 1 of the series on my developement experience with Liferay.

Let me start with how add liferay runtime in Eclipse and start /stop liferay from Eclipse IDE

Liferay installation is liferay-portal-5.2.3 and Eclipse version is Eclipse Java EE IDE for Web Developers

1. Go to Windows ->Preferences

2. Select Server -> Runtime Environments, Click on “Add”,
Select Apache Tomcat v6.0 , Click Next

3. Give name for the Runtime,
Give the Tomcat Installation Directory, Browse up to the Tomcat Folder in
the Liferay installation, ex, D:\liferay-portal-5.2.3\tomcat-6.0.18
Make sure the Select the JRE and Java 5 or Java 6.
Click “Finish”.

4. On the Server Console of Eclipse, Click New -> Server

5. On the window opened,
Give Server Name: ex, Tomcat For Liferay
Server Runtime Environment: From the drop down select the Runtime
created for Liferay as in Step 5.

6. Double Click on the server created.
a. Under Server Locations, Select “Use Tomcat”
b. Edit Deploy path, give the value “webapps”

7. Edit VM arguments

a.Click on “Open Configuration” in the server configuration.
b. Select the “Arguments” tab

Add the following values,

-Xms128m -Xmx512m -XX:MaxPermSize=128m
-Djava.io.tmpdir="D:\liferay-portal-5.2.3\tomcat-6.0.18\temp"
-Djava.security.auth.login.config="D:\liferay-portal-5.2.3\tomcat-6.0.18\conf\jaas.config"

-Dfile.encoding=UTF8
-Duser.timezone=GMT+1