<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Lý Minh Phương Blog</title>
	<atom:link href="http://lyphuong10.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://lyphuong10.wordpress.com</link>
	<description>tháng 07.2010</description>
	<lastBuildDate>Mon, 07 Nov 2011 03:48:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='lyphuong10.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Lý Minh Phương Blog</title>
		<link>http://lyphuong10.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://lyphuong10.wordpress.com/osd.xml" title="Lý Minh Phương Blog" />
	<atom:link rel='hub' href='http://lyphuong10.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Liferay Portal 4 &#8211; Portlet development guide</title>
		<link>http://lyphuong10.wordpress.com/2011/08/10/liferay-portal-4-portlet-development-guide/</link>
		<comments>http://lyphuong10.wordpress.com/2011/08/10/liferay-portal-4-portlet-development-guide/#comments</comments>
		<pubDate>Wed, 10 Aug 2011 13:34:07 +0000</pubDate>
		<dc:creator>lyphuong10</dc:creator>
				<category><![CDATA[Web JSP Servlet]]></category>

		<guid isPermaLink="false">http://lyphuong10.wordpress.com/?p=127</guid>
		<description><![CDATA[Copyright © 2000, 2007 Liferay Inc. Revision History Revision 1.0 December 20th, 2006 Table of Contents Preface 1. Introduction 1. Portlet Development vs Servlet Development 2. Java Portlet Specification (JSR-168) 3. Recommended Tools 3.1. JDK 1.5.0 or JDK 1.4.2 3.2. Jikes 1.22 or Jikes 1.21 3.3. Ant 1.6.5 3.4. Subversion or a Similar Version Control [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=127&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<div>
<p>Copyright © 2000, 2007 Liferay Inc.</p>
</div>
<div>
<div>
<table summary="Revision history" width="100%" border="1">
<tbody>
<tr>
<th colspan="2" align="left" valign="top"><strong>Revision History</strong></th>
</tr>
<tr>
<td align="left">Revision 1.0</td>
<td align="left">December 20th, 2006</td>
</tr>
</tbody>
</table>
</div>
</div>
<hr />
<div>
<p><strong>Table of Contents<span id="more-127"></span></strong></p>
<dl>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e38">Preface</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e77">1. Introduction</a></dt>
<dd>
<dl>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e84">1. Portlet Development vs Servlet Development</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e117">2. Java Portlet Specification (JSR-168)</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e132">3. Recommended Tools</a></dt>
<dd>
<dl>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e139">3.1. JDK 1.5.0 or JDK 1.4.2</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e152">3.2. Jikes 1.22 or Jikes 1.21</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e173">3.3. Ant 1.6.5</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e189">3.4. Subversion or a Similar Version Control System</a></dt>
</dl>
</dd>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e200">4. Portlet development environments</a></dt>
</dl>
</dd>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e227">2. Liferay Specific Descriptors</a></dt>
<dd>
<dl>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e235">1. Extended Portlet Definition</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e496">2. Organizing Portlets in Categories</a></dt>
</dl>
</dd>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e508">3. Liferay Portlet Frameworks</a></dt>
<dd>
<dl>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e523">1. Writing a Simple JSPPortlet</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e658">2. StrutsPortlet Tutorial</a></dt>
<dd>
<dl>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e666">2.1. Writting a Very Simple Struts Portlet</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1110">2.2. Adding an action</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1564">2.3. Conclusion</a></dt>
</dl>
</dd>
</dl>
</dd>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1569">4. Portlet deployment</a></dt>
<dd>
<dl>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1574">1. Liferay Hot Deploy</a></dt>
<dd>
<dl>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1579">1.1. Layout Templates, Portlets and Themes</a></dt>
</dl>
</dd>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1610">2. Manual Deployment</a></dt>
</dl>
</dd>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1620">5. Liferay Services</a></dt>
<dd>
<dl>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1629">1. Security and Permissions Service</a></dt>
<dd>
<dl>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1634">1.1. Introduction</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1639">1.2. Overview</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1657">1.3. Implementing Permissions</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e2192">1.4. Summary</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e2202">1.5. Information</a></dt>
</dl>
</dd>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e2305">2. User service</a></dt>
</dl>
</dd>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e2328">6. Conclusions</a></dt>
</dl>
</div>
<div lang="en">
<div>
<div>
<div>
<h2><a name="d0e38"></a>Preface</h2>
</div>
</div>
</div>
<p><strong>Intended audience. </strong>This document is intended for developers that want to develop portlets that will be deployed in Liferay Portal. As Liferay supports the portlet specification (JSR-168), any portlet developed according to that standard will work.</p>
<p><strong>Liferay version. </strong>This guide has been written for Liferay 4. Some details might be different for previous versions. Do not expect it to be accurate for even older versions.</p>
<p><strong>Related documents. </strong>If this is not what you are looking for consider the following related documents</p>
<div>
<ul>
<li>Liferay Portal 4 &#8211; Customization Guide</li>
<li>Liferay Portal 4 &#8211; Portal Users Guide</li>
<li>Liferay Portal 4 &#8211; Development in the Extension Environment</li>
</ul>
</div>
<p><strong>More information and support. </strong>If you are looking for help for a specific issue we invite you to use our community forums: <a href="http://forums.liferay.com/" target="_top">http://www.liferay.com/web/guest/devzone/forums</a> to ask your questions. We also offer professional support services (<a href="mailto:support@liferay.com" target="_top">support@liferay.com</a>) where your company will be assigned a Liferay developer ensuring your questions are answered promptly so that your project is never compromised. Purchased support always gets first priority. This business model allows us to build a company that can contribute a great portal to the open source community. If your company uses Liferay, please consider purchasing support. Liferay has an extremely liberal license model (MIT, very similar to Apache and BSD), which means you can rebundle Liferay, rename it, and sell it under your name. We believe free means you can do whatever you want with it. Our only source of revenue is from professional support and consulting.</p>
</div>
<div lang="en">
<div>
<div>
<div>
<h2><a name="d0e77"></a>Chapter 1. Introduction</h2>
</div>
</div>
</div>
<div>
<p><strong>Table of Contents</strong></p>
<dl>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e84">1. Portlet Development vs Servlet Development</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e117">2. Java Portlet Specification (JSR-168)</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e132">3. Recommended Tools</a></dt>
<dd>
<dl>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e139">3.1. JDK 1.5.0 or JDK 1.4.2</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e152">3.2. Jikes 1.22 or Jikes 1.21</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e173">3.3. Ant 1.6.5</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e189">3.4. Subversion or a Similar Version Control System</a></dt>
</dl>
</dd>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e200">4. Portlet development environments</a></dt>
</dl>
</div>
<p>This guide covers the Liferay specific deployment description and explains the tools, additional features and services that Liferay Portal offers to developers of portlets. A portlet is a web application that follows a set of conventions that allow portals to manage its lifecycle and integrate them with other portlets.</p>
<p>The following sections provide an introduction to the development of portlets and the environment recommended for this task.</p>
<div lang="en">
<div>
<div>
<div>
<h2><a name="d0e84"></a>1. Portlet Development vs Servlet Development</h2>
</div>
</div>
</div>
<p>Developing a Java Portlet is similar to the process of developing a Servlet based web applications. The main differences are:</p>
<div>
<ul>
<li>The portlet only produces a fragment of the final HTML and not the full markup. The portal will join the fragments of several portlets and will create the full page returned to the user.</li>
<li>The class receiving the requests has to inherit from javax.portlet.Portlet instead of javax.servlet.http.HttpServlet.</li>
<li>A portlet request may involve a two phase process:
<div>
<ol type="1">
<li>On each request at most one portlet will be able to perform an state-changing operation. This is referred to as the Action phase and is implemented through a method called <code>processAction</code>. Not always an action phase is needed. Requests that involved an action phase are invoked to an URL known as an ActionURL, while those that only have a render phase are invoked through a RenderURL.</li>
<li>Next is the render phase where all other portlets related to the page that is going to be returned may be called in any order to produce the HTML fragment to draw themselves. Portlet implement this functionality through a method called <code>render</code>.</li>
</ol>
</div>
</li>
<li>Existing web application development frameworks such as Struts, JSF, Webworks, etc can be used through the use of Bridges. Other existing frameworks have been adapted to be usable directly without the need of a bridge. An example is the Spring Portlet MVC framework.</li>
</ul>
</div>
<p>A portlet container is a server side software component that is capable of running portlets. A portal is a web application that includes a portlet container and may offer additional services to the user. Liferay Portal includes its own portlet container and offers lots of functionalities such as user and organization administration, creation of virtual communities, having pages based on portlet layouts, graphical selection of portlets and drag&amp;drop to place them, grouping pages into websites, several bundled ready-to-use portlets, and much more.</p>
</div>
<div lang="en">
<div>
<div>
<div>
<h2><a name="d0e117"></a>2. Java Portlet Specification (JSR-168)</h2>
</div>
</div>
</div>
<p>The Java platform provides an standard referred to as JSR-168 that standarizes how portlets interact with portlet containers and ensures compatibility across different portal products as long as portlet adheres to the standard. Liferay Portal provides a 100% compatible portlet container that guarantees that any portlet that adheres to the standard specification will be able to run within Liferay.</p>
<p>In JSR-168 a portlet application may aggregate several different portlets and is packed in a WAR file just as a standard Java web application. The portlets of the application are defined in a file called <code>portlet.xml</code> that is placed in the <code>WEB-INF</code> directory inside the WAR file. This file can be seen as an extension to the web.xml defined in the Java Servlet Specification. The Java Portlet specification allows portlet containers</p>
<p>For more information related to JSR-168 it is recommended to read the specification itself. Also several articles introducing development of JSR-168 portlets and explaining how to use several portlet frameworks are available online.</p>
</div>
<div lang="en">
<div>
<div>
<div>
<h2><a name="d0e132"></a>3. Recommended Tools</h2>
</div>
</div>
</div>
<p><a name="chapter1-development-environment"></a>The following instructions will help you get your development environment ready for working with the source code. These instructions are specific to setting up for deployment to Orion server and Tomcat 5.5 developing with Java JDK 1.5. Liferay Portal is compatible with Java 1.4 also and a wide array of application servers and containers. You will need to adjust your development environment according to your platform.</p>
<p>Before we can get started, the following components must be installed on your machine.</p>
<div lang="en">
<div>
<div>
<div>
<h3><a name="d0e139"></a>3.1. JDK 1.5.0 or JDK 1.4.2</h3>
</div>
</div>
</div>
<div>
<ol type="1">
<li>Download and install <a href="http://java.sun.com/j2se/1.5.0/download.jsp" target="_top">JDK 1.5.0</a>. JDK 1.4 is also supported.</li>
<li>Set an environment variable called JAVA_HOME to point to your JDK directory.</li>
</ol>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h3><a name="d0e152"></a>3.2. Jikes 1.22 or Jikes 1.21</h3>
</div>
</div>
</div>
<p>Jikes is a Java compiler by IBM that is much faster than the original one provided by the JDK.</p>
<div>
<ol type="1">
<li>Download and unzip <a href="http://www-124.ibm.com/developerworks/oss/jikes" target="_top">Jikes 1.22</a>. If using JDK 1.4 you have to use Jikes 1.21 instead.</li>
<li>Set an environment variable called JIKES_HOME to point to your Jikes directory.</li>
<li>Add <em><code>JIKES_HOME\bin</code></em> to your PATH environment variable.</li>
</ol>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h3><a name="d0e173"></a>3.3. Ant 1.6.5</h3>
</div>
</div>
</div>
<div>
<ol type="1">
<li>Download and unzip the latest version of <a href="http://ant.apache.org/" target="_top">Ant</a>.</li>
<li>Set an environment variable called ANT_HOME to point to your Ant directory.</li>
<li>Add ANT_HOME\bin to your PATH environment variable.</li>
</ol>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h3><a name="d0e189"></a>3.4. Subversion or a Similar Version Control System</h3>
</div>
</div>
</div>
<p>We recommend that you put all your code and configuration files into a version control system. Subversion is free and open source and can be used through a set of commands, by installing a subversion client such as <a href="http://www.smartsvn.com/" target="_top">SmartSVN</a>, <a href="http://tortoisesvn.net/" target="_top">TortoiseSVN</a> or through the integration mechanisms provided by most IDEs.</p>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h2><a name="d0e200"></a>4. Portlet development environments</h2>
</div>
</div>
</div>
<p>Portlets for Liferay can be developed using general tools or Liferay specific tools. Here is a list of the most common options:</p>
<div>
<dl>
<dt>Using an IDE that supports portlet development</dt>
<dd>Increasingly IDEs are providing tools for developing portlets. This is usually a good option for rapid application development, mainly if you already have the knowledge set of that tool. In this case the IDE must allow adding Liferay specific descriptors as explained in chapter 3. The result provided by the IDE must be a WAR file that can be deployed to Liferay using the method described in Chapter 4.</p>
</dd>
<dt>Creating an custom environment</dt>
<dd>Using tools such as ant or maven it&#8217;s not difficult to create an environment to create portlet applications that are packaged as WAR and deployed by copying that file to the autodeploy directory in a Liferay installation.</p>
</dd>
<dt>Using Liferay&#8217;s development environment</dt>
<dd>This environment provides a ready to use ant based system for developing portlets and customizing Liferay Portal in general. It is the option that gives most flexibility and access to all Liferay specific APIs. Use this environment if you want to use the portlet frameworks provided by Liferay such as JSPPortlet and StrutsPortlet described in chapter 3. For detailed information about this environment read <em>Liferay Portal 4 &#8211; Development in the Extension Environment</em>.</p>
</dd>
</dl>
</div>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h2><a name="d0e227"></a>Chapter 2. Liferay Specific Descriptors</h2>
</div>
</div>
</div>
<div>
<p><strong>Table of Contents</strong></p>
<dl>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e235">1. Extended Portlet Definition</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e496">2. Organizing Portlets in Categories</a></dt>
</dl>
</div>
<p>Liferay Portal has two specific deployment descriptors that extend the functionality provided by the <code>portlet.xml</code> file. One of them provides the ability to use Liferay specific features and the second one permits the configuration of the UI that will allow users to select the portlets. The next sections describe both of them.</p>
<div lang="en">
<div>
<div>
<div>
<h2><a name="d0e235"></a>1. Extended Portlet Definition</h2>
</div>
</div>
</div>
<p>The file <code>liferay-portlet.xml</code> may be placed in the <code>WEB-INF</code> directory of any portlet application to configure Liferay Portal specific features. Following is an example of what this file may look like:</p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;!DOCTYPE liferay-portlet-app PUBLIC "-//Liferay//DTD Portlet Application 4.2.0//EN" "http://www.liferay.com/dtd/liferay-portlet-app_4_2_0.dtd"&gt;

&lt;liferay-portlet-app&gt;
	&lt;portlet&gt;
		&lt;portlet-name&gt;1&lt;/portlet-name&gt;
		&lt;struts-path&gt;mail&lt;/struts-path&gt;
		&lt;preferences-unique-per-layout&gt;false&lt;/preferences-unique-per-layout&gt;
		&lt;preferences-owned-by-group&gt;false&lt;/preferences-owned-by-group&gt;
		&lt;use-default-template&gt;false&lt;/use-default-template&gt;
		&lt;restore-current-view&gt;false&lt;/restore-current-view&gt;
		&lt;maximize-edit&gt;true&lt;/maximize-edit&gt;
		&lt;private-request-attributes&gt;false&lt;/private-request-attributes&gt;
		&lt;render-weight&gt;0&lt;/render-weight&gt;
	&lt;/portlet&gt;
...
&lt;/liferay-portlet-app&gt;</pre>
<p>The <code>portlet-name</code> element must be equal to the portlet name specified in the <code>portlet.xml</code> file. Here is a complete list of all the available options.</p>
<div>
<dl>
<dt>struts-path</dt>
<dd>This option is only useful when using the Liferay StrutsPortlet framework. Suppose the struts-path value is &#8220;mail&#8221;. This tells the portal that all requests with the path mail/* are considered part of this portlet&#8217;s scope. Users who request paths that match mail/* will only be granted access if they also have access to this portlet. This is true for both portlet requests and regular servlet requests.</p>
</dd>
<dt>configuration-path</dt>
<dd>The configuration-path value is a Struts path that allows users to configure the portlet at runtime. The Struts path must reference a class that extends com.liferay.portal.struts.PortletAction.</p>
</dd>
<dt>indexer-class</dt>
<dd>The indexer-class value must be a class that implements <code>com.liferay.util.lucene.Indexer</code> and is called to create or update a search index for the portlet.</p>
</dd>
<dt>scheduler-class</dt>
<dd>The scheduler-class value must be a class that implements <code>com.liferay.portal.job.Scheduler</code> and is called to schedule Quartz jobs for this portlet.</p>
</dd>
<dt>portlet-url-class</dt>
<dd>The portlet-url-class value must be a class that extends <code>com.liferay.portlet.PortletURLImplWrapper</code>. Set this class to override the default portlet URL implementation.</p>
</dd>
<dt>portlet-url-class</dt>
<dd>The portlet-url-class value must be a class that implements <code>com.liferay.portal.servlet.FriendlyURLPortletPlugin</code>. Use this if content inside a portlet needs to have a friendly URL. See the Message Boards portlet source code for an example of its uses.</p>
</dd>
<dt>portlet-data-handler-class</dt>
<dd>The portlet-data-handler-class value must be a class that implements <code>com.liferay.portal.kernel.lar.PortletDataHandler</code> and is called when archiving tasks are run.</p>
</dd>
<dt>smtp-message-listener-class</dt>
<dd>The smtp-message-listener-class value must be a class that implements <code>com.liferay.portal.kernel.smtp.MessageListener</code> and is called when processing emails.</p>
</dd>
<dt>preferences-company-wide</dt>
<dd>Set the preferences-company-wide value to true if the preferences for the portlet are across the entire company. Setting this value to true means the value for preferences-unique-per-layout and preferences-owned-by-group are not used. The default value is false.</p>
<p>For example, an administrator could set the preferences to an Announcements portlet that would save a message in the portlet&#8217;s preferences. This message would then be used across all pages for that company. The portlet must not be instanceable because instanceable portlets have uniquely generated portlet ids.</p>
<p>The default behavior of the bundled Announcements portlet sets the instanceable value to true so that normal users cannot create company wide messages. A future release would include permissions for the edit mode versus the view mode which would allow an administrator to set the message while users would just view the message.</p>
</dd>
<dt>preferences-unique-per-layout</dt>
<dd>Set the preferences-unique-per-layout value to true if the preferences for the portlet are unique for each page. If set to false, the preferences for the portlet are shared across all pages. The default value is true.</p>
<p>The preferences-unique-per-layout element is used in combination with the preferences-owned-by-group element. See the comments for the preferences-owned-by-group element for more information.</p>
</dd>
<dt>preferences-owned-by-group</dt>
<dd>Set the preferences-owned-by-group value to true if the preferences for the portlet are owned by the group when the portlet is shown in a group page. If set to false, the preferences are owned by the user at all times. The default value is true.</p>
<p>Suppose the Stocks portlet has preferences-unique-per-layout set to true and preferences-owned-by-group set to false. Users can set a different list of stocks for every personal page. Users can set a different list of stocks for every community page.</p>
<p>Suppose the Stocks portlet has preferences-unique-per-layout set to false and preferences-owned-by-group set to false. Users can set one list of stocks to be shared across all personal pages. Users can set one list of stocks to be shared across a community&#8217;s set of pages.</p>
<p>Suppose the Stocks portlet has preferences-unique-per-layout set to true and preferences-owned-by-group set to true. Users can set a different list of stocks for every personal page. Administrators set the portlet preferences for users in a community page. Administrators can set a different list of stocks for every community page that are then shared by all users within a community.</p>
<p>Suppose the Stocks portlet has preferences-unique-per-layout set to false and preferences-owned-by-group set to true. Users can set one list of stocks to be shared across all personal pages. Administrators set the portlet preferences for users in a community page. Administrators can set one list of stocks to be shared by all users across a community&#8217;s set of pages.</p>
</dd>
<dt>use-default-template</dt>
<dd>Set the use-default-template value to true if the portlet uses the default template to decorate and wrap content. Setting this to false allows the developer to own and maintain the portlet&#8217;s entire outputted content. The default value is true.</p>
<p>The most common use of this is if you want the portlet to look different from the other portlets or if you want the portlet to not have borders around the outputted content.</p>
</dd>
<dt>show-portlet-access-denied</dt>
<dd>Set the show-portlet-access-denied value to true if users are shown the portlet with an access denied message if they do not have access to the portlet. If set to false, users are never shown the portlet if they do not have access to the portlet. The default value is set in portal.properties.</p>
</dd>
<dt>show-portlet-inactive</dt>
<dd>Set the show-portlet-inactive value to true if users are shown the portlet with an inactive message if the portlet is inactive. If set to false, users are never shown the portlet if the portlet is inactive. The default value is set in portal.properties.</p>
</dd>
<dt>action-url-redirect</dt>
<dd>Set the action-url-redirect value to true if an action URL for this portlet should cause an auto redirect. This helps prevent double submits. The default value is false.</p>
</dd>
<dt>restore-current-view</dt>
<dd>Set the restore-current-view value to true if the portlet restores to the current view when toggling between maximized and normal states. If set to false, the portlet will reset the current view when toggling between maximized and normal states. The default value is true.</p>
</dd>
<dt>maximize-edit</dt>
<dd>Set the maximize-edit value to true if the portlet goes into the maximized state when the user goes into the edit mode. This only affects the default portal icons and not what may be programmatically set by the portlet developer. The default value is false.</p>
</dd>
<dt>maximize-help</dt>
<dd>Set the maximize-help value to true if the portlet goes into the maximized state when the user goes into the edit mode. This only affects the default portal icons and not what may be programmatically set by the portlet developer. The default value is false.</p>
</dd>
<dt>maximize-print</dt>
<dd>Set the maximize-print value to true if the portlet goes into the maximized state when the user goes into the edit mode. This only affects the default portal icons and not what may be programmatically set by the portlet developer. The default value is false.</p>
</dd>
<dt>layout-cacheable</dt>
<dd>Set the layout-cacheable flag to true if the data contained in this portlet will never change unless the layout or portlet entry is changed.</p>
</dd>
<dt>instanceable</dt>
<dd>Set the instanceable value to true if the portlet can appear multiple times on a page. If set to false, the portlet can only appear once on a page. The default value is false.</p>
</dd>
<dt>private-request-attributes</dt>
<dd>Set the private-request-attributes value to true if the portlet does not share request attributes with any other portlet. The default value is true.</p>
</dd>
<dt>render-weight</dt>
<dd>The default value of render-weight is 1. If set to a value less than 1, the portlet is rendered in parallel. If set to a value of 1 or greater, then the portlet is rendered serially. Portlets with a greater render weight have greater priority and will be rendered before portlets with a lower render weight.</p>
<p>If the ajaxable value is set to false, then render-weight is always set to 1if it is set to a value less than 1. This means ajaxable can override render-weight if ajaxable is set to false.</p>
</dd>
<dt>ajaxable</dt>
<dd>The default value of ajaxable is true. If set to false, then this portlet can never be displayed via Ajax.</p>
</dd>
<dt>add-default-resource</dt>
<dd>If the add-default-resource value is set to false, and the portlet does not belong to the page but has been dynamically added, then the user will see that he does not have permissions to view the portlet. If the add-default-resource value is set to true, the default portlet resources and permissions are added to the page. The user can then view the portlet. Most portlets are harmless and can benefit from this flexibility. However, to prevent security loop holes, the default value is false.</p>
</dd>
<dt>system</dt>
<dd>Set the system value to true if the portlet is a system portlet that a user cannot manually add to their page. The default value is false.</p>
</dd>
<dt>active</dt>
<dd>Set the active value to true if the portlet is active and available to users. If set to false, the portlet will not be active or available to users. The default value is true.</p>
<p>This value can be changed at runtime via the Admin portlet.</p>
</dd>
<dt>include</dt>
<dd>Set the include value to true to if the portlet is available to the portal. If set to false, the portlet is not available to the portal. The default value is true. Portlets that are not included as part of the portal are never available to the user to be made active or inactive. As far the user knows, the portlets do not even exist in the system. This allows the Liferay developers to bundle a lot of portlets in one core package, and yet allow custom deployments to turn on or off individual portlets or sets of portlets. This follows the Siebel and Microsoft model of bundling everything in one core package, but using XML configuration or registry settings to turn on and off features or sets of features. We do not recommend that custom deployers modify the core source by removing specific portlets because this prevents an easy upgrade process in the future. The best way to turn on and off portlets is to set the include element. The advantage of this way of doing things is that it becomes very easy to deploy Liferay. All features are available in one package. The disadvantage is that by not utilizing all of the portlets, you are wasting disk space and may even take a small but static memory footprint. However, we feel that the extra disk space and memory usage is a cheap price to pay in order to provide an easy installation and upgrade path.</p>
</dd>
</dl>
</div>
<p>In addition to specifying the above parameters specific to each portlet, the <code>liferay-portlet.xml</code> file can also be used to specify role mappings and custom user attributes global to the whole portlet application. Here is an example:</p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;!DOCTYPE liferay-portlet-app PUBLIC "-//Liferay//DTD Portlet Application 4.2.0//EN" "http://www.liferay.com/dtd/liferay-portlet-app_4_2_0.dtd"&gt;

&lt;liferay-portlet-app&gt;
...
	&lt;role-mapper&gt;
		&lt;role-name&gt;user&lt;/role-name&gt;
		&lt;role-link&gt;User&lt;/role-link&gt;
	&lt;/role-mapper&gt;
	&lt;custom-user-attribute&gt;
		&lt;name&gt;user.name.random&lt;/name&gt;
		&lt;custom-class&gt;com.liferay.portlet.CustomUserAttributes&lt;/custom-class&gt;
	&lt;/custom-user-attribute&gt;
&lt;/liferay-portlet-app&gt;</pre>
<p>Here is a more detailed description of these elements:</p>
<div>
<dl>
<dt>role-mapper</dt>
<dd>The role-mapper contains two names specified by role-name and role-link. The role-name value must be a role specified in portlet.xml. The role-link value must be the name of a Liferay role that exists in the database. The role-mapper element pairs up these two values to map roles from portlet.xml to roles in the Liferay database. This is needed because Liferay roles may contain spaces whereas roles in portlet.xml cannot contain spaces. This also adds extra flexibility where the portlet vendor does not need to have any knowledge about Liferay&#8217;s roles.</p>
</dd>
<dt>custom-user-attribute</dt>
<dd>The custom-user-attribute contains a list of names that are retrieved using a custom class that extends <code>com.liferay.portlet.CustomUserAttributes</code>.</p>
<p>For a usage example, download the sample hot deployable portlet WAR named <code>test.war</code>. Look for the class <code>com.liferay.portlet.teststruts.TestStrutsUserAttributes</code> to see how it associates the custom user attribute &#8220;user.name.test&#8221; with the value &#8220;Test Name&#8221;. This class could be modified to read custom user attributes from another datasource that may be a database, a LDAP server, or a web service.</p>
</dd>
</dl>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h2><a name="d0e496"></a>2. Organizing Portlets in Categories</h2>
</div>
</div>
</div>
<p>The interface provided to a user to select a portlet to be added to a page shows the portlets organized in categories to make it easier to find them. The file liferay-display.xml is available to portlet developers to specify how they want their portlets to be categorized. Following is an example of what this file may look like:</p>
<pre>&lt;display&gt;
	&lt;category name="category.admin"&gt;
		&lt;portlet id="9" /&gt;
		&lt;portlet id="40" /&gt;
		&lt;portlet id="79" /&gt;
		&lt;portlet id="80" /&gt;
	&lt;/category&gt;
	&lt;category name="category.cms"&gt;
		&lt;category name="category.alfresco"&gt;
			&lt;portlet id="91" /&gt;
		&lt;/category&gt;
	&lt;/category&gt;
...
&lt;display&gt;</pre>
<p>The name of the category must be a key defined in the resource bundle of the portlet. The value of the id attribute must be the portlet-name as defined in the <code>portlet.xml</code> file. Categories can be nested and default portal categories can be used to add the portlet along with the bundled portlets.</p>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h2><a name="d0e508"></a>Chapter 3. Liferay Portlet Frameworks</h2>
</div>
</div>
</div>
<div>
<p><strong>Table of Contents</strong></p>
<dl>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e523">1. Writing a Simple JSPPortlet</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e658">2. StrutsPortlet Tutorial</a></dt>
<dd>
<dl>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e666">2.1. Writting a Very Simple Struts Portlet</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1110">2.2. Adding an action</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1564">2.3. Conclusion</a></dt>
</dl>
</dd>
</dl>
</div>
<p>In the next sections, you will learn how to develop a JSR 168 portlet leveraging two frameworks offered by Liferay to make deployment easier. First you will also learn how to create a simple JSPPortlet before moving on to the more complicated StrutsPortlet.</p>
<p>Both of these frameworks are available through the extension environment, so the rest of this section will assume that you already have it installed in a directory called <code>ext</code>. If you need more information about the extension environment, please read the <em>Liferay Portal 4 &#8211; Development in the Extension Environment</em> guide.</p>
<p>Note that by using these portlet frameworks your portlets will only work in Liferay Portal but not in other JSR-168 compliant portlets. Use them also if you need to speed your development and do not plan to deploy your portlets in other portal in the near term.</p>
<div lang="en">
<div>
<div>
<div>
<h2><a name="d0e523"></a>1. Writing a Simple JSPPortlet</h2>
</div>
</div>
</div>
<p>Although a JSPPortlet does little more than display content, there is still some work that needs to be done. Let’s start by creating a new directory called <code>myjspportlet</code> within <code>ext\ext-web\docroot\html\portlet\ext</code> Next, open <code>portlet-ext.xml</code> within <code>ext\ext-web\docroot\WEB-INF\</code>.</p>
<div>
<table summary="Note" border="0">
<tbody>
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img src="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/note.png" alt="[Note]" /></td>
<th align="left">Note</th>
</tr>
<tr>
<td align="left" valign="top">If you are using Eclipse, you may need to associate .xml files to Eclipse if your .xml files are being opened in a separate editor. You can do this by selecting<strong> Window</strong> from the menu bar and then <strong>Preferences</strong>. Expand the <strong>Workbench </strong>navigation, and click on<strong> File</strong> <strong>A</strong><strong>ssociations</strong>. From there you can add *.xml as a new File type and associate it to open in Eclipse.</td>
</tr>
</tbody>
</table>
</div>
<p>Notice how the portlets are uniquely identified by their portlet-name (also referred within Liferay Portal as the portlet id). As such, you will want to create a new portlet that is an increment of the portlet name, such as EXT_2. Since we are creating a JSPPortlet, you will want the portlet-class to reference the full class name: com.liferay.portlet.JSPPortlet. For this tutorial, add the following to your portlet-ext.xml (you may find it easier to copy and paste EXT_1 and just make the necessary changes):</p>
<pre>&lt;portlet&gt;
  &lt;portlet-name&gt;EXT_2&lt;/portlet-name&gt;
  &lt;display-name&gt;My JSPPortlet&lt;/display-name&gt;
  &lt;portlet-class&gt;com.liferay.portlet.JSPPortlet&lt;/portlet-class&gt;
  &lt;init-param&gt;
    &lt;name&gt;view-jsp&lt;/name&gt;
    &lt;value&gt;/portlet/ext/myjspportlet/view.jsp&lt;/value&gt;
  &lt;/init-param&gt;
  &lt;expiration-cache&gt;300&lt;/expiration-cache&gt;
  &lt;supports&gt;
    &lt;mime-type&gt;text/html&lt;/mime-type&gt;
  &lt;/supports&gt;
  &lt;portlet-info&gt;
    &lt;title&gt;My JSP Portlet&lt;/title&gt;
  &lt;/portlet-info&gt;
  &lt;security-role-ref&gt;
    &lt;role-name&gt;Power User&lt;/role-name&gt;
  &lt;/security-role-ref&gt;
  &lt;security-role-ref&gt;
    &lt;role-name&gt;User&lt;/role-name&gt;
  &lt;/security-role-ref&gt;
&lt;/portlet&gt;</pre>
<p>Here is a basic summary of what each of the elements represents:</p>
<div>
<table border="1">
<col />
<col />
<tbody>
<tr>
<td>portlet-name</td>
<td>The portlet-name element contains the canonical name of the portlet. Each portlet name is unique within the portlet application.</td>
</tr>
<tr>
<td>display-name</td>
<td>The display-name type contains a short name that is intended to be displayed by tools. It is used by display-name elements. The display name need not be unique.</td>
</tr>
<tr>
<td>portlet-class</td>
<td>The portlet-class element contains the fully qualified class name of the portlet.</td>
</tr>
<tr>
<td>init-param</td>
<td>The init-param element contains a name/value pair as an initialization param of the portlet.</td>
</tr>
<tr>
<td>expiration-cache</td>
<td>Expiration-cache defines expiration-based caching for this portlet. The parameter indicates the time in seconds after which the portlet output expires. -1 indicates that the output never expires.</td>
</tr>
<tr>
<td>supports</td>
<td>The supports element contains the supported mime-type. Supports also indicates the portlet modes a portlet supports for a specific content type. All portlets must support the view mode.</td>
</tr>
<tr>
<td>portlet-info</td>
<td>Portlet-info defines portlet information.</td>
</tr>
<tr>
<td>security-role-ref</td>
<td>The security-role-ref element contains the declaration of a security role reference in the code of the web application. Specifically in Liferay, the role-name references which role’s can access the portlet. (A Power User can personalize the portal, whereas a User cannot.)</td>
</tr>
</tbody>
</table>
</div>
<p>Now that you have configured your portlet-ext.xml, the next step is to create the jsp pages. Within your <code>/myjspportlet directory</code>, add a file called <code>init.jsp</code>. Within this file, add the following two lines of code:</p>
<pre>&lt;%@ include file="/html/common/init.jsp" %&gt;
&lt;portlet:defineObjects /&gt;</pre>
<p>These two lines import all the common class files and also set common variables used by each portlet. If you need to import portlet specific classes or initialize portlet specific variables, be sure to add them to their directory specific init.jsp, as opposed to the common/init.jsp.</p>
<p>These two lines import all the common class files and also set common variables used by each portlet. If you need to import portlet specific classes or initialize portlet specific variables, be sure to add them to their directory specific init.jsp, as opposed to the common/init.jsp.</p>
<p>Now, add a view.jsp. This jsp file will hold the content of your JSPPortlet. Write “Hello [your name here]‿ within the jsp. So the question is then, how does the portal know how to load these particular files? If you look back at the portlet element that was added within portlet-ext.xml, you will notice that you initialized a <code>view-jsp</code> parameter as having the value <code>/ext/myjspportlet/view.jsp</code>. By specifying this init-param, you are giving the portlet a default jsp to load.</p>
<p>Finally, in order to be able to add your portlet to the portal, you need to define the name within Language-ext.properties by adding the following line:</p>
<p><code>javax.portlet.title.EXT_2=My JSP Portlet</code></p>
<p>Since you have setup the Extension Environment, you need to deploy the changes you have made to your application server by running <strong>ant deploy</strong> from the <code>ext</code> directory.</p>
<div>
<table summary="Note" border="0">
<tbody>
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img src="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/note.png" alt="[Note]" /></td>
<th align="left">Note</th>
</tr>
<tr>
<td align="left" valign="top">Eclipse users may use the Ant view to run ant commands. In this case just double click the <strong>deploy [default]</strong>.</td>
</tr>
</tbody>
</table>
</div>
<p>Start Tomcat again as soon as the deployment finishes. Browse to the <strong>Home</strong> tab of the portal, and in the<strong> Add Portlet to Wide Column</strong> dropdown add “My JSP Portlet‿ to your portal.</p>
</div>
<div lang="en">
<div>
<div>
<div>
<h2><a name="d0e658"></a>2. StrutsPortlet Tutorial</h2>
</div>
</div>
</div>
<p>This section will take you through an example-driven tutorial on how to develop a StrutsPortlet. It is assumed that you have an extension environment installed in a directory called <code>ext</code>. It is also assumed that you will be using Tomcat as the application server.</p>
<div lang="en">
<div>
<div>
<div>
<h3><a name="d0e666"></a>2.1. Writting a Very Simple Struts Portlet</h3>
</div>
</div>
</div>
<p>The goal of this section is to create a Struts Portlet within Liferay.</p>
<div>
<ol type="1">
<li>Define the portlet
<div>
<ul>
<li>portlet-ext.xml</li>
<li>liferay-portlet-ext.xml</li>
</ul>
</div>
</li>
<li>Define the page flow and layout
<div>
<ul>
<li>struts-config.xml</li>
<li>tiles-defs.xml</li>
</ul>
</div>
</li>
<li>Create the JSP
<div>
<ul>
<li>view.jsp</li>
</ul>
</div>
</li>
</ol>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e699"></a>Key Concepts</h4>
</div>
</div>
</div>
<p>What are the main differences between a JSP Portlet and a Struts Portlet?</p>
<div>
<ul>
<li><code>struts-config.xml</code></li>
<li><code>tiles-defs.xml</code></li>
</ul>
</div>
<p>Instead of forwarding directly to a JSP</p>
<div>
<ul>
<li><code>struts-config.xml</code> – define the page flow</li>
<li><code>tiles-defs.xml</code> – define the page layout</li>
</ul>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e726"></a>Why Use Struts?</h4>
</div>
</div>
</div>
<div>
<ul>
<li>Struts implements MVC. Although there are other frameworks that implement MVC, Struts is the most widely used and mature technology.</li>
<li>What is MVC? MVC separates the presentation code from the business logic code.</li>
<li>Struts provides centralized page-flow management in the form of struts-config.xml. This makes it highly scalable and allows you to modularize the coding process.</li>
<li>By using Struts, you will be using a number of best practices that have been built into the framework.</li>
</ul>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e742"></a>Why Use Tiles?</h4>
</div>
</div>
</div>
<p>A page layout is typically designed using include statements. If there are 100 JSPs and the header and footer need to be swapped, all 100 JSPs need to be changed. With Tiles, a single template can be used to determine the page layout. Only the template needs to be changed, and all the pages will be updated accordingly.</p>
<div><img src="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic1.gif" alt="" /></div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e749"></a>High Level Overview</h4>
</div>
</div>
</div>
<div>
<ul>
<li>A URL or URI is passed to the Controller.</li>
<li>The Controller determines what page should be displayed.
<div><img src="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic2.gif" alt="" /></div>
</li>
</ul>
</div>
<p><strong>Example:</strong></p>
<p>How does Liferay determine which JSP is displayed first?</p>
<div>
<ul>
<li>Our starting point is portlet-ext.xml view-action</li>
<li>Controller <img src="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic5.gif" alt="" /> MainServlet.java
<div><img src="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic3.gif" alt="" /></div>
</li>
</ul>
</div>
<p><strong>Detailed View:</strong></p>
<div><img src="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic4.gif" alt="" /></div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e781"></a>Directory Structure</h4>
</div>
</div>
</div>
<p>Configuration files are located in this directory: <code>…\ext\ext-web\docroot\WEB-INF</code></p>
<p>JSPs will be placed in this directory: <code>…\ext\ext-web\docroot\html\portlet\ext</code></p>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e792"></a>Portlet Definition</h4>
</div>
</div>
</div>
<p>Add the following portlet definition to the <code>portlet-ext.xml</code> file:</p>
<pre>&lt;portlet&gt;
	&lt;portlet-name&gt;EXT_4&lt;/portlet-name&gt;
	&lt;display-name&gt;Library Portlet&lt;/display-name&gt;
	&lt;portlet-class&gt;com.liferay.portlet.StrutsPortlet&lt;/portlet-class&gt;
	&lt;init-param&gt;
		&lt;name&gt;view-action&lt;/name&gt;
		&lt;value&gt;/ext/library/view&lt;/value&gt;
	&lt;/init-param&gt;
	&lt;expiration-cache&gt;0&lt;/expiration-cache&gt;
&lt;supports&gt;
		&lt;mime-type&gt;text/html&lt;/mime-type&gt;
	&lt;/supports&gt;
	&lt;resource-bundle&gt;com.liferay.portlet.StrutsResourceBundle&lt;/resource-bundle&gt;
	&lt;security-role-ref&gt;
		&lt;role-name&gt;power-user&lt;/role-name&gt;
	&lt;/security-role-ref&gt;
	&lt;security-role-ref&gt;
		&lt;role-name&gt;user&lt;/role-name&gt;
	&lt;/security-role-ref&gt;
&lt;/portlet&gt;</pre>
<p>Next add the following Liferay specific info to <code>liferay-portlet-ext.xml</code>:</p>
<pre>&lt;portlet&gt;
	&lt;portlet-name&gt;EXT_4&lt;/portlet-name&gt;
	&lt;struts-path&gt;ext/library&lt;/struts-path&gt;
	&lt;use-default-template&gt;false&lt;/use-default-template&gt;
&lt;/portlet&gt;</pre>
<div>
<ul>
<li>The struts-path is used to implement security.</li>
<li>http://localhost:8080/c/portal/layout?p_l_id=PRI.15.1&amp;p_p_id=EXT_4&amp;p_p_action=1&amp;p_p_state=maximized&amp;p_p_mode=view&amp;p_p_col_id=column-1&amp;p_p_col_pos=5&amp;p_p_col_count=6&amp;_EXT_4_struts_action=%2Fext%2Flibrary%2Fview</li>
<li>struts_action=“/ext/library/view”</li>
</ul>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e819"></a>struts-config.xml</h4>
</div>
</div>
</div>
<p>struts-config.xml defines the page flow</p>
<pre>&lt;action path="/ext/library/view" forward="portlet.ext.library.view" /&gt;</pre>
<p>What is /ext/library/view?</p>
<p>portlet-ext.xml:</p>
<pre>&lt;init-param&gt;
	&lt;name&gt;view-action&lt;/name&gt;
	&lt;value&gt;/ext/library/view&lt;/value&gt;
&lt;/init-param&gt;</pre>
<p>What is portlet.ext.library.view?</p>
<p>It is the forward that is used to look up the tiles definition.</p>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e836"></a>tiles-defs.xml</h4>
</div>
</div>
</div>
<p>tiles-defs.xml defines the page layout</p>
<pre>&lt;definition name="portlet.ext.library" extends="portlet" /&gt;

&lt;definition name="portlet.ext.library.view" extends="portlet.ext.library"&gt;
	&lt;put name="portlet_content" value="/portlet/ext/library/view.jsp" /&gt;
&lt;/definition&gt;</pre>
<p>What is portlet.ext.library.view?</p>
<div>
<ul>
<li>From struts-config.xml
<pre>&lt;action path="/ext/library/view" forward="portlet.ext.library.view" /&gt;
&lt;definition name="portlet.ext.library" extends="portlet" /&gt;

&lt;definition name="portlet.ext.library.view" extends="portlet.ext.library"&gt;
	&lt;put name="portlet_content" value="/portlet/ext/library/view.jsp" /&gt;
&lt;/definition&gt;</pre>
</li>
</ul>
</div>
<p>What is /portlet/ext/library/view.jsp?</p>
<p>For reference: portlet-ext.xml from JSP Portlet Training</p>
<pre>	&lt;init-param&gt;
		&lt;name&gt;view-jsp&lt;/name&gt;
		&lt;value&gt;/portlet/ext/jsp_portlet/view.jsp&lt;/value&gt;
	&lt;/init-param&gt;</pre>
<p>For the JSP Portlet, the JSP was pointed directly from portlet-ext.xml. For Struts portlets, this is done through tiles-defs.xml</p>
<pre>&lt;definition name="portlet.ext.library" extends="portlet" /&gt;

&lt;definition name="portlet.ext.library.view" extends="portlet.ext.library"&gt;
	&lt;put name="portlet_content" value="/portlet/ext/library/view.jsp" /&gt;
&lt;/definition&gt;</pre>
<p>What is portlet?</p>
<p>Portlet is the template that will be used (portlet.jsp). See …\portal\portal-web\docroot\WEB-INF\tiles-defs.xml for more information.</p>
<p>What is portlet.ext.library?</p>
<div>
<ul>
<li>portlet.ext.library extends portlet. This means that portlet.ext.library will use the portlet.jsp as its template.</li>
<li>portlet.ext.library.view extends portlet.ext.library. This means that portlet.ext.library.view will also use portlet.jsp for its template.</li>
</ul>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e874"></a>Create the JSP</h4>
</div>
</div>
</div>
<p>The next step is to create the JSP.</p>
<div>
<ul>
<li>Create a directory called library here: <code>…\ext\ext-web\docroot\html\portlet\ext</code></li>
<li>Your directory structure should now look like this: <code>…\ext\ext-web\docroot\html\portlet\ext\library</code></li>
<li>Create view.jsp in the library directory: <code>…\ext\ext-web\docroot\html\portlet\ext\library\view.jsp</code></li>
<li>Enter “Simple Struts Portlet!” in view.jsp</li>
</ul>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e898"></a>Deploy the Files to Tomcat</h4>
</div>
</div>
</div>
<p>Once you have finished modifying all of the files, deploy them to Tomcat.</p>
<div>
<ol type="1">
<li>Open up a cmd prompt.</li>
<li>Click <strong>Start</strong>, <strong>Run</strong>, and then type<strong> cmd</strong>.</li>
<li>Navigate to your ext directory and then type <strong>ant deploy</strong>.
<div>
<ul>
<li><code>…\ext&gt;ant deploy</code></li>
</ul>
</div>
</li>
</ol>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e930"></a>Check the Tomcat Directory</h4>
</div>
</div>
</div>
<p>Verify that the files were deployed to Tomcat.</p>
<div>
<ol type="1">
<li>Go to <code>…\tomcat\webapps\ROOT\WEB-INF</code> and open <code>portlet-ext.xml</code>, <code>liferay-portlet-ext.xml</code>, <code>struts-config-ext.xml</code>, and <code>tiles-defs-ext.xml</code> to check that the files were deployed correctly.</li>
<li>Go to <code>…\tomcat\webapps\ROOT\html\portlet\ext\library</code> and open up <code>view.jsp </code>to see that it was deployed correctly.</li>
</ol>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e963"></a>Final Steps</h4>
</div>
</div>
</div>
<div>
<ol type="1">
<li>Restart Tomcat.</li>
<li>Open up a new browser and type:
<div>
<ul>
<li>http://localhost:8080</li>
<li>LOGIN: test@liferay.com</li>
<li>PASSWORD: test</li>
</ul>
</div>
</li>
<li>Click <strong>Add Content</strong>&gt;<strong>Undefined</strong>.</li>
<li>Click javax.portlet.title.EXT_4.</li>
</ol>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e995"></a>Key Concepts</h4>
</div>
</div>
</div>
<div><img src="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic6.gif" alt="" /></div>
<div><img src="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic7.gif" alt="" /></div>
<p>Now that we’ve finished building the framework for our portlet, let’s move on to the next exercise. In this exercise, we will:</p>
<div>
<ul>
<li>Create a new file called <code>init.jsp</code> where we will add commonly used variables and declarations.</li>
<li>Set the portlet title.</li>
<li>Add the portlet to a category.</li>
</ul>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1016"></a>init.jsp</h4>
</div>
</div>
</div>
<p>Create init.jsp in the library directory:<code> …\ext\ext-web\docroot\html\portlet\ext\library\init.jsp</code></p>
<p><code>Enter the following in init.jsp:</code></p>
<pre>	&lt;%@ include file="/html/common/init.jsp" %&gt;
	&lt;p&gt;Add commonly used variables and declarations here!&lt;/p&gt;</pre>
<p>What file are we including with this line?</p>
<pre>	&lt;%@ include file="/html/common/init.jsp" %&gt;
…\portal\portal-web\docroot\html\common\init.jsp</pre>
<p>This will gives us access to the Liferay tag libraries.</p>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1034"></a>view.jsp</h4>
</div>
</div>
</div>
<div>
<ul>
<li>Add this line above “Simple Struts Portlet!” in view.jsp:
<pre>&lt;%@ include file="/html/portlet/ext/library/init.jsp" %&gt;
	Simple Struts Portlet!</pre>
</li>
<li>This will give us access to the init.jsp located here:
<p><code>…\ext\ext-web\docroot\html\portlet\ext\library\init.jsp</code></li>
<li>Ant deploy. You do not have to restart Tomcat.</li>
<li>The following should now be displayed: <strong>Add commonly used variables and declarations here! Simple Struts Portlet</strong></li>
</ul>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1057"></a>Set the Portlet Title</h4>
</div>
</div>
</div>
<div>
<ul>
<li>Go to Language-ext.properties and add the following line:
<p><code>…\ext\ext-ejb\classes\content\Language-ext.properties</code></p>
<p><code><code>javax.portlet.title.EXT_4=Library</code></code></li>
<li>Ant deploy and Restart Tomcat.</li>
<li>The portlet title will now be “Library.”</li>
</ul>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1077"></a>Add the Portlet to a Category</h4>
</div>
</div>
</div>
<div>
<ol type="1">
<li>Go to liferay-display.xml and add the following line:
<p><code>…\ext\ext-web\docroot\WEB-INF\liferay-display.xml </code></p>
<pre>	&lt;category name="category.test"&gt;
		&lt;portlet id=“EXT_3" /&gt;
		&lt;portlet id="EXT_4" /&gt;
		...
	&lt;/category&gt;</pre>
</li>
<li>You will now be able to select your portlet from the “Test” category.</li>
</ol>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1092"></a>Review of &lt;struts-path&gt;</h4>
</div>
</div>
</div>
<pre>&lt;portlet&gt;
	&lt;portlet-name&gt;EXT_4&lt;/portlet-name&gt;
	&lt;struts-path&gt;ext/library&lt;/struts-path&gt;
	&lt;use-default-template&gt;false&lt;/use-default-template&gt;
&lt;/portlet&gt;</pre>
<p>Liferay will check the struts-path to check whether a user has the required roles to access the portlet.</p>
<p>Note: When you see the error message: <strong>You do not have the required roles to access this portlet.</strong></p>
<div>
<ol type="1">
<li>Check to see that you have defined the roles correctly in portlet-ext.xml.</li>
<li>Check the &lt;struts-path&gt; to see if you have defined it correctly.</li>
</ol>
</div>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h3><a name="d0e1110"></a>2.2. Adding an action</h3>
</div>
</div>
</div>
<p>The goal of this section is to add an Action Class to the Struts Portlet and to display an success page.</p>
<div>
<ol type="1">
<li>Define the Action.
<div>
<ul>
<li>struts-config.xml</li>
<li>tiles-defs.xml</li>
</ul>
</div>
</li>
<li>Update existing JSP files.
<div>
<ul>
<li>view.jsp</li>
<li>init.jsp</li>
</ul>
</div>
</li>
<li>Create success and error JSP files.
<div>
<ul>
<li>error.jsp</li>
<li>Success.jsp</li>
</ul>
</div>
</li>
<li>Create Action Class to process submit.
<div>
<ul>
<li>AddBookAction.java</li>
</ul>
</div>
</li>
</ol>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1153"></a>Review Key Concepts</h4>
</div>
</div>
</div>
<p>What are the main differences between a JSP Portlet and a Struts Portlet?</p>
<div>
<ul>
<li>JSP Portlet goes directly to a JSP</li>
<li>Struts Portlet has an page flow</li>
</ul>
</div>
<p>Where does the page flow get defined?</p>
<div>
<ul>
<li>struts-config.xml – define the page flow</li>
<li>tiles-defs.xml – define the page layout</li>
</ul>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1174"></a>struts-config.xml</h4>
</div>
</div>
</div>
<p>struts-config.xml defines the page flow</p>
<pre>&lt;action path="/ext/library/view" forward="portlet.ext.library.view" /&gt;</pre>
<p>Lets add another path to the page flow</p>
<pre>&lt;action path="/ext/library/add_book" type="com.ext.portlet.library.action.AddBookAction"&gt;
	&lt;forward name="portlet.ext.library.error" path="portlet.ext.library.error" /&gt;
	&lt;forward name="portlet.ext.library.success" path="portlet.ext.library.success" /&gt;
&lt;/action&gt;</pre>
<p>What is type?</p>
<div>
<ul>
<li>Type is a Struts defined way of passing control to the AddBookAction class.</li>
</ul>
</div>
<p>Lets look at the forward nodes:</p>
<pre>&lt;forward name="portlet.ext.library.error" path="portlet.ext.library.error" /&gt;
&lt;forward name="portlet.ext.library.success" path="portlet.ext.library.success" /&gt;</pre>
<p>What is name?</p>
<div>
<ul>
<li>It the unique identifier for that forward node.</li>
</ul>
</div>
<p>What is path?</p>
<div>
<ul>
<li>This is your link to the <code>tiles-def.xml</code>.</li>
</ul>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1210"></a>tiles-defs.xml</h4>
</div>
</div>
</div>
<p>tiles-defs.xml defines the page layout</p>
<pre>&lt;definition name="portlet.ext.library" extends="portlet" /&gt;

&lt;definition name="portlet.ext.library.view" extends="portlet.ext.library"&gt;
	&lt;put name="portlet_content" value="/portlet/ext/library/view.jsp" /&gt;
&lt;/definition&gt;</pre>
<p>Lets add the error and success paths</p>
<pre>&lt;definition name="portlet.ext.library.error" extends="portlet.ext.library"&gt;
	&lt;put name="portlet_content" value="/portlet/ext/library/error.jsp" /&gt;
&lt;/definition&gt;

&lt;definition name="portlet.ext.library.success" extends="portlet.ext.library"&gt;
	&lt;put name="portlet_content" value="/portlet/ext/library/success.jsp" /&gt;
&lt;/definition&gt;</pre>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1221"></a>init.jsp</h4>
</div>
</div>
</div>
<p>Update <code>init.jsp</code> in the library directory</p>
<p><code>…\ext\ext-web\docroot\html\portlet\ext\library\init.jsp</code></p>
<p><code>Remove the following:</code></p>
<pre>&lt;p&gt;Add commonly used variables and declarations here!&lt;/p&gt;</pre>
<p><code>init.jsp</code> should only contain this line:</p>
<pre>&lt;%@ include file="/html/common/init.jsp" %&gt;</pre>
<p>Review: What does including this file give us?</p>
<pre>&lt;%@ include file="/html/common/init.jsp" %&gt;
…\portal\portal-web\docroot\html\common\init.jsp</pre>
<p><code>This will give access to the Liferay tag libraries.</code></p>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1250"></a>view.jsp</h4>
</div>
</div>
</div>
<pre>&lt;%@ include file="/html/portlet/ext/library/init.jsp" %&gt;

&lt;br/&gt;
Add a book entry to the Library:
&lt;br/&gt;&lt;br/&gt;
&lt;form action="&lt;portlet:actionURL windowState="&lt;%= WindowState.MAXIMIZED.toString() %&gt;"&gt;&lt;portlet:param name="struts_action" value="/ext/library/add_book" /&gt;&lt;/portlet:actionURL&gt;" method="post" name="&lt;portlet:namespace /&gt;fm"&gt;	

	Book Title:

	&lt;input name="&lt;portlet:namespace /&gt;book_title" size="20" type="text" value=""&gt;&lt;br/&gt;&lt;br/&gt;

	&lt;input type="button" value="Submit" onClick="submitForm(document.&lt;portlet:namespace /&gt;fm);"&gt;
&lt;/form&gt;
&lt;br/&gt;</pre>
<p>What does “struts_action” do?</p>
<div>
<ul>
<li>Struts_action is the ActionMapping to the struts-config.xml path.
<pre>&lt;action path="/ext/library/add_book" type="com.ext.portlet.library.action.AddBookAction"&gt;</pre>
</li>
<li>value=<code>"/ext/library/add_book“</code>
<div>
<ul>
<li>This is the link to the ActionPath.</li>
</ul>
</div>
</li>
<li>Review
<p>What does “struts_action” connect us to?</p>
<p>It connects us to the struts-config.xml</li>
</ul>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1279"></a>error.jsp</h4>
</div>
</div>
</div>
<div>
<ul>
<li><code>error.jsp</code>Path:
<p><code>ext-web/docroot/html/portlet/ext/library/error.jsp</code></li>
</ul>
</div>
<div>
<ul>
<li><code>error.jsp</code> Contents:
<p>ERROR!</li>
</ul>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1299"></a>success.jsp</h4>
</div>
</div>
</div>
<div>
<ul>
<li>success.jsp Path:
<p><code>ext-web/docroot/html/portlet/ext/library/success.jsp</code></li>
<li>success.jsp Contents:
<p>SUCCESS!</li>
</ul>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1314"></a>AddBookAction.java</h4>
</div>
</div>
</div>
<div>
<ul>
<li>AddBookAction Class Path:
<p><code>ext/ext-ejb/src/com/ext/portlet/library/action/AddBookAction.java</code></li>
<li>AddBookAction Class Contents:
<pre>package com.ext.portlet.library.action;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletConfig;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
public class AddBookAction extends PortletAction {
public void processAction(
			ActionMapping mapping, ActionForm form, PortletConfig config,
			ActionRequest req, ActionResponse res)

		throws Exception {

		String bookTitle = req.getParameter("book_title");

		if ( null == bookTitle || "".equals(bookTitle) ) {
			setForward(req, "portlet.ext.library.error");
		} else {
			setForward(req, "portlet.ext.library.success");
		}
	}

	public ActionForward render(ActionMapping mapping, ActionForm form,
		PortletConfig config, RenderRequest req, RenderResponse res)
		throws Exception {
		if (getForward(req) != null &amp;&amp; !getForward(req).equals("")) {
			return mapping.findForward(getForward(req));
		} else {
			return mapping.findForward("portlet.ext.library.view");
		}
	}
}</pre>
</li>
<li>Main code:
<pre>String bookTitle = req.getParameter("book_title");

if ( null == bookTitle || "".equals(bookTitle) ) {
	setForward(req, "portlet.ext.library.error");
} else {
	setForward(req, "portlet.ext.library.success");
}</pre>
</li>
<li>Where does “book_title” come from?
<p>It comes from to the <code>view.jsp</code> form.</li>
<li>What is the if/else statement doing?
<div>
<ul>
<li>It is detecting if the book title was submitted.</li>
<li>According to the detected state, it sets the forward path.</li>
</ul>
</div>
</li>
<li><code>Error </code>forward path:
<pre>if ( null == bookTitle || "".equals(bookTitle) ) {
	setForward(req, "portlet.ext.library.error");
} else {
	setForward(req, "portlet.ext.library.success");
}</pre>
</li>
<li><code>Success</code> forward path:
<pre>if ( null == bookTitle || "".equals(bookTitle) ) {
	setForward(req, "portlet.ext.library.error");
} else {
	setForward(req, "portlet.ext.library.success");
}</pre>
</li>
<li><code>Error</code> and<code> Success</code> forward path is linked to the the path in <code>struts-config.xml</code>:
<pre>&lt;forward name="portlet.ext.library.error" path="portlet.ext.library.error" /&gt;
&lt;forward name="portlet.ext.library.success" path="portlet.ext.library.success" /&gt;</pre>
</li>
</ul>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1379"></a>Struts Action Mapping</h4>
</div>
</div>
</div>
<div><img src="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic8.gif" alt="" /></div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1383"></a>Deploy the Files to Tomcat</h4>
</div>
</div>
</div>
<p>Once you have finished modifying all of the files, deploy them to Tomcat.</p>
<div>
<ol type="1">
<li>Open up a cmd prompt.
<div>
<ul>
<li>Click <strong>Start</strong>&gt;<strong>Run</strong> and then type <strong>cmd</strong>.</li>
</ul>
</div>
</li>
<li>Navigate to your ext directory and then type <strong>ant deploy</strong>.
<div>
<ul>
<li><code>…\ext&gt;ant deploy</code></li>
</ul>
</div>
</li>
</ol>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1416"></a>Check the Tomcat Directory</h4>
</div>
</div>
</div>
<p>Verify that the files were deployed to Tomcat</p>
<div>
<ul>
<li>Go to <code>…\tomcat\webapps\ROOT\WEB-INF</code> and open <code>portlet-ext.xml</code>, <code>liferay-portlet-ext.xml</code>, <code>struts-config-ext.xml</code>, and<code> tiles-defs-ext.xml</code> and check to see that the files were deployed correctly.</li>
<li>Next, go to <code>…\tomcat\webapps\ROOT\html\portlet\ext\library </code>and open up <code>view.jsp</code> to see that it was deployed correctly.</li>
</ul>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1449"></a>Final Steps</h4>
</div>
</div>
</div>
<div>
<ol type="1">
<li>Restart Tomcat</li>
<li>Open up a new browser and type:
<p>http://localhost:8080</p>
<p>LOGIN: test@liferay.com</p>
<p>PASSWORD: test</li>
</ol>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1465"></a>Key Concepts</h4>
</div>
</div>
</div>
<div><img src="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic9.gif" alt="" /></div>
<div><img src="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic10.gif" alt="" /></div>
<div><img src="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic11.gif" alt="" /></div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1471"></a>Objectives</h4>
</div>
</div>
</div>
<p>Now that we’ve finished redirecting with an action. Lets make the success page display the submitted value.</p>
<div>
<ul>
<li>Update <code>success.jsp</code> to display the submitted value.</li>
</ul>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1483"></a>success.jsp</h4>
</div>
</div>
</div>
<p><code>success.jsp</code> Path:</p>
<div>
<ul>
<li><code>ext-web/docroot/html/portlet/ext/library/success.jsp</code></li>
</ul>
</div>
<p>success.jsp Contents:</p>
<pre>&lt;%@ include file="/html/portlet/ext/library/init.jsp" %&gt;
&lt;%
	String bookTitle = request.getParameter("book_title");
%&gt;
&lt;table align="center" cellspacing="10" cellpadding="3"&gt;
&lt;tr&gt;
	&lt;td style="font-weight:bold"&gt;Book Title:&lt;/td&gt;
	&lt;td&gt;&lt;%= bookTitle %&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;</pre>
<div>
<ul>
<li>Add <code>init.jsp</code>
<pre>&lt;%@ include file="/html/portlet/ext/library/init.jsp" %&gt;</pre>
</li>
<li>This will give us access to the <code>init.jsp</code> located here:
<p><code>…\ext\ext-web\docroot\html\portlet\ext\library\init.jsp</code></li>
<li>Get the submitted value
<pre>String bookTitle = request.getParameter("book_title");</pre>
</li>
<li>Display the submitted value in <code>success.jsp</code>
<pre>&lt;%= bookTitle %&gt;</pre>
</li>
</ul>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1528"></a>Deploy the Files to Tomcat</h4>
</div>
</div>
</div>
<p>Once you have finished modifying success.jsp, deploy it to Tomcat</p>
<div>
<ol type="1">
<li>Open up a cmd prompt.
<div>
<ul>
<li>Click<strong> <strong>Star</strong>t</strong>&gt;<strong>Run</strong> and then type <strong>cmd</strong>.</li>
</ul>
</div>
</li>
<li>Navigate to your ext directory and then type <strong>ant deploy</strong>.
<div>
<ul>
<li><code>…\ext&gt;ant deploy</code></li>
</ul>
</div>
</li>
</ol>
</div>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h3><a name="d0e1564"></a>2.3. Conclusion</h3>
</div>
</div>
</div>
<p>You&#8217;ve learned how to create a StrutsPortlet using some of the patterns used to create the portlets bundled with Liferay. The next recommended steps are to read the code of those portlets and to look for more information about Struts itself.</p>
</div>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h2><a name="d0e1569"></a>Chapter 4. Portlet deployment</h2>
</div>
</div>
</div>
<div>
<p><strong>Table of Contents</strong></p>
<dl>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1574">1. Liferay Hot Deploy</a></dt>
<dd>
<dl>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1579">1.1. Layout Templates, Portlets and Themes</a></dt>
</dl>
</dd>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1610">2. Manual Deployment</a></dt>
</dl>
</div>
<p>Portlets may be hot deployed through a Liferay specific mechanism or deployed manually using the regular mechanism of the application server. The next sections explain both options.</p>
<div lang="en">
<div>
<div>
<div>
<h2><a name="d0e1574"></a>1. Liferay Hot Deploy</h2>
</div>
</div>
</div>
<p>Liferay allows you to easily hot deploy layout templates, JSR 168 portlets, and themes. Layout templates allow portlets to be arranged inside the constraints of custom layouts. JSR 168 portlets add functional abilities to the portal. Themes modify the look and feel of the portal. Layout templates, portlets and themes can be deployed at runtime by utilizing the hot deploy features of Liferay.</p>
<div lang="en">
<div>
<div>
<div>
<h3><a name="d0e1579"></a>1.1. Layout Templates, Portlets and Themes</h3>
</div>
</div>
</div>
<div>
<ol type="1">
<li>Go to the drive where you installed your server. Check to see that /home/liferay/deploy exists. If it does not, create it. You can also customize the location of this directory from the Admin portlet:
<div>
<div><img src="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/adminhotdeploy.jpg" alt="" /></div>
</div>
</li>
<li>Start the server. The server will now automatically scan for *.war files.</li>
<li>Download one of the layout templates, sample portlets or themes to /home/liferay/deploy. Click <a href="http://www.liferay.com/web/guest/downloads/samples" target="_top">here</a> for a list of sample portlets, themes and layouts. (Any JSR 168 compliant portlet WAR will work as well.)</li>
<li>Install either JBoss+Jetty, JBoss+Tomcat, Jetty, Resin, Tomcat or WebSphere.</li>
<li>If you have already set up the extension environment, you can hot deploy portlets, layouts or themes by dropping them into ext/portlets, ext/layouttpl or ext/themes respectively. Then run <strong>ant deploy</strong> from that directory.
<p>Notes: If the hot deploy feature does not work, make sure that your *.war file is a JSR 168 compliant portlet WAR, theme or layout. (You cannot use themes and layouts designed for Liferay Portal v3.6.1 or layouts and themes that were designed for other portals).</li>
</ol>
</div>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h2><a name="d0e1610"></a>2. Manual Deployment</h2>
</div>
</div>
</div>
<p>It is also possible to deploy the web application using the mechanisms provided by the application server being used. But before deploying it is necessary to do some massaging to the WAR file that will allow Liferay Portal to notice that a new portlet application has been deployed. The <code>com.liferay.portal.tools.PortletDeployer</code> should be used to do this. It is recommended that you use this tool within an ant build script. Following is an example target that might be used to invoke it. It has been taken from the portlets directory of the Liferay extension environment. Adapt the paths as needed.</p>
<pre>	&lt;target name="deploy"&gt;
		&lt;java
			classname="com.liferay.portal.tools.PortletDeployer"
			classpathref="project.classpath"
			fork="true"
			newenvironment="true"&gt;

				&lt;!-- Required Arguments --&gt;

				&lt;jvmarg value="-Ddeployer.base.dir=./" /&gt;
				&lt;jvmarg value="-Ddeployer.dest.dir=${app.server.deploy.dir}" /&gt;
				&lt;jvmarg value="-Ddeployer.app.server.type=${app.server.type}" /&gt;
				&lt;jvmarg value="-Ddeployer.portlet.taglib.dtd=${project.dir}/web-sites/liferay.com-web/docroot/WEB-INF/tld/liferay-portlet.tld" /&gt;
				&lt;jvmarg value="-Ddeployer.unpack.war=true" /&gt;

				&lt;!-- Optional Arguments --&gt;

				&lt;jvmarg value="-Ddeployer.tomcat.lib.dir=${app.server.tomcat.lib.global.dir}" /&gt;

				&lt;!-- Dependent Libraries --&gt;

				&lt;arg value="${project.dir}/lib/util-bridges.jar" /&gt;
				&lt;arg value="${project.dir}/lib/util-java.jar" /&gt;
				&lt;arg value="${project.dir}/web-sites/liferay.com-web/docroot/WEB-INF/lib/util-taglib.jar" /&gt;

				&lt;!-- Specific WARs --&gt;

				&lt;arg line="${deploy.specific.wars}" /&gt;
		&lt;/java&gt;
	&lt;/target&gt;</pre>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h2><a name="d0e1620"></a>Chapter 5. Liferay Services</h2>
</div>
</div>
</div>
<div>
<p><strong>Table of Contents</strong></p>
<dl>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1629">1. Security and Permissions Service</a></dt>
<dd>
<dl>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1634">1.1. Introduction</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1639">1.2. Overview</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e1657">1.3. Implementing Permissions</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e2192">1.4. Summary</a></dt>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e2202">1.5. Information</a></dt>
</dl>
</dd>
<dt><a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/#d0e2305">2. User service</a></dt>
</dl>
</div>
<p>Portlet applications may invoke the services provided by Liferay Portal by using the portal-client.jar client library.</p>
<p>It is also possible to use Liferay Service Builder to develop your portlets using the same service oriented architecture that Liferay Portal is based on.</p>
<p>The following sections describe the most important services that can be used. Refer the documentation in the public Liferay wiki for more information</p>
<div lang="en">
<div>
<div>
<div>
<h2><a name="d0e1629"></a>1. Security and Permissions Service</h2>
</div>
</div>
</div>
<p>The Permissions service is provided by Liferay Portal to developers to write security related functionality in their own portlets. Currently this functionality is only provided for portlets developed within the Liferay sources or through the extension environment.</p>
<div lang="en">
<div>
<div>
<div>
<h3><a name="d0e1634"></a>1.1. Introduction</h3>
</div>
</div>
</div>
<p>Fine grain permissioning is one of the main new features of Liferay Portal 4. Developers can now implement access security into their custom portlets, giving administrators and users a lot more control over their portlets and contents. This document will provide a reference for implementing this new security feature into their custom portlets. Developers should first read the Security and Permissions section of the Liferay User Guide before continuing with this document.</p>
</div>
<div lang="en">
<div>
<div>
<div>
<h3><a name="d0e1639"></a>1.2. Overview</h3>
</div>
</div>
</div>
<p>Adding fine grain permissioning to custom portlets consists of four main steps (also known as DRAC):</p>
<div>
<ol type="1">
<li>Define all resources and their permissions.</li>
<li>For all the resources defined in step 1, register them into the permission system. This is also known simply as “adding resources.”</li>
<li>Associate the necessary permissions to these resources.</li>
<li>Check permission before returning resources.</li>
</ol>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h3><a name="d0e1657"></a>1.3. Implementing Permissions</h3>
</div>
</div>
</div>
<p>In this section, each of the four main steps in adding Liferay’s security feature into custom portlets (built on top of the Liferay portal) will be explained. The following are two definitions that are important to remember.</p>
<div>
<dl>
<dt>Resouce</dt>
<dd>A generic term for any object represented in the portal. Example of resources includes portlets (e.g., Message Boards, Calendar, etc.), Java classes (e.g., Message Board Topics, Calendar Events, etc.), and files (e.g., documents, images, etc.)</p>
</dd>
<dt>Permission</dt>
<dd>An action acting on a resource. For example, the view in “viewing the calendar portlet” is defined as a permission in Liferay.</p>
</dd>
</dl>
</div>
<p>Keep in mind that the permission for a portlet resource is implemented a little differently from the other resources such as Java classes and files. In each of the subsections below, the permission implementation for the portlet resource is explained first, then the model (and file) resource.</p>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1677"></a>Defining Resources and Actions</h4>
</div>
</div>
</div>
<p>For your custom portlet, Liferay portal needs to know whether there are resources that require permission and whether there are custom permissions. The default configuration is encapsulated in an XML file found in the <code>portal/portal-ejb/classes/resource-actions</code> directory, you might use it as a reference to create a similar file for your portlet. If your portlet only needs the view and the configuration permission, and that the portlet doesn’t use any models with permission, then you do not need to create this XML file. The reason is that all portlets in Liferay automatically inherit these permissions. However, if your portlet does have custom permission and/or uses models that have custom permissions, then you will need to create an XML file defining the resources and actions. Let’s take a look at <code>blogs.xml</code> in <code>portal/portal-ejb/classes/resource-actions</code> and see how the blogs portlet defined these resources and actions:</p>
<pre>&lt;?xml version="1.0"?&gt;

&lt;resource-action-mapping&gt;
	&lt;portlet-resource&gt;
		&lt;portlet-name&gt;33&lt;/portlet-name&gt;
		&lt;supports&gt;
			&lt;action-key&gt;ADD_ENTRY&lt;/action-key&gt;
			&lt;action-key&gt;CONFIGURATION&lt;/action-key&gt;
			&lt;action-key&gt;VIEW&lt;/action-key&gt;
		&lt;/supports&gt;
		&lt;community-defaults&gt;
			&lt;action-key&gt;VIEW&lt;/action-key&gt;
		&lt;/community-defaults&gt;
		&lt;guest-defaults&gt;
			&lt;action-key&gt;VIEW&lt;/action-key&gt;
		&lt;/guest-defaults&gt;
		&lt;guest-unsupported&gt;
			&lt;action-key&gt;ADD_ENTRY&lt;/action-key&gt;
		&lt;/guest-unsupported&gt;
	&lt;/portlet-resource&gt;
	&lt;model-resource&gt;
		&lt;model-name&gt;com.liferay.portlet.blogs.model.BlogsCategory&lt;/model-name&gt;
		&lt;portlet-ref&gt;
			&lt;portlet-name&gt;33&lt;/portlet-name&gt;
		&lt;/portlet-ref&gt;
		&lt;supports&gt;
			&lt;action-key&gt;DELETE&lt;/action-key&gt;
			&lt;action-key&gt;PERMISSIONS&lt;/action-key&gt;
			&lt;action-key&gt;UPDATE&lt;/action-key&gt;
			&lt;action-key&gt;VIEW&lt;/action-key&gt;
		&lt;/supports&gt;
		&lt;community-defaults&gt;
			&lt;action-key&gt;VIEW&lt;/action-key&gt;
		&lt;/community-defaults&gt;
		&lt;guest-defaults&gt;
			&lt;action-key&gt;VIEW&lt;/action-key&gt;
		&lt;/guest-defaults&gt;
		&lt;guest-unsupported&gt;
			&lt;action-key&gt;UPDATE&lt;/action-key&gt;
		&lt;/guest-unsupported&gt;
	&lt;/model-resource&gt;
	&lt;model-resource&gt;
		&lt;model-name&gt;com.liferay.portlet.blogs.model.BlogsEntry&lt;/model-name&gt;
		&lt;portlet-ref&gt;
			&lt;portlet-name&gt;33&lt;/portlet-name&gt;
		&lt;/portlet-ref&gt;
		&lt;supports&gt;
			&lt;action-key&gt;ADD_COMMENT&lt;/action-key&gt;
			&lt;action-key&gt;DELETE&lt;/action-key&gt;
			&lt;action-key&gt;PERMISSIONS&lt;/action-key&gt;
			&lt;action-key&gt;UPDATE&lt;/action-key&gt;
			&lt;action-key&gt;VIEW&lt;/action-key&gt;
		&lt;/supports&gt;
		&lt;community-defaults&gt;
			&lt;action-key&gt;VIEW&lt;/action-key&gt;
		&lt;/community-defaults&gt;
		&lt;guest-defaults&gt;
			&lt;action-key&gt;VIEW&lt;/action-key&gt;
		&lt;/guest-defaults&gt;
		&lt;guest-unsupported&gt;
			&lt;action-key&gt;UPDATE&lt;/action-key&gt;
		&lt;/guest-unsupported&gt;
	&lt;/model-resource&gt;
&lt;/resource-action-mapping&gt;</pre>
<div lang="en">
<div>
<div>
<div>
<h5><a name="d0e1693"></a>Portlet Resource</h5>
</div>
</div>
</div>
<p>In the XML, the first thing defined is the portlet itself. Right under the root element <code><code>&lt;resource-action-mapping&gt;</code></code>, we have a child element called <code>&lt;portlet-resource&gt;</code>. In this element, we define the portlet name, which is 33 in our case. Next, we list all the actions this portlet supports under the <code><code>&lt;supports&gt;</code></code> tag. Keep in mind that this is at the portlet level. To understand what should be listed here, developers should ask themselves what actions belong to the portlet itself or what actions are performed on the portlet that may require a security check. In our case, users need permission to add an entry (<code>ADD_ENTRY</code>), configure blogs portlet settings (<code>CONFIGURATION</code>), and view the blogs itself (<code>VIEW</code>). Each of these supported permissions is within its own <code>&lt;action-key&gt;</code> tag. After we’ve defined all the actions that require a check, we move on to define some of the default permission settings. The <code>community-defaults</code> tag defines what actions are permitted by default for this portlet on the community (group) page the portlet resides. Put it another way, what should a user that has access to the community this portlet resides be able to do minimally? For the blogs portlet, a user with access to the community containing the blogs portlet should be able to view it. Likewise, the <code>guest-defaults</code> tag defines what actions are permitted by default to guests visiting a layout containing this portlet. So if a guest has access to the community page that contains a blogs portlet, the guest should, at the very least, be able to view the portlet according to <code>blogs.xml </code>(not necessarily the content of the portlet). Otherwise, the guest will see an error message within the portlet. Depending on your custom portlet, you may add more actions here that make sense. The <code>guest-unsupported </code>tag contains actions that a visiting guest should never be able to do. For example, the guest visiting the blogs portlet should never be able to add a blog entry since the blog belongs to either a user or a group of users. So even if a user wants to grant guests the ability to add a blog entry to her blog, there is no way for her to grant that permission because the <code>blogs.xml </code>doesn’t permit such an action for guests.</p>
</div>
<div lang="en">
<div>
<div>
<div>
<h5><a name="d0e1736"></a>Model Resource</h5>
</div>
</div>
</div>
<p>After defining the portlet as a resource, we move on to define models within the portlet that also require access check. The model resource is surrounded by the <code>&lt;model-resource&gt;</code> tag. Within this tag, we first define the model name. This must be the fully qualified Java class name of the model. Next we define the portlet name that this model belongs to under the <code>portlet-ref </code>tag. Though unlikely, a model can belong to multiple portlets, which you may use multiple <code>&lt;portlet-name&gt;</code> tags to define. Similar to the portlet resource element, the model resource element also allows you to define a supported list of actions that require permission to perform. You must list out all the performable actions that require a permission check. As you can see for a blog entry, a user must have permission in order to add comments to an entry, delete an entry, change the permission setting of an entry, update an entry, or simply to view an entry. The <code>&lt;community-defaults&gt;</code> tag, the <code>&lt;guest-defaults&gt;</code> tag, and the <code>&lt;guest-unsupported&gt;</code> tag are all similar in meaning to what’s explained for portlet resource in section 3.1.1.</p>
</div>
<div lang="en">
<div>
<div>
<div>
<h5><a name="d0e1759"></a>Default.xml</h5>
</div>
</div>
</div>
<p>After defining your permission scheme for your custom portlet, you then need to tell Liferay the location of this file. For Liferay core, the XML file would normally reside in <code>portal/portal-ejb/classes/resource-actions</code> and a reference to the file would appear in the <code>default.xml </code>file. For the extension environment, the recommended setup is to put your XML file in <code>ext/ext-ejb/classes/resource-actions</code>. Create a file called <code>default-ext.xml</code> and model it after the <code>default.xml</code> file. Add all your custom resource-action XML files in the <code>default-ext.xml</code> file. Then copy the property resource.actions.configs found in <code>portal.properties</code> and paste it into <code>portal-ext.properties</code>. Lastly, add a comma to the end of the property value and then add the path to your <code>default-ext.xml</code> file. (i.e. <code>resource.actions.configs=resource-actions/default.xml,resource-actions/default-ext.xml</code>) Below is an example of the <code>default.xml</code> file.</p>
<pre>&lt;?xml version="1.0"?&gt;

&lt;resource-action-mapping&gt;
	&lt;resource file="resource-actions/portal.xml" /&gt;
	&lt;resource file="resource-actions/blogs.xml" /&gt;
	&lt;resource file="resource-actions/bookmarks.xml" /&gt;
	&lt;resource file="resource-actions/calendar.xml" /&gt;
	&lt;resource file="resource-actions/communities.xml" /&gt;
	&lt;resource file="resource-actions/documentlibrary.xml" /&gt;
	&lt;resource file="resource-actions/imagegallery.xml" /&gt;
	&lt;resource file="resource-actions/journal.xml" /&gt;
	&lt;resource file="resource-actions/messageboards.xml" /&gt;
	&lt;resource file="resource-actions/polls.xml" /&gt;
	&lt;resource file="resource-actions/shopping.xml" /&gt;
	&lt;resource file="resource-actions/wiki.xml" /&gt;
&lt;/resource-action-mapping&gt;</pre>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1799"></a>Adding Resources</h4>
</div>
</div>
</div>
<p>After defining resources and actions, the next task is to write code that adds resources into the permissioning system. A lot of the logic to add resources is encapsulated in the <code>ResourceLocalServiceImpl</code> class. So adding resources is as easy as calling the add resource method in <code>ResourceLocalServiceUtil</code> class.</p>
<pre>public void addResources(
	String companyId, String groupId, String userId, String name,
	String primKey, boolean portletActions,
	boolean addCommunityPermissions, boolean addGuestPermissions);</pre>
<p>For all the Java objects that require access permission, you need to make sure that they are added as resources every time a new one is created. For example, every time a user adds a new entry to her blog, the <code>addResources</code>(…) method is called to add the new entry to the resource system. Here’s an example of the call from the <code>BlogsEntryLocalServiceImpl </code>class.</p>
<pre>ResourceLocalServiceUtil.addResources(
	entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
	BlogsEntry.class.getName(), entry.getPrimaryKey().toString(),
	false, addCommunityPermissions, addGuestPermissions);</pre>
<p>The parameters <code>companyId</code>, <code>groupId</code>, and<code> userId </code>should be self explanatory. The <code>name</code> parameter is the fully qualified Java class name for the resource object being added. The <code>p</code><code>rimKey </code>parameter is the primary key of the resource object. As for the <code>portletActions</code> parameter, set this to true if you’re adding portlet action permissions. In our example, we set it to <code>false</code> because we’re adding a model resource, which should be associated with permissions related to the model action defined in <code>blogs.xml</code>. The <code>addCommunityPermissions</code> and the <code>addGuestPermissions</code> parameters are inputs from the user. If set to true, <code>ResourceLocalService</code> will then add the default permissions to the current community group and the guest group for this resource respectively.</p>
<div lang="en">
<div>
<div>
<div>
<h5><a name="d0e1859"></a>UI Interface</h5>
</div>
</div>
</div>
<p>If you would like to provide your user the ability to choose whether to add the default community permission and the guest permission for the resources within your custom portlet, Liferay has a custom JSP tag you may use to quickly add that functionality. Simply insert the <code>&lt;liferay-ui:input-permissions /&gt;</code> tag into the appropriate JSP and the checkboxes will show up on your JSP. Of course, make sure the tag is within the appropriate <code>&lt;form&gt;</code> tags.</p>
</div>
<div lang="en">
<div>
<div>
<div>
<h5><a name="d0e1870"></a>Deleting Resources</h5>
</div>
</div>
</div>
<p>To prevent having a lot of dead resources taking up space in the <code>Resource_ </code>database table, you must remember to remove them from the <code>Resource_ </code>table when the resource is no longer applicable. Simply call the <code>deleteResource(…)</code> method in <code>ResourceLocalServiceUtil</code>. Here’s an example of a blogs entry being removed:</p>
<pre>ResourceLocalServiceUtil.deleteResource(
	entry.getCompanyId(), BlogsEntry.class.getName(),
	Resource.TYPE_CLASS, Resource.SCOPE_INDIVIDUAL,
	entry.getPrimaryKey().toString());</pre>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1889"></a>Adding Permission</h4>
</div>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h5><a name="d0e1892"></a>Portlet Permission</h5>
</div>
</div>
</div>
<p>On the portlet level, no code needs to be written in order to have the permission system work for your custom portlet. Your custom portlet will automatically have all the permission features. If you’ve defined any custom permissions (supported actions) in your portlet-resource tag in section 3.1, those are automatically added to a list of permissions and users can readily choose them. Of course, for your custom permissions to have any value, you’ll need to show or hide certain functionality in your portlet. You can do that by checking the permission first before performing the intended functionality. This will be covered in section 3.4.</p>
</div>
<div lang="en">
<div>
<div>
<div>
<h5><a name="d0e1897"></a>Model Permission</h5>
</div>
</div>
</div>
<p>In order to allow a user to set permissions on the model resources, you will need to expose the permission interface to the user. This can be done by adding two Liferay UI tag to your JSP. The first one is the <code>&lt;liferay-security:permissionsURL&gt;</code> tag which returns a URL that takes the user to the page to configure the permission settings. The second tag is the <code>&lt;liferay-ui:icon&gt;</code> tag that shows a permission icon to the user. Below is an example found in the file <code>view_entry_content.jsp.</code></p>
<pre>&lt;liferay-security:permissionsURL
	modelResource="&lt;%= BlogsEntry.class.getName() %&gt;"
	modelResourceDescription="&lt;%= entry.getTitle() %&gt;"
	resourcePrimKey="&lt;%= entry.getPrimaryKey().toString() %&gt;"
	var="entryURL"
/&gt;

&lt;liferay-ui:icon image="permissions" url="&lt;%= entryURL %&gt;" /&gt;</pre>
<p>The attributes you need to provide to the first tag are <code>modelResource</code>, <code>modelResourceDescription</code>, <code>resourcePrimKey</code>, and var. The <code>modelResource</code> attribute is the fully qualified Java object class name. It then gets translated in <code>Language.properties</code> to a more readable name (underlined in red in figure 3.3.2.1).</p>
<pre>model.resource.com.liferay.portlet.blogs.model.BlogsEntry=Entry</pre>
<div><img src="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/blogsentrypermission.gif" alt="" /></div>
<p>As for the <code>modelResourceDescription</code> attribute, you can pass in anything that best describes this model instance. In the example, the blogs title was passed in, which is reflected in figure 3.3.2.1 with the blue underline. The <code>resourcePrimKey </code>attribute is simply the primary key of your model instance. The<code> var </code>attribute is the variable name this URL String will get assigned to. This variable is then passed to the <code>&lt;liferay-ui:icon&gt;</code> tag so the permission icon will have the proper URL link. There’s also an optional attribute <code>redirect </code>that’s available if you want to override the default behavior of the upper right arrow link shown in figure 3.3.2.1. That is all you need to do to enable users to configure the permission settings for model resources!!</p>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e1949"></a>Checking Permissions</h4>
</div>
</div>
</div>
<p>The last major step to implementing permission to your custom portlet is to check permission. This may be done in a couple of places. For example, your business layer should check for permission before deleting a resource, or your user interface should hide a button that adds a model (e.g., a calendar event) if the user does not have permission to do so.</p>
<div lang="en">
<div>
<div>
<div>
<h5><a name="d0e1954"></a>Checking Portlet Resource Permission</h5>
</div>
</div>
</div>
<p>Similar to the other steps, the default permissions for the portlet resources are automatically checked for you. You do not need to implement anything for your portlet to discriminate whether a user is allowed to view or to configure the portlet itself. However, you do need to implement any custom permission you have defined in your resource-actions XML file. In the blogs portlet example, one custom supported action is <code>ADD_ENTRY</code>. There are two places in the source code that check for this permission. The first one is in the file <code>view_entries.jsp</code>. The presence of the add entry button is contingent on whether the user has permission to add entry (and also whether the user is in tab one).</p>
<pre>&lt;%
boolean showAddEntryButton = tabs1.equals("entries") &amp;&amp; PortletPermission.contains(permissionChecker, plid, PortletKeys.BLOGS, ActionKeys.ADD_ENTRY);
%&gt;</pre>
<p>The second place that checks for the add entry permission is in the file <code>BlogsEntryServiceImpl</code>. (Notice the difference between this file and the <code>BlogsEntryLocalServiceImpl</code>.) In the <code>addEntry(…)</code> method, a call is made to check whether the incoming request has permission to add entry.</p>
<pre>PortletPermission.check(
	getPermissionChecker(), plid, PortletKeys.BLOGS,
	ActionKeys.ADD_ENTRY);</pre>
<p>If the check fails, it throws a <code>PrincipalException</code> and the add entry request aborts. You’re probably wondering what the PortletPermission class and the PermissionChecker class do. Let’s take a look at these two classes.</p>
<div lang="en">
<div>
<div>
<div>
<h6><a name="d0e1985"></a>PermissionChecker</h6>
</div>
</div>
</div>
<p>The PermissionChecker class has a method called <code>hasPermission(…)</code> that checks whether a user making a resource request has the necessary access permission. If the user is not signed in (guest user), it checks for guest permissions. Otherwise, it checks for user permissions. This class is available to you in two places. First in your business logic layer, you can obtain an instance of the PermissionChecker by calling the <code>getPermissionChecker()</code> method inside your <code>ServiceImpl</code> class. This method is available because all <code>ServiceImpl</code> (not <code>LocalServiceImpl</code>) extends the <code>PrincipalBean</code> class, which implements the <code>getPermissionChecker()</code> method. The other place where you can obtain an instance of the PermissionChecker class is in your JSP files. If your JSP file contains the portlet tag <code>&lt;portlet:defineObjects /&gt;</code> or includes another JSP file that does, you’ll have an instance of the PermissionChecker class available to you via the <code>permissionChecker</code> variable. Now that you know what the <code>PermissionChecker </code>does and how to obtain an instance of it, let’s take a look at Liferay’s convention in using it.</p>
</div>
<div lang="en">
<div>
<div>
<div>
<h6><a name="d0e2020"></a>PortletPermission</h6>
</div>
</div>
</div>
<p><code>PortletPermission</code> is a helper class that makes it easy for you to check permission on portlet resources (as oppose to model resources, covered later in section 3.4.2). It has two static methods called <code>check(…)</code> and another two called <code>contains(…)</code>. They are all essentially the same. The two differences between them are:</p>
<div>
<ol type="1">
<li>Only one <code>check(…) </code>method and one <code>contains(…)</code> method take in the portlet layout ID variable (<code>plid</code>).</li>
<li>The <code>check(…)</code> methods throw a new <code>PrincipalException</code> if user does not have permission, and the <code>contains(…) </code>methods return a boolean indicating whether user has permission.</li>
</ol>
</div>
<p>The <code>contains(…)</code> methods are meant to be used in your JSP files since they return a boolean instead of throwing an exception. The check(…) methods are meant to be called in your business layer (ServiceImpl). Let’s revisit the blogs portlet example below. (The addEntry(…) method is found in BlogsEntryServiceImpl.)</p>
<pre>public BlogsEntry addEntry(
		String plid, String categoryId, String[] tags, String title,
		String content, int displayDateMonth, int displayDateDay,
		int displayDateYear, int displayDateHour, int displayDateMinute,
		boolean addCommunityPermissions, boolean addGuestPermissions)
throws PortalException, SystemException {

	PortletPermission.check(
		getPermissionChecker(), plid, PortletKeys.BLOGS,
		ActionKeys.ADD_ENTRY);

	return BlogsEntryLocalServiceUtil.addEntry(
		getUserId(), plid, categoryId, tags, title, content,
		displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
		displayDateMinute, addCommunityPermissions, addGuestPermissions);
}</pre>
<p>Before the <code>addEntry(…)</code> method calls <code>BlogsEntryLocalServiceUtil.addEntry(…)</code> to add a blogs entry, it calls <code>PortletPermission.check(…)</code> to validate user permission. If the check fails, a <code>PrincipalException</code> is thrown and an entry will not be added. Note the parameters passed into the method. Again, the <code>getPermissionChecker()</code> method is readily available in all <code>ServiceImpl</code> classes. The <code>plid </code>variable is passed into the method by its caller (most likely from a <code>PortletAction</code> class). <code>PortletKeys.BLOGS</code> is just a static <code>String</code> indicating that the permission check is against the blogs portlet. <code>ActionKeys.ADD_ENTRY</code> is also a static String to indicate the action requiring the permission check. You’re encouraged to do likewise with your custom portlet names and custom action keys.</p>
<p>Whether you need to pass in a portlet layout ID (plid) depends on whether your custom portlet supports multiple instances. Let’s take a look at the message board portlet for example. A community may need three separate page layouts, each having a separate instance of the message board portlet. Only by using the portlet layout ID will the permission system be able to distinguish the three separate instances of the message board portlet. This way, permission can be assigned separately in all three instances. Though in general, most portlets won’t need to use the portlet layout ID in relation to the permission system.</p>
</div>
<div lang="en">
<div>
<div>
<div>
<h6><a name="d0e2102"></a>Service vs. LocalService</h6>
</div>
</div>
</div>
<p>Since the <code>ServiceImpl</code> class extends the <code>PrincipalBean</code> class, it has access to information of the current user making the service request. Therefore, the <code>ServiceImpl</code> class is the ideal place in your business layer to check user permission. Liferay’s convention is to implement the actual business logic inside the <code>LocalServiceImpl</code> methods, and then the <code>ServiceImpl</code> calls these methods via the <code>LocalServiceUtil</code> class after the permission check completes successfully. Your <code>PortletAction</code> classes should make calls to <code>ServiceUtil</code> (wrapper to <code>ServiceImpl</code>) guaranteeing that permission is first checked before the request is fulfilled.</p>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h5><a name="d0e2134"></a>Checking Model Resource Permission</h5>
</div>
</div>
</div>
<p>Checking model resource permission is very similar to checking portlet resource permission. The only major difference is that instead of calling methods found in the PortletPermission class mention previously, you need to create your own helper class to assist you in checking permission. The next section will detail how this is done.</p>
<div lang="en">
<div>
<div>
<div>
<h6><a name="d0e2139"></a>Custom Permission Class</h6>
</div>
</div>
</div>
<p>It is advisable to have a helper class to help check permission on your custom models. This custom permission class is similar to the PortletPermission class but is tailored to work with your custom models. While you can implement this class however you like, we encourage you to model after the PortletPermission class, which contains four static methods. Let’s take a look at the <code>BlogsEntryPermission</code> class.</p>
<pre>public class BlogsEntryPermission {

	public static void check(
			PermissionChecker permissionChecker, String entryId,
			String actionId)
		throws PortalException, SystemException {

		if (!contains(permissionChecker, entryId, actionId)) {
			throw new PrincipalException();
		}
	}

	public static void check(
			PermissionChecker permissionChecker, BlogsEntry entry,
			String actionId)
		throws PortalException, SystemException {

		if (!contains(permissionChecker, entry, actionId)) {
			throw new PrincipalException();
		}
	}

	public static boolean contains(
			PermissionChecker permissionChecker, String entryId,
			String actionId)
		throws PortalException, SystemException {

		BlogsEntry entry = BlogsEntryLocalServiceUtil.getEntry(entryId);

		return contains(permissionChecker, entry, actionId);
	}

	public static boolean contains(
			PermissionChecker permissionChecker, BlogsEntry entry,
			String actionId)
		throws PortalException, SystemException {

		return permissionChecker.hasPermission(
			entry.getGroupId(), BlogsEntry.class.getName(),
			entry.getPrimaryKey().toString(), actionId);
	}
}</pre>
<p>Again, the two check(…) methods are meant to be called in your business layer, while the two contains(…) methods can be used in your JSP files. As you can see, it’s very similar to the PortletPermission class. The two notable differences are:</p>
<div>
<ol type="1">
<li>Instead of having the <code>portletId</code> as one of the parameters, the methods in this custom class take in either an <code>entryId</code> or a <code>BlogsEntry</code> object.</li>
<li>None of the methods need to receive the portlet layout ID (<code>plid</code>) as a parameter. (Your custom portlet may choose to use the portlet layout ID if need be.)</li>
</ol>
</div>
<p>Let’s see how this class is used in the blogs portlet code.</p>
<pre>public BlogsEntry getEntry(String entryId) throws PortalException, SystemException {

	BlogsEntryPermission.check(
		getPermissionChecker(), entryId, ActionKeys.VIEW);

	return BlogsEntryLocalServiceUtil.getEntry(entryId);
}</pre>
<p>In the <code>BlogsEntryServiceImpl</code> class is a method called <code>getEntry(…)</code>. Before this method returns the blogs entry object, it calls the custom permission helper class to check permission. If this call doesn’t throw an exception, the entry is retrieved and returned to its caller.</p>
<pre>&lt;c:if test="&lt;%= BlogsEntryPermission.contains(permissionChecker, entry, ActionKeys.UPDATE) %&gt;"&gt;
	&lt;portlet:renderURL windowState="&lt;%= WindowState.MAXIMIZED.toString() %&gt;" var="entryURL"&gt;
		&lt;portlet:param name="struts_action" value="/blogs/edit_entry" /&gt;
		&lt;portlet:param name="redirect" value="&lt;%= currentURL %&gt;" /&gt;
		&lt;portlet:param name="entryId" value="&lt;%= entry.getEntryId() %&gt;" /&gt;
	&lt;/portlet:renderURL&gt;

	&lt;liferay-ui:icon image="edit" url="&lt;%= entryURL %&gt;" /&gt;
&lt;/c:if&gt;</pre>
<p>In the <code>view_entry_content.jsp</code> file, the <code>BlogsEntryPermission.contains(…) </code>method is called to check whether or not to show the edit button. That’s all there is to it!</p>
</div>
</div>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h3><a name="d0e2192"></a>1.4. Summary</h3>
</div>
</div>
</div>
<p>Let’s review what we’ve just covered. Implementing permission into your custom portlet consists of four main steps. First step is to define any custom resources and actions. Next step is to implement code to register (or add) any newly created resources such as a <code>BlogsEntry</code> object. The third step is to provide an interface for the user to configure permission. Lastly, implement code to check permission before returning resources or showing custom features. Two major resources are portlets and Java objects. There is not a lot that needs to be done for the portlet resource to implement the permission system since Liferay Portal has a lot of that work done for you. You mainly focus your efforts on any custom Java objects you’ve built. You’re now well on your way to implement security to your custom Liferay portlets! For other user guides, please visit the <a href="http://www.liferay.com/web/guest/products/documentation" target="_top">Liferay documentation page</a></p>
</div>
<div lang="en">
<div>
<div>
<div>
<h3><a name="d0e2202"></a>1.5. Information</h3>
</div>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e2205"></a>Roles</h4>
</div>
</div>
</div>
<p>If you’re wondering how the Liferay user roles, community roles, and organization / location roles should be implemented in your custom portlet, this brief section will address that. The short answer is, nothing needs to be developed specifically for user, community, and organization / location roles to work with your custom portlets. Liferay’s permission system has all that provided for you. When the <code>hasUserPermission(…)</code> method is called within the <code>PermissionChecker</code> class, Liferay checks all the roles the current user has, whether they’re organization / location roles, community roles, or user roles.</p>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e2216"></a>Using Your Own Security System in Liferay</h4>
</div>
</div>
</div>
<p>Here’s a brief outline of how you can use your own security system in Liferay.</p>
<div>
<ul>
<li>Create your own <code>PermissionChecker</code> class that extends Liferay’s <code>PermissionChecker</code> class.</li>
<li>Register this new class in <code>portal.properties</code> (or <code>portal-ext.properties</code> for the EXT environment) under the <code>permissions.checker</code> property.</li>
<li>Override the <code>hasUserPermission(…)</code> method and the <code>hasGuestPermission(…)</code> method with your own calls to your permission system.</li>
<li>You can call the <code>setValues(…)</code> method to pull in parameters from the request object that your permission checker might need (e.g., <code>userId, projected</code>, etc).</li>
<li>You can call the <code>resetValues(…)</code> method to wipe out old parameters.</li>
<li>Override the <code>isAdmin(…)</code> method.</li>
</ul>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h4><a name="d0e2273"></a>Database Schema View</h4>
</div>
</div>
</div>
<p>Reviewing how Liferay stores all the permission information in the database may help you gain a better understanding to the entire permission system.</p>
<div>
<ul>
<li>The <code>resource_</code> table contains all the registered resources outlined in section 3.2.</li>
<li>Every possible secure action that can be done to a resource will result in a row in the <code>permission_ </code>table. For example, a <code>BlogsEntry</code> resource may have a row in <code>permission_</code> for the view action, and another for the update action.
<div><img src="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/permissiontable.gif" alt="" /></div>
</li>
<li>Whether a user has permission to a resource depends on the roles the user has, or the community (groups) and organization the user is in (green tables). If those roles or groups contain the needed <code>permissionId</code> in the permissions table (in blue), then the user has access to the resource.
<div><img src="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/liferay_permissions.gif" alt="" /></div>
</li>
</ul>
</div>
</div>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h2><a name="d0e2305"></a>2. User service</h2>
</div>
</div>
</div>
<p>The User service allows the management of the portal user and it&#8217;s communities (aka Groups), Roles and UserGroups. It can be accessed through the static methods of UserServiceUtil. Following is a description of it&#8217;s most important methods:</p>
<pre>	public static com.liferay.portal.model.User addUser(
		java.lang.String companyId, boolean autoUserId,
		java.lang.String userId, boolean autoPassword,
		java.lang.String password1, java.lang.String password2,
		boolean passwordReset, java.lang.String emailAddress,
		java.util.Locale locale, java.lang.String firstName,
		java.lang.String middleName, java.lang.String lastName,
		java.lang.String nickName, java.lang.String prefixId,
		java.lang.String suffixId, boolean male, int birthdayMonth,
		int birthdayDay, int birthdayYear, java.lang.String jobTitle,
		java.lang.String organizationId, java.lang.String locationId,
		boolean sendEmail)
		throws com.liferay.portal.PortalException,
			com.liferay.portal.SystemException, java.rmi.RemoteException;</pre>
<p>Add a new user inserting in its profile the provided information</p>
<pre>	public static com.liferay.portal.model.User updateUser(
		java.lang.String userId, java.lang.String password,
		java.lang.String emailAddress, java.lang.String languageId,
		java.lang.String timeZoneId, java.lang.String greeting,
		java.lang.String resolution, java.lang.String comments,
		java.lang.String firstName, java.lang.String middleName,
		java.lang.String lastName, java.lang.String nickName,
		java.lang.String prefixId, java.lang.String suffixId, boolean male,
		int birthdayMonth, int birthdayDay, int birthdayYear,
		java.lang.String smsSn, java.lang.String aimSn, java.lang.String icqSn,
		java.lang.String jabberSn, java.lang.String msnSn,
		java.lang.String skypeSn, java.lang.String ymSn,
		java.lang.String jobTitle, java.lang.String organizationId,
		java.lang.String locationId)
		throws com.liferay.portal.PortalException,
			com.liferay.portal.SystemException, java.rmi.RemoteException;</pre>
<p>Update a user&#8217;s profile with the provided information.</p>
<pre>	public static void addGroupUsers(java.lang.String groupId,
		java.lang.String[] userIds)
		throws com.liferay.portal.PortalException,
			com.liferay.portal.SystemException, java.rmi.RemoteException;</pre>
<p>Add a set of users to a give community (aka Group) identified by the groupId.</p>
<pre>	public static void addRoleUsers(java.lang.String roleId,
		java.lang.String[] userIds)
		throws com.liferay.portal.PortalException,
			com.liferay.portal.SystemException, java.rmi.RemoteException;</pre>
<p>Add a set of users to a give Role identified by the roleId.</p>
<p>For more information check the Portal Javadocs.</p>
</div>
</div>
<div lang="en">
<div>
<div>
<div>
<h2><a name="d0e2328"></a>Chapter 6. Conclusions</h2>
</div>
</div>
</div>
<p>After reading this document you should have a clear idea of what you need to develop and deploy a portlet in Liferay. It has also covered the most important resources and services that Liferay provides to portlet developers.</p>
<p>After reading this document we recommend reading more articles and information about portlet development and/or attend one of the available training sessions.</p>
<p>Source: <a href="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/">http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/</a></p>
</div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lyphuong10.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lyphuong10.wordpress.com/127/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lyphuong10.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lyphuong10.wordpress.com/127/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/lyphuong10.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/lyphuong10.wordpress.com/127/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/lyphuong10.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/lyphuong10.wordpress.com/127/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lyphuong10.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lyphuong10.wordpress.com/127/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lyphuong10.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lyphuong10.wordpress.com/127/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lyphuong10.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lyphuong10.wordpress.com/127/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=127&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://lyphuong10.wordpress.com/2011/08/10/liferay-portal-4-portlet-development-guide/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/8b8638691b0148442a47955d24cc60c1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">lyphuong10</media:title>
		</media:content>

		<media:content url="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/note.png" medium="image">
			<media:title type="html">[Note]</media:title>
		</media:content>

		<media:content url="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/note.png" medium="image">
			<media:title type="html">[Note]</media:title>
		</media:content>

		<media:content url="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic1.gif" medium="image" />

		<media:content url="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic2.gif" medium="image" />

		<media:content url="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic5.gif" medium="image" />

		<media:content url="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic3.gif" medium="image" />

		<media:content url="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic4.gif" medium="image" />

		<media:content url="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic6.gif" medium="image" />

		<media:content url="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic7.gif" medium="image" />

		<media:content url="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic8.gif" medium="image" />

		<media:content url="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic9.gif" medium="image" />

		<media:content url="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic10.gif" medium="image" />

		<media:content url="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/pic11.gif" medium="image" />

		<media:content url="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/adminhotdeploy.jpg" medium="image" />

		<media:content url="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/blogsentrypermission.gif" medium="image" />

		<media:content url="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/permissiontable.gif" medium="image" />

		<media:content url="http://content.liferay.com/4.2/doc/devel/liferay_4_portlet_development_guide/onepage/images/liferay_permissions.gif" medium="image" />
	</item>
		<item>
		<title>Step1: From DB to simple UI</title>
		<link>http://lyphuong10.wordpress.com/2011/08/10/step1-from-db-to-simple-ui/</link>
		<comments>http://lyphuong10.wordpress.com/2011/08/10/step1-from-db-to-simple-ui/#comments</comments>
		<pubDate>Wed, 10 Aug 2011 13:29:51 +0000</pubDate>
		<dc:creator>lyphuong10</dc:creator>
				<category><![CDATA[Web JSP Servlet]]></category>

		<guid isPermaLink="false">http://lyphuong10.wordpress.com/?p=125</guid>
		<description><![CDATA[Pet Catalog (or PetStore) is a most popular &#8220;HelloWorld&#8221; for J2EE technologies. Many tutorials, explained some new technology use it for demonstrating advantages, promised by this technology. Many of us started to study J2EE from these examples. Last of them readed by me was about PetStore on JSF 2.0 &#38; EJB 3.1 in J2EE 6.0 [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=125&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Pet Catalog (or PetStore) is a most popular &#8220;HelloWorld&#8221; for J2EE technologies. Many tutorials, explained some new technology use it for demonstrating advantages, promised by this technology. <span id="more-125"></span>Many of us started to study J2EE from these examples. Last of them readed by me was about PetStore on JSF 2.0 &amp; EJB 3.1 in J2EE 6.0 (<a href="http://weblogs.java.net/blog/caroljmcdonald/archive/2009/08/java_ee_6_pet_c.html">http://weblogs.java.net/blog/caroljmcdonald/archive/2009/08/java_ee_6_pet_c.html</a>)<br />
But, there are no such example in Liferay. Liferay site said to use WOL (World Of Liferay) as such PetStore, but, these portlets (even they implemented some very useful functionality) not so easy to people just come into Liferay portlets development to study how to do it).<br />
So, I&#8217;ve decided to write same example, but as Liferay Portlet</p>
<h2>What we are going to do</h2>
<p>During developing Pet Catalog for Liferay we will:</p>
<ul>
<li>Install Liferay and Liferay Plugins SDK;</li>
<li>Create Simple Project;</li>
<li>Configure Eclipse to use it (it is not necessary and any other IDE may be used);</li>
<li>Discuss technologies used inside Liferay;</li>
<li>Developing DB entities &amp; Services with using Service Builder;</li>
<li>Developing UI with using JSPPortlet.</li>
</ul>
<p>Some Liferay specific UI features (like tags to implement tables with paginator) will be discussed also.<br />
Not so much &#8211; but it is only first tutorial and I hope (if it will be interesting) to continue this series with more tutorials explained basic Liferay functionality and services.</p>
<p>All sources for this step available at SVN: <a href="https://emforge.svn.sourceforge.net/svnroot/emforge/experiments/petcatalog-portlet/step1/petcatalog-portlet/">https://emforge.svn.sourceforge.net/svnroot/emforge/experiments/petcatalog-portlet/step1/petcatalog-portlet/</a> or you can browse them via <a href="http://www.emforge.net/web/liferay-petstore-portlet/sources">Project Sources</a></p>
<h2>Install Liferay and Plugins SDK</h2>
<p>Simplest way to start using liferay &#8211; is download Liferay version bundled with some server &#8211; for example tomcat 6.0 (default configuration) from SourceForge site (<a href="https://sourceforge.net/projects/lportal/files/Liferay%20Portal/5.2.3/liferay-portal-tomcat-6.0-5.2.3.zip/download">https://sourceforge.net/projects/lportal/files/Liferay%20Portal/5.2.3/liferay-portal-tomcat-6.0-5.2.3.zip/download</a>). After download unzip it somewhere (lets say <em>&lt;path_to_liferay&gt;</em>), go to tomcat bin directory (<em>&lt;path_to_liferay&gt;/tomcat-6.0.18/bin</em>) and run tomcat (./startup.sh)<br />
Liferay ships with tomcat preconfigured to run liferay, so, all required memory settings, as well as preinstalled applications are ready to use &#8211; and simple run should work (ok, in my case it is working in 99%). To be sure liferay started well &#8211; you need to check logs (<em>&lt;path_to_liferay&gt;/tomcat-6.0.18/log/catalina.out</em>). After about 3-5 minutes &#8211; server should be run and ready to use.<br />
To validate it &#8211; navigate your browser to <a href="http://localhost:8080/">http://localhost:8080</a> &#8211; you should see default liferay page with 7Coz demo. To login as Admin simple click on &#8220;Login as Bruno Admin&#8221; link<br />
There are different ways to develop portlets for Liferay &#8211; more details you can read in liferay wiki (<a href="http://www.liferay.com/web/guest/community/wiki/-/wiki/Main/How+do+you+develop+-+Development+Strategies">http://www.liferay.com/web/guest/community/wiki/-/wiki/Main/How+do+you+develop+-+Development+Strategies</a>). We will use Plugin SDK Environment. To develop portlets in Plugins Environment we need to download Plugins SDK (again, from SourceForge: <a href="https://sourceforge.net/projects/lportal/files/Liferay%20Portal/5.2.3/liferay-plugins-sdk-5.2.3.zip/download">https://sourceforge.net/projects/lportal/files/Liferay%20Portal/5.2.3/liferay-plugins-sdk-5.2.3.zip/download</a>), unzip it somewhere (<em>&lt;path_to_plugins&gt;</em>) and edit <em>&lt;</em><em>path_to_plugins</em><em>&gt;/build.properties</em> to point correct portal installation (uncommented property <em>app.server.dir</em> should point to <em>&lt;path_to_liferay&gt; </em>in our case).</p>
<h2>Create Portlet Project</h2>
<p>To start new portlet project switch to <em>&lt;</em><em>path_to_plugins</em><em>&gt;/portlets</em> and call</p>
<pre># ant -Dportlet.name=petcatalog -Dportlet.display.name="Pet Catalog" create
</pre>
<p>(I hope you have ant and java installed!)<br />
As result, it will create folder <em>petcatalog-portlet </em>with required project structure and some initial files</p>
<h3>What we have inside</h3>
<p>Inside we have:</p>
<ul>
<li><strong>build.xml</strong> &#8211; is an ant-file to build/deploy our project. Please, note &#8211; since this file is referenced to ant-files from plugins-sdk &#8211; this project cannot be moved somethere out of plugins-sdk;</li>
<li><strong>docroot</strong> &#8211; root of portlet &#8211; actually it is root of web-application;</li>
<li><strong>docroot/WEB-INF</strong> &#8211; standard folder with configuration files;</li>
<li><strong>docroot/WEB-INF/portlet.xml</strong> &amp; <strong>docroot/WEB-INF/liferay-portlet.xml</strong> &#8211; description of portlets implemented in plugin;</li>
<li><strong>docroot/WEB-INF/liferay-display.xml</strong> &#8211; file defined how this portlet displayed in applications menu in liferay;</li>
<li><strong>docroot/WEB-INF/liferay-plugin-package.properties</strong> &#8211; file contains some packaging options for the project;</li>
<li><strong>docroot/WEB-INF/src</strong> &#8211; java-sources;</li>
</ul>
<h2>Configure Eclipse Project</h2>
<p>This step is not required &#8211; actually you can do everything described later in any IDE and command-line, but I&#8217;ve used to use Eclipse and feel myself much more comfortable in it. So, we will setup eclipse project to work on portlet. To do it switch into portlet folder (<em>&lt;path_to_liferay&gt;/portlets/petcatalog-portlet</em>) and call</p>
<pre># ant setup-eclipse
</pre>
<p>This command will create required Eclipse project files.<br />
Before we will import generated project into Eclipse workspace, we need to get portal sources. It is not required fro command-line build, but project generated has some dependencies to this portal project, so, we need to have it in workspace. Simple import portal project from SVN <a href="http://svn.liferay.com/repos/public/portal/tags/5.2.3/">http://svn.liferay.com/repos/public/portal/tags/5.2.3/</a> into workspace (please not &#8211; it will take some &#8211; quite long &#8211; time since project quite big)<br />
Now we can import generated portlet project into workspace also</p>
<h3>Configure Tomcat server under Eclipse</h3>
<p>Now, to be able to run and debug portal (and our portlet) under Eclipse we need configure Liferay&#8217;s tomcat server under Eclipse:</p>
<ol>
<li>Define Tomcat 6.0 Runtime (Window -&gt; Preferences -&gt; Server -&gt; Runtime Environment -&gt; Add -&gt; Apache Tomcat 6.0) and point it to tomcat in Liferay (<em>&lt;path_to_liferay&gt;/tomcat-6.0.18</em>)</li>
<li>Create Liferay server instance (Services Tab -&gt; New -&gt; Server)</li>
<li>Configure it (double click on created server):
<ol>
<li>Increase Timeouts to something big enough;</li>
<li>Server Locations -&gt; Switch to &#8220;Use Tomcat Installation&#8221;;</li>
<li>Set standard Liferay Java options: Open Launch Configuration -&gt; Arguments Tab -&gt; VM Arguments -&gt; Add <strong>-Xms128m -Xmx1024m -XX:<a title="MaxPermSize" href="https://www.assembla.com/wiki/show/speakenergy/MaxPermSize">MaxPermSize</a>=128m -Dfile.encoding=UTF8 -Duser.timezone=GMT</strong></li>
<li>Add sources of projects (to make it possible to debug): Open Launch Configuration -&gt; Source Tab -&gt; Add -&gt; Java Project -&gt; Select both &#8211; portal &amp; portlet projects</li>
</ol>
</li>
</ol>
<p><strong><img src="http://www.emforge.net/image/image_gallery?uuid=1482a7b0-7ed9-422c-9094-b40bc1f1d8a1&amp;groupId=10919&amp;t=1262181344811" alt="" width="640" height="484" align="middle" /><br />
</strong></p>
<p>Now, you should be able to start Liferay in Eclipse and see it&#8217;s log file in Console view.<br />
latest step to setup ant-target. Open Ant View (Window -&gt; Show View -&gt; Ant) and drag&amp;drop build.xml from portlet project into this view. Now, you will able to call required target (like deploy) for our portlet by double-click on it in this view</p>
<h2>What Technologies will be used in Portlet Development</h2>
<p>OK, now we are ready to start for real development, but before lets shortly list of technologies Liferay used or we will use.<br />
For working with Database Liferay used <strong>Hibernate</strong>. In our cae we will not have care about hibernate mappings and configuration, since everything is done by Liferay core, or will be done for us by ServiceBuilder.<br />
Spring Framework widelly used in Liferay to link different components, but again &#8211; we do not need care about it too much &#8211; since all required bean configuration will be done for us by ServiceBuilder<br />
There are different frameworks available to use for Portlets UI development: Struts, Spring MVC, JSF (including IceFaces or RichFaces) and many more, but, in our case we will use JSP. Yes, yes, it is 2009 year &#8211; but in some cases it is still make sense to use plain, old, good JSP in some project. In our case reasons are:</p>
<ol>
<li>Each portlet (including our own) implemented not a big system, bug small part of functionality. And it is responsibility of Portal (Liferay) to combine them into bigger system;</li>
<li>We do not need templating (like Tiles in Struts or Facelets in JSF) &#8211; since templates usually used to define &#8220;general&#8221; page look: header, footer, borders, but in our case it is responsibility of Liferay &#8211; we only need care about our small part of screen;</li>
<li>With using JSP we can use some very useful tag (like to implement table with paginator);</li>
</ol>
<p>So, be ready to remember your development childhood <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>Working with ServiceBuilder</h2>
<p>ServiceBuilder is a special tool provided by Liferay to build database entities, and services working with them. Speaking in EJB terms it help us to build @Entity and @Stateless beans.<br />
In our example I will use &#8220;simplified&#8221; version of catalog &#8211; same as used in this JSF 2.0 and EJB 3.0 sample &#8211; supported only 1 entity object to edit/display list of pets.<br />
So, to define our entity lets create file docroot/WEB-INF/service.xml with content:</p>
<pre>&lt;?xml version='1.0' encoding='UTF-8' ?&gt;
&lt;!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 5.1.0//EN" "<a href="http://www.liferay.com/dtd/liferay-service-builder_5_1_0.dtd">http://www.liferay.com/dtd/liferay-service-builder_5_1_0.dtd</a>"&gt;
&lt;service-builder package-path='petcatalog'&gt;
    &lt;namespace&gt;PetCatalog&lt;/namespace&gt;

    &lt;!-- Project --&gt;
    &lt;entity name='Item' table='PETS_ITEM' local-service='true' remote-service='false'&gt;
        &lt;!-- PK fields --&gt;
        &lt;column name='itemId' type='long' primary='true'/&gt;
        
        &lt;column name="productId" type="String" /&gt;        
        &lt;column name="name" type="String" /&gt;        
        &lt;column name="description" type="String" /&gt;        
        &lt;column name="imageUrl" type="String" /&gt;        
        &lt;column name="imageThumbUrl" type="String" /&gt;        
        &lt;column name="price" type="double" /&gt;
    &lt;/entity&gt;
&lt;/service-builder&gt;
</pre>
<p>This file described entities (and not only entities &#8211; but we will speak about it later) operating by our portlet. In our case we simple defined same fields as used in JSF2/EJB3.1 PetCatalog sample.<br />
Not, we can generate services classes and files from this description &#8211; simple run target <strong>build-service</strong> in our portlet ant-file. As result of this target followed classes will be generated:</p>
<ul>
<li>Model &amp; Service Implementation classes;</li>
<li>Model &amp; Service Interface &amp; Util classes;</li>
<li>Hibernate mapping, Model Hints, Spring Configuration files.</li>
</ul>
<p>Lets look more details into them</p>
<h3>Model and Service Implementation classes</h3>
<p>You can find them in <em>docroot/WEB-INF/src/petcatalog</em> folder (<em>petcatalog</em> package as it was defined in our service.xml). Model &#8211; is a DB-Model class (same as @Entity in EJB3), Service &#8211; is a service class &#8211; same as @Statelles in EJB 3.<br />
For both, Model and Service we may see 3 different kind of classes:</p>
<ul>
<li>Base Classes (petcatalog.model.impl.ItemModelImpl &amp; petcatalog.service.base.ItemLocalServiceBaseImpl) &#8211; this classes always generated by ServiceBuilder and implemented basic functionality &#8211; like required accessors for attributes, basic CRUD operations and so on. Since this classes always regenerated by ServiceBuilder &#8211; we should not change them;</li>
<li>Implementation Classes (petcatalog.model.impl.ItemImpl &amp; petcatalog.service.impl.ItemLocalServiceImpl) &#8211; they are inherited from base-classes and used for adding additional logic (methods, attributes not covered by service.xml file) by user. So, if we will like to add some new method into your service &#8211; we will add it into petcatalog.service.impl.ItemLocalServiceImpl)</li>
<li>Interfaces &#8211; will be discussed in next topic, but &#8211; important thing is: interfaces are always generated from implementation. So, after you will add some extra method into your service implementation class &#8211; you will need to call ServiceBuilder again to regenerate interfaces</li>
</ul>
<h3>Model and Service Interface and Util classes</h3>
<p>Will classes placed in docroot/WEB-INF/service folder and compiled into docroot/WEB-INF/lib/petclinic-service.jar. Improtant thing &#8211; these classes always regenerated by service build, so, it does not make sense to do any changes there &#8211; instead you should change Implementation clases discussed before.<br />
Util-class (petcatalog.service.ItemLocalServiceUtil) implemented singleton pattern &#8211; it is used to access Service Implementation instance by using static methods.<br />
In rest portlet code we should use this Util class to access Service functionality, and use Model Interface to operate with models (then real implementation is not required).</p>
<h3>Hibernate mapping, Model Hints, Spring Configuration files</h3>
<p>Additionally ServiceBuilder generated:</p>
<ul>
<li>Hibernate mapping file for our portlet (at <em>docroot/WEB-INF/src/META-INF/portlet-hbm.xml</em>);</li>
<li>Model Hints file (at <em>docroot/WEB-INF/src/META-INF/portlet-model-hints.xml</em>) &#8211; this file contains additional information about model, helped Liferay to build UI &#8211; like length of fileds, format and many more (read Liferay wiki for details: <a href="http://www.liferay.com/web/guest/community/wiki/-/wiki/Main/Customize+DB+Column+Sizes%29;">http://www.liferay.com/web/guest/community/wiki/-/wiki/Main/Customize+DB+Column+Sizes);</a></li>
<li>Same META-INF folder also has several spring-configuration files, most of them as &#8220;default&#8221;, provided hibernate sessionFactory, transactionManager and other &#8220;default&#8221; beans. But it also has portlet-spring.xml which has definitions of our Service and related beans.</li>
</ul>
<p>OK, nice, now, we may implement our UI used this generated service</p>
<h2>Developing UI with using JSPPortlet</h2>
<p>Again, based on simple JSF2.0/EJB3.1 PetCatalog sample we are going to display list of pets and allow user to see details of pet by clicking the link in the table row.</p>
<h3>Define Portlet</h3>
<p>First of all we need to define our portlet. Create target executed in the beginning already created dummy portlet for us. You can check next files:</p>
<ul>
<li>docroot/WEB-INF/portlet.xml &#8211; contains definition of our petcatalog portlet. it said what portlet implemented in <strong>com.sample.jsp.portlet.JSPPortlet</strong> and /view.jsp is used to display portlet content. These settings is ok for us (at least for now), so, keep it like it is;</li>
<li>docroot/WEB-INF/liferay-portlet.xml &#8211; contains some additional (liferay specific) configuration for our portlet. Keep it like it is for now;</li>
<li>docroot/WEB-INF/src/com/sample/jsp/portlet/JSPPortlet.java &#8211; source of our portlet &#8211; currently it did not do anything &#8211; just said to display view.jsp;</li>
<li>docroot/view.jsp &#8211; this jsp will display some default text on portlet display;</li>
</ul>
<p>So, by default SDK generated simple portlet &#8211; we will use it as start-point. So, lets test is it working: run liferay, and run <strong>deploy</strong> target in portlet ant. Checking liferay logs (if you are using Eclipse like I&#8217;m you will see them in Eclipse console view) we can see:<br />
10:42:01,509 INFO  [PortletAutoDeployListener:87] Portlets for /home/akakunin/apps/liferay-portal-5.2.3/deploy/petcatalog-portlet-5.2.3.1.war copied successfully. Deployment will start in a few seconds.</p>
<pre>Oct 15, 2009 10:42:08 AM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring root WebApplicationContext
Loading file:/var/tmp/1-petcatalog-portlet/WEB-INF/classes/service.properties
10:42:08,644 INFO  [DialectDetector:64] Determining dialect for HSQL Database Engine 1
10:42:08,647 WARN  [DialectDetector:79] Liferay is configured to use Hypersonic as its database. Do NOT use Hypersonic in production. Hypersonic is an embedded database useful for development and demo'ing purposes. The database settings can be changed in portal.properties.
10:42:08,649 INFO  [DialectDetector:97] Using dialect org.hibernate.dialect.HSQLDialect
Loading file:/var/tmp/1-petcatalog-portlet/WEB-INF/classes/service.properties
Loading file:/var/tmp/1-petcatalog-portlet/WEB-INF/classes/service.properties
10:42:11,280 INFO  [ServiceComponentLocalServiceImpl:270] Running PetCatalog SQL scripts for the first time
10:42:11,880 INFO  [PortletHotDeployListener:227] Registering portlets for petcatalog-portlet
10:42:12,396 INFO  [PortletHotDeployListener:346] 1 portlet for petcatalog-portlet is available for use
</pre>
<p>Looks like portlet correctly deployed. Now lets check how it is working:</p>
<ul>
<li>Open liferay UI in browser (<a href="http://localhost:8080/">http://localhost:8080</a>),</li>
<li>Login as admin (if you have 7Coz portlet installed, you can simple click on &#8220;Login as Bruno Admin&#8221;, if not, login by default admin: <a href="mailto:test@liferay.com/test%29">test@liferay.com/test)</a></li>
<li>Create new page (&#8220;test&#8221; for example) to place our portlet;</li>
<li>&#8220;Add Application&#8221; on this page &#8211; in popups with list of available applications/portlets we will able to find our &#8220;Pet Catalog&#8221; portlet in &#8220;Sample&#8221; category;</li>
<li>Great! We can see default text &#8220;This is the <strong>Sample JSP Portlet</strong>. Use this as a quick way to include JSPs&#8221; &#8211; everything works fine.</li>
</ul>
<p><strong><img src="http://www.emforge.net/image/image_gallery?uuid=0cd3e874-40af-4253-a9a4-795bdb596c93&amp;groupId=10919&amp;t=1262181440412" alt="" width="425" height="351" align="middle" /><br />
</strong></p>
<h3>Fill data into DB</h3>
<p>In our simplest sample we will not have UI to add new Pets, only to display, so, we need to place them there manually:</p>
<ul>
<li>Stop Liferay;</li>
<li>Open any SQL Client you like (and depending from which DB your Liferay configured to use). By default Liferay configured to use HSQL. HSQL client (which also may be used as client-app) we can find in <em>&lt;path_to_liferay&gt;/tomcat-6.0.18/lib/ext/hsql.jar</em> and DB itself stored in <em>&lt;path_to_liferay&gt;/data/hsql/lportal</em> files.</li>
<li>So, open hsql client by run <strong># java -cp &lt;path_to_liferay&gt;/tomcat-6.0.18/lib/ext/hsql.jar org.hsqldb.util.DatabaseManagerSwing</strong></li>
<li>In opened configuration window use options to connect to file in file-system and use jdbc:hsqldb:file:&lt;path_to_liferay&gt;/hsql/lportal as URL</li>
<li>In opened window we will already see PETS_ITEM in the list of table &#8211; it is because Liferay already created it during first portlet deployment we only need to insert require data;</li>
<li>Execute sample.sql there (you can find this file in docroot/WEB-INF/sql/sample.sql in project archive);</li>
<li>Close client;</li>
</ul>
<p><img src="http://www.emforge.net/image/image_gallery?uuid=521644ff-bea5-432f-8d95-8e598fb471bb&amp;groupId=10919&amp;t=1262181510757" alt="" width="414" height="308" align="middle" /></p>
<h3>Display Table with pets</h3>
<p>To display table with pets we need to change our view.jsp to by follow way:</p>
<pre>&lt;%@ taglib uri="<a href="http://java.sun.com/portlet_2_0">http://java.sun.com/portlet_2_0</a>" prefix="portlet" %&gt;
&lt;%@ taglib uri="<a href="http://liferay.com/tld/ui">http://liferay.com/tld/ui</a>" prefix="liferay-ui" %&gt;

&lt;%@ page import="java.util.ArrayList" %&gt;
&lt;%@ page import="java.util.List" %&gt;

&lt;%@ page import="javax.portlet.PortletURL" %&gt;
&lt;%@ page import="javax.portlet.PortletPreferences" %&gt;
&lt;%@ page import="javax.portlet.WindowState" %&gt;

&lt;%@ page import="com.liferay.portal.kernel.dao.search.ResultRow" %&gt;
&lt;%@ page import="com.liferay.portal.kernel.dao.search.SearchContainer" %&gt;
&lt;%@ page import="com.liferay.portal.kernel.dao.search.SearchEntry" %&gt;

&lt;%@ page import="petcatalog.model.Item" %&gt;

&lt;%@page import="petcatalog.service.ItemLocalServiceUtil"%&gt;&lt;portlet:defineObjects /&gt;

&lt;%
    PortletURL portletURL = renderResponse.createRenderURL();
    
    // define list of headers we will use in the table
    List&lt;String&gt; headerNames = new ArrayList&lt;String&gt;();
    headerNames.add("name");
    headerNames.add("photo");
    headerNames.add("price");

    // create search container, used to display table
    SearchContainer searchContainer = new SearchContainer(renderRequest,
                                                        null, null,
                                                        SearchContainer.DEFAULT_CUR_PARAM,
                                                        SearchContainer.DEFAULT_DELTA,
                                                        portletURL,
                                                        headerNames,
                                                        "There No Pets To Display");
    portletURL.setParameter(searchContainer.getCurParam(), String.valueOf(searchContainer.getCurValue()));
    
    // get count of pets and list of pets to display on current page
    int petsCount = ItemLocalServiceUtil.getItemsCount();
    List&lt;Item&gt; pets = ItemLocalServiceUtil.getItems(searchContainer.getStart(),
                                                    searchContainer.getEnd());
    
    // set count into search container
    searchContainer.setTotal(petsCount);
    
    // fill table
    List&lt;ResultRow&gt; resultRows = searchContainer.getResultRows();
    for (int i=0; i &lt; pets.size(); i++) {
        Item pet = pets.get(i);
        ResultRow row = new ResultRow(pet, pet.getItemId(), i);

        row.addText(pet.getName(), "");
        row.addJSP("/pet_image.jsp", application, request, response);
        row.addText(String.valueOf(pet.getPrice()));

        resultRows.add(row);
    }    
    
    // and finally display it
%&gt;
&lt;liferay-ui:search-iterator searchContainer="&lt;%= searchContainer %&gt;" /&gt;</pre>
<p>This code doing following:</p>
<ul>
<li>Initialized SearchContainer &#8211; special Liferay-sepcific class used to display tables;</li>
<li>Get data (count of pets and specific subset of pets) from our ItemLocalServiceUtil service, generated by ServiceBuilder. As you can see &#8211; some basic functions were generated there automatically;</li>
<li>Fill SearchContainer with data to display;</li>
<li>Display table with using liferay-ui:search-iterator tag</li>
</ul>
<p>As result, default Liferay table should be used to dispplay pets with many functionality like applying styles from theme, pagination and so on.<br />
But &#8211; before we will able to see it we need to do some additional changes:</p>
<h4>Display Pet Images</h4>
<p>Do display pets images in the table we did:</p>
<pre>row.addJSP("/pet_image.jsp", application, request, response);
So, we need to create required JSP file:

&lt;%@ page import="com.liferay.portal.kernel.dao.search.ResultRow" %&gt;
&lt;%@ page import="com.liferay.portal.kernel.util.WebKeys" %&gt;
&lt;%@ page import="petcatalog.model.Item" %&gt;

&lt;%
ResultRow row = (ResultRow)request.getAttribute(WebKeys.SEARCH_CONTAINER_RESULT_ROW);

Item pet = (Item)row.getObject();
%&gt;
&lt;img src="&lt;%= request.getContextPath() %&gt;/images/&lt;%=pet.getImageThumbUrl() %&gt;"/&gt;</pre>
<div>
Quite easy &#8211; it&#8217;s get currently displayed Pet Item object and create image for it<br />
Also, we need to copy images into docroot/images folder (you can get them in example sources)</p>
<h4>Localization Support</h4>
<p>String contstant, used in headerNames are resource-keys. To correctly display headers we need to add localization support. To do it &#8211; add resource-bundle tag into our portlet definition in portlet.xml like:</p>
<pre>            &lt;portlet-mode&gt;VIEW&lt;/portlet-mode&gt;
        &lt;/supports&gt;
<strong> &lt;resource-bundle&gt;petcatalog.messages&lt;/resource-bundle&gt;</strong>
        &lt;portlet-info&gt;
            &lt;title&gt;Projects&lt;/title&gt;
</pre>
<p>And create docroot/WEB-INF/src/petcatalog/messages.properties file:</p>
<pre>photo=Photo</pre>
</div>
<p>name &amp; price is already present in Liferay&#8217;s resources, so, we do not need to translate them. Later you can easily add localization for your portlet<br />
What is all &#8211; try to redeploy portlet and refresh the page<br />
<strong><img src="http://www.emforge.net/image/image_gallery?uuid=6ecf61da-151a-46fc-95aa-3f3e166c825b&amp;groupId=10919&amp;t=1262181586393" alt="" width="755" height="538" align="middle" /><br />
</strong></p>
<h3>Display Pet Details</h3>
<p>To display pet details we we need to change (improve) a little bit our portlet class.<br />
So, lets change portlet.xml to point into new class:</p>
<pre>        &lt;portlet-name&gt;petcatalog&lt;/portlet-name&gt;
        &lt;display-name&gt;Pet Catalog&lt;/display-name&gt;
        &lt;portlet-class&gt;<strong>petcatalog.portlet.PetCatalogPortlet</strong>&lt;/portlet-class&gt;
        &lt;init-param&gt;
</pre>
<p>and create this class extending from  from com.liferay.util.bridges.jsp.JSPPortlet:</p>
<pre>package petcatalog.portlet;
import com.liferay.util.bridges.jsp.JSPPortlet;
public class PetCatalogPortlet extends JSPPortlet {
}
</pre>
<p>Now we can remove old portlet package in com.sample and redeploy -everything should continue to work.<br />
Then we need to change table to correctly generate link to pet details.<br />
On view.jsp, in for loop change how data for first column was added:</p>
<pre>        ResultRow row = new ResultRow(pet, pet.getItemId(), i);

        PortletURL petURL = renderResponse.createRenderURL();
        petURL.setWindowState(WindowState.MAXIMIZED);
        petURL.setParameter("pet_id", String.valueOf(pet.getItemId()));
        petURL.setParameter("redirect", com.liferay.portal.util.PortalUtil.getCurrentURL(request));
        row.addText(pet.getName(), petURL.toString());
        
        
        row.addJSP("/pet_image.jsp", application, request, response);
</pre>
<p>Here we created URL, added petId and currentURL as arguments and added it as link for first column.<br />
Now, lets change our portlet to handle pet_id parameter:</p>
<pre>public class PetCatalogPortlet extends JSPPortlet {
    @Override
    public void doView(RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException {
        // check - do we have pet_id parameter
        Long petId = ParamUtil.getLong(renderRequest, "pet_id");
        if (petId != null &amp;&amp; petId != 0l) {
            // try to get Pet
            try {
                Item pet = ItemLocalServiceUtil.getItem(petId);
                renderRequest.setAttribute("pet", pet);
            } catch (Exception ex) {
                throw new PortletException("Cannot get pet", ex);
            }
            include("/view_pet.jsp", renderRequest, renderResponse);
        } else {
            super.doView(renderRequest, renderResponse);
        }
    }
}
</pre>
<p><strong>doView </strong>method called then portlet is rendered. We just check pet_id parameter, get Catalog Item by id, put it into request attributes and navigate into view_pet.jsp<br />
Last thing &#8211; implement view_pet.jsp:</p>
<pre>&lt;%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %&gt;
&lt;%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %&gt;

&lt;%@ page import="javax.portlet.PortletURL" %&gt;
&lt;%@ page import="javax.portlet.PortletPreferences" %&gt;
&lt;%@ page import="javax.portlet.WindowState" %&gt;
&lt;%@ page import="com.liferay.portal.kernel.util.UnicodeFormatter"%&gt;

&lt;%@ page import="petcatalog.model.Item" %&gt;

&lt;portlet:defineObjects /&gt;

&lt;%
// get pet
Item pet = (Item)request.getAttribute("pet");
String redirect = request.getParameter("redirect");
%&gt;

&lt;table&gt;
    &lt;tr&gt;
        &lt;td&gt;&lt;liferay-ui:message key="name" /&gt;:&lt;/td&gt;
        &lt;td&gt;&lt;%= pet.getName() %&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;&lt;liferay-ui:message key="description" /&gt;:&lt;/td&gt;
        &lt;td&gt;&lt;%= pet.getDescription() %&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;&lt;liferay-ui:message key="photo" /&gt;:&lt;/td&gt;
        &lt;td&gt;&lt;img src="&lt;%= request.getContextPath() %&gt;/images/&lt;%=pet.getImageUrl() %&gt;"/&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;&lt;liferay-ui:message key="price" /&gt;:&lt;/td&gt;
        &lt;td&gt;&lt;%= pet.getPrice() %&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;
&lt;input id="cancelButton" type="button" value="&lt;liferay-ui:message key='cancel' /&gt;"
       onclick="location.href = '&lt;%= UnicodeFormatter.toString(redirect) %&gt;'"/&gt;
</pre>
<p>This JSP will display Pet Details and image, Cancel button will navigate us back into list.</p>
<p><strong><img src="http://www.emforge.net/image/image_gallery?uuid=c86a59a8-7763-4a24-a394-dceed4c1e473&amp;groupId=10919&amp;t=1262181660069" alt="" width="862" height="938" align="middle" /><br />
</strong></p>
<h2>What&#8217;s next?</h2>
<p>Ok, we completed very simple portlet for Liferay. Even it is simple, it covered all parts of web-application &#8211; starting from UI and finishing DB, explained how to create new DB tables and Services in Liferay, how easily write UI sometimes with sometimes not so simple functionality (like paginator).<br />
In next tutorials I hope to cover followed questions:</p>
<ul>
<li>Add new Pet &#8211; process actions in portlets;</li>
<li>Permissions and Authorization for Items;</li>
<li>Better UI: use bookmarkable links;</li>
<li>Dependency management in Portlets;</li>
<li>and many many more.</li>
</ul>
<p>Source: <a href="http://www.emforge.net/web/liferay-petstore-portlet/wiki/-/wiki/Main/Step1%3A+From+DB+to+simple+UI">http://www.emforge.net/web/liferay-petstore-portlet/wiki/-/wiki/Main/Step1%3A+From+DB+to+simple+UI</a></p>
<p>&nbsp;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lyphuong10.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lyphuong10.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lyphuong10.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lyphuong10.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/lyphuong10.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/lyphuong10.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/lyphuong10.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/lyphuong10.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lyphuong10.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lyphuong10.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lyphuong10.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lyphuong10.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lyphuong10.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lyphuong10.wordpress.com/125/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=125&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://lyphuong10.wordpress.com/2011/08/10/step1-from-db-to-simple-ui/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/8b8638691b0148442a47955d24cc60c1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">lyphuong10</media:title>
		</media:content>

		<media:content url="http://www.emforge.net/image/image_gallery?uuid=1482a7b0-7ed9-422c-9094-b40bc1f1d8a1&#038;groupId=10919&#038;t=1262181344811" medium="image" />

		<media:content url="http://www.emforge.net/image/image_gallery?uuid=0cd3e874-40af-4253-a9a4-795bdb596c93&#038;groupId=10919&#038;t=1262181440412" medium="image" />

		<media:content url="http://www.emforge.net/image/image_gallery?uuid=521644ff-bea5-432f-8d95-8e598fb471bb&#038;groupId=10919&#038;t=1262181510757" medium="image" />

		<media:content url="http://www.emforge.net/image/image_gallery?uuid=6ecf61da-151a-46fc-95aa-3f3e166c825b&#038;groupId=10919&#038;t=1262181586393" medium="image" />

		<media:content url="http://www.emforge.net/image/image_gallery?uuid=c86a59a8-7763-4a24-a394-dceed4c1e473&#038;groupId=10919&#038;t=1262181660069" medium="image" />
	</item>
		<item>
		<title>Portal Pack : Write Database Portlet using Service Builder Plug-in</title>
		<link>http://lyphuong10.wordpress.com/2011/08/10/portal-pack-write-database-portlet-using-service-builder-plug-in/</link>
		<comments>http://lyphuong10.wordpress.com/2011/08/10/portal-pack-write-database-portlet-using-service-builder-plug-in/#comments</comments>
		<pubDate>Wed, 10 Aug 2011 13:21:17 +0000</pubDate>
		<dc:creator>lyphuong10</dc:creator>
				<category><![CDATA[Web JSP Servlet]]></category>

		<guid isPermaLink="false">http://lyphuong10.wordpress.com/?p=123</guid>
		<description><![CDATA[The service builder framework in Liferay represents the database layer and all the interactions with database are done through service builder infrastructure. So in this blog, I will explain how you can use service builder framework inside your custom portlet using NetBeans 6.5 &#38; Portal Pack 3.0. To use service builder framework, you first need [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=123&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<div id="aui_3_2_0_1241">
<p id="aui_3_2_0_1240">The service builder framework in Liferay represents the database layer and all the interactions with database are done through service builder infrastructure. <span id="more-123"></span>So in this blog, I will explain how you can use service builder framework inside your custom portlet using <a href="http://www.netbeans.org/">NetBeans 6.5</a> &amp;<a href="http://portalpack.netbeans.org/"> Portal Pack 3.0</a>. To use service builder framework, you first need to create a service xml and then generate the required code. The Portal Pack here helps you by providing a nice GUI editor for service.xml file where you can define the entities or database structures and from the same GUI you can generate the services code which can be used inside your portlet.</p>
<p>I have taken an example of Simple Form Submission Portlet here. Using this portlet you can submit customer details which will be stored inside liferay&#8217;s database and the same portlet will also show the no of customer records present in the database.</p>
<p>First create a Webapplication with &#8220;Portlet Support&#8221; framework and add a new Portlet to it. Now you need to create the service.xml file. Let&#8217;s create the portlet application as &#8220;CustomerApp&#8221; and a portlet &#8220;CustomerPortlet&#8221; inside it.</p>
<h2>Creating the <kbd>service.xml</kbd> File</h2>
<p>After creating a portlet application, you need to create a <kbd>service.xml</kbd> file inside the portlet application.</p>
<h3>To Create a <kbd>service.xml</kbd> File</h3>
<ol type="1">
<li>From the CustomerApp application, right click on Web Pages and select New &gt; Others &gt; Web Space/Liferay Plugins &gt; Service Builder XML</li>
<li>Enter the file name as service. Make sure the &#8220;Folder&#8221; is selected as web. Then click Finish.</li>
<li>The <kbd>service.xml</kbd> file is created inside the <kbd>web</kbd> directory and the IDE opens the service.xml inside the editor area.</li>
</ol>
<p>You can see two tabs &#8220;Design&#8221; and &#8220;XML&#8221; in the editor. The &#8220;Design&#8221; tab helps the user to add/modify entities through GUI and using &#8220;XML&#8221;, user can directly modify the xml.</p>
<p><a href="http://cdn.www.liferay.com/image/image_gallery?uuid=8443c406-feb7-48a2-884f-c3688ca30946&amp;groupId=805128&amp;t=1237222867435" target="_blank"><img src="http://cdn.www.liferay.com/image/image_gallery?uuid=8443c406-feb7-48a2-884f-c3688ca30946&amp;groupId=805128&amp;t=1237222867435" alt="" width="789" height="261" /></a></p>
<div>Fig: 1</div>
<p>Now we are ready to add entities to our service xml.</p>
<h3>To Create Entity</h3>
<ol type="1">
<li>Click on &#8220;Add&#8221; button.
<p>The Service Definition window appears.  <a href="http://cdn.www.liferay.com/image/image_gallery?uuid=83cd82bf-4297-4c86-97d8-e312e6d81c2c&amp;groupId=805128&amp;t=1237222867405" target="_blank"><img src="http://cdn.www.liferay.com/image/image_gallery?uuid=83cd82bf-4297-4c86-97d8-e312e6d81c2c&amp;groupId=805128&amp;t=1237222867405" alt="" width="374" height="202" /></a></li>
<li>Specify the Entity Name as &#8220;CustomerDtls&#8221; and table name as &#8220;CustomerDtls&#8221;. The Entity name and table name doesn&#8217;t need to be same.</li>
<li>Now Click &#8220;Add&#8221;. So a new entity called &#8220;CustomerDtls&#8221; is now created.</li>
<li>Change the default Package Path name to com.sample.customer and namespace to &#8220;customer&#8221;. The namespace should be unique for every portlet application. No two portlet applications should have the same namespace.</li>
</ol>
<h3>Add Columns</h3>
<p>After creating an entity, you need to add columns for that entity. So to create columns for an entity</p>
<ul>
<li>Select an entity.</li>
<li>Click &#8220;Add&#8221; under the Columns tab as shown in the Fig : 3.</li>
</ul>
<div> <a href="http://cdn.www.liferay.com/image/image_gallery?uuid=66004a13-0a69-49d6-9cd9-245692e34c1e&amp;groupId=805128&amp;t=1237222867391" target="_blank"><img src="http://cdn.www.liferay.com/image/image_gallery?uuid=66004a13-0a69-49d6-9cd9-245692e34c1e&amp;groupId=805128&amp;t=1237222867391" alt="" width="762" height="226" /></a></p>
<div>Fig : 3</div>
</div>
<div>
<div>
<ul>
<li>The Column Details window appears.</li>
<li>Specify the Name of the column as &#8220;id&#8221; and the column type as long. You can choose the column type as String, Double, and Date from the drop down list.</li>
<li>Select the Primary Key checkbox and click Add. So for this entity, id is the primary key. A column is created with the Column Name as id and type as long.</li>
<li>Add two more columns with column name name, age with types String, int respectively.</li>
<li>You can see that there are three columns created for the &#8220;CustomerDtls&#8221; entity. (Fig: 4)</li>
</ul>
<p>Note: There should be atleast one primary key defined for an entity.</p></div>
</div>
<div></div>
<p><a href="http://cdn.www.liferay.com/image/image_gallery?uuid=084d4ba2-7afc-4d98-b5fb-c36a78f72f77&amp;groupId=805128&amp;t=1237222867417" target="_blank"><img src="http://cdn.www.liferay.com/image/image_gallery?uuid=084d4ba2-7afc-4d98-b5fb-c36a78f72f77&amp;groupId=805128&amp;t=1237222867417" alt="" width="885" height="277" /></a></p>
<div>                                                    Fig : 4</p>
<div>
<h3>Add Finder Methods</h3>
</div>
<div>You can also add your custom finder methods to the entity from &#8220;Finders&#8221; tab. In &#8220;Finders&#8221; tab, click &#8220;Add Finder&#8221; to add finder methods. It provides a GUI where you can select different columns required for your finder methods.(Fig. 5)</p>
<p><a href="http://cdn.www.liferay.com/image/image_gallery?uuid=2f2e679f-c213-4733-ac81-0eabed730c59&amp;groupId=805128&amp;t=1237222867422" target="_blank"><img src="http://cdn.www.liferay.com/image/image_gallery?uuid=2f2e679f-c213-4733-ac81-0eabed730c59&amp;groupId=805128&amp;t=1237222867422" alt="" width="578" height="474" /></a></p>
<p>Fig. 5</p></div>
</div>
<h3>Generating Services</h3>
<ul>
<li>From the <kbd>service.xml</kbd> GUI editor, click the &#8220;Generate Services&#8221; button.</li>
<li>You can see the creation of classes, services, and data models that are required for the database interaction. The service api classes are generated under $project/services directory and added to the project classpath. You should not do any modification in those classes as those will be overwritten next time when you run &#8220;Generate Service&#8221;. But the implementation classes which can be modified by the user, are added to the project source path and you can modify them as you want. But after modifying anything in the service implementation classes, you need to run &#8220;Generate Service&#8221; again.</li>
<li>By default the generated service api jar will be bundled inside the portlet war file. But if you want other applications to access your services then the service api jar file needs to be there in the server classpath. You can do that by changing the preference which can be accessed by clicking on &#8220;Preferences&#8221; button. (Fig: 6)</li>
</ul>
<div><a href="http://cdn.www.liferay.com/image/image_gallery?uuid=b059bfc3-60a5-4ffa-aaa6-cad65965d6d6&amp;groupId=805128&amp;t=1237222867429" target="_blank"><img src="http://cdn.www.liferay.com/image/image_gallery?uuid=b059bfc3-60a5-4ffa-aaa6-cad65965d6d6&amp;groupId=805128&amp;t=1237222867429" alt="" width="498" height="363" /></a><br />
Fig: 6</p>
<ul>
<li>Now in the GUI editor, click the Local Methods tab. This tab lists local method defined in the local service implementation. Now you can select &#8220;Go to Source&#8221;  to go the local service implementation. In our example this is &#8220;CustomerDtlsLocalServiceImpl.java&#8221; file. But we don&#8217;t need to add any local method for our current example.</li>
</ul>
</div>
<h3>Creating the View Page for Customer Portlet</h3>
<ul>
<li>From the Projects pane, click the <kbd>CustomerPortlet_view.jsp</kbd> file.</li>
<li>Add code to the <kbd>CustomerPortlet_view.jsp</kbd> file to create a HTML form to specify the id,name and age of a customer. This jsp also shows the no of customers in the database. Replace the CustomerPortlet_view.jsp code with following code snippets.</li>
</ul>
<div id="aui_3_2_0_1259"><code> &lt;%@page contentType="text/html"%&gt;</code><br />
<code>&lt;%@page pageEncoding="UTF-8"%&gt;</code></p>
<p><code>&lt;%@ page import="javax.portlet.*"%&gt;</code><br />
<code>&lt;%@ page import="com.example.customer.service.*"%&gt;</code><br />
<code>&lt;%@ page import="com.example.customer.model.*"%&gt;</code><br />
<code>&lt;%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%&gt;</code></p>
<p><code>&lt;portlet:defineObjects /&gt;</code><br />
<code>&lt;%PortletPreferences prefs = renderRequest.getPreferences();%&gt; </code><br />
<code>&lt;table&gt;</code><br />
<code>&lt;form method="POST" action="&lt;portlet:actionURL/&gt;"&gt;</code></p>
<p><code>    &lt;tr&gt;</code><br />
<code>        &lt;td&gt;Customer ID:&lt;/td&gt;</code><br />
<code>        &lt;td&gt;&lt;Input type="text" name="id"/&gt;&lt;/td&gt;</code><br />
<code>    &lt;/tr&gt;</code><br />
<code>    &lt;tr&gt;</code><br />
<code>        &lt;td&gt;Name:&lt;/td&gt;</code><br />
<code>        &lt;td&gt;&lt;Input type="text" name="name"/&gt;&lt;/td&gt;</code><br />
<code>    &lt;/tr&gt;</code><br />
<code>    &lt;tr&gt;</code><br />
<code>        &lt;td&gt;Age:&lt;/td&gt;</code><br />
<code>        &lt;td&gt;&lt;Input type="text" name="age"/&gt;&lt;/td&gt;</code><br />
<code>    &lt;/tr&gt;</code><br />
<code>    &lt;tr&gt;</code><br />
<code>        &lt;td&gt;&lt;Input type="submit"/&gt;&lt;/td&gt;</code><br />
<code>    &lt;/tr&gt;</code><br />
<code>&lt;/form&gt;</code><br />
<code>&lt;/table&gt;</code><br />
<code>&lt;H3&gt; No of Customers in Database :</code><br />
<code>    &lt;%</code><br />
<code>        out.println(CustomerDtlsLocalServiceUtil.getCustomerDtlsesCount());</code><br />
<code>    %&gt;</code><br />
<code>&lt;/H3&gt;</code></div>
<p>&nbsp;</p>
<ul>
<li>From the Projects pane, click the <kbd>CustomerPortlet.java</kbd> file under the <kbd>com.test</kbd> package. Add the following code to processAction method. This method gets the data from the browser and add customer details to the database.</li>
</ul>
<div><code> public void processAction(ActionRequest request, ActionResponse response) throws PortletException,IOException {</code><br />
<code>      </code><br />
<code>        try {</code><br />
<code>            long id = Long.parseLong(request.getParameter("id"));</code><br />
<code>            String name = request.getParameter("name");</code><br />
<code>            int age = Integer.parseInt(request.getParameter("age"));</code><br />
<code>            CustomerDtls customer = CustomerDtlsLocalServiceUtil.createCustomerDtls(id);</code><br />
<code>            customer.setId(id);</code><br />
<code>            customer.setName(name);</code><br />
<code>            customer.setAge(age);</code><br />
<code>            CustomerDtlsLocalServiceUtil.addCustomerDtls(customer);</code><br />
<code>            System.out.println("Added");</code><br />
<code>        } catch (Exception ex) {</code><br />
<code>            ex.printStackTrace();</code><br />
<code>            </code><br />
<code>        }</code><br />
<code>    }</code></div>
<p>&nbsp;</p>
<h3>Deploy And Test</h3>
<p>So we are now ready to deploy the portlet application. Right click on the portlet project and select &#8220;Deploy&#8221; to deploy the portlet on Liferay Portal Server. I am assuming you have selected &#8220;Liferay Portal Server&#8221;  as runtime for the portlet application. The required table is created automatically during the deployment time, so ideally you don&#8217;t need to create the table manually. But incase you get &#8220;Table not Found Exception&#8221; while accessing the portlet, you can run the generated table.sql manually to create the required tables. The table.sql can be found under &#8220;WEB-INF/sql&#8221; directory.</p>
<div id="aui_3_2_0_1256">
<div>Now access your liferay portal from the browser and add the new &#8220;CustomerPortlet&#8221; to a page. You can see a simple form for customer data and below that no of customers in database which is initially &#8220;0&#8243;. Now try to add a customer and after successful addition of data to the database, the &#8220;No of Customers in Database&#8221; will be changed to 1.</div>
<div></div>
<div><a href="http://cdn.www.liferay.com/image/image_gallery?uuid=7b67ecaa-db3c-4129-b2fb-0b9a01f99dcb&amp;groupId=805128&amp;t=1237222867412" target="_blank"><img src="http://cdn.www.liferay.com/image/image_gallery?uuid=7b67ecaa-db3c-4129-b2fb-0b9a01f99dcb&amp;groupId=805128&amp;t=1237222867412" alt="" width="660" height="189" /></a></div>
</div>
<div id="aui_3_2_0_1256">Fig: 7</div>
<div>Source: <a href="http://www.liferay.com/web/satyaranjan/blog/-/blogs/2506216">http://www.liferay.com/web/satyaranjan/blog/-/blogs/2506216</a></div>
</div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lyphuong10.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lyphuong10.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lyphuong10.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lyphuong10.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/lyphuong10.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/lyphuong10.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/lyphuong10.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/lyphuong10.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lyphuong10.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lyphuong10.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lyphuong10.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lyphuong10.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lyphuong10.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lyphuong10.wordpress.com/123/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=123&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://lyphuong10.wordpress.com/2011/08/10/portal-pack-write-database-portlet-using-service-builder-plug-in/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/8b8638691b0148442a47955d24cc60c1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">lyphuong10</media:title>
		</media:content>

		<media:content url="http://cdn.www.liferay.com/image/image_gallery?uuid=8443c406-feb7-48a2-884f-c3688ca30946&#038;groupId=805128&#038;t=1237222867435" medium="image" />

		<media:content url="http://cdn.www.liferay.com/image/image_gallery?uuid=83cd82bf-4297-4c86-97d8-e312e6d81c2c&#038;groupId=805128&#038;t=1237222867405" medium="image" />

		<media:content url="http://cdn.www.liferay.com/image/image_gallery?uuid=66004a13-0a69-49d6-9cd9-245692e34c1e&#038;groupId=805128&#038;t=1237222867391" medium="image" />

		<media:content url="http://cdn.www.liferay.com/image/image_gallery?uuid=084d4ba2-7afc-4d98-b5fb-c36a78f72f77&#038;groupId=805128&#038;t=1237222867417" medium="image" />

		<media:content url="http://cdn.www.liferay.com/image/image_gallery?uuid=2f2e679f-c213-4733-ac81-0eabed730c59&#038;groupId=805128&#038;t=1237222867422" medium="image" />

		<media:content url="http://cdn.www.liferay.com/image/image_gallery?uuid=b059bfc3-60a5-4ffa-aaa6-cad65965d6d6&#038;groupId=805128&#038;t=1237222867429" medium="image" />

		<media:content url="http://cdn.www.liferay.com/image/image_gallery?uuid=7b67ecaa-db3c-4129-b2fb-0b9a01f99dcb&#038;groupId=805128&#038;t=1237222867412" medium="image" />
	</item>
		<item>
		<title>Web Services in Liferay</title>
		<link>http://lyphuong10.wordpress.com/2011/08/10/web-services-in-liferay/</link>
		<comments>http://lyphuong10.wordpress.com/2011/08/10/web-services-in-liferay/#comments</comments>
		<pubDate>Wed, 10 Aug 2011 13:01:03 +0000</pubDate>
		<dc:creator>lyphuong10</dc:creator>
				<category><![CDATA[Web JSP Servlet]]></category>

		<guid isPermaLink="false">http://lyphuong10.wordpress.com/?p=118</guid>
		<description><![CDATA[What is web service Web service is nothing but exposes your software as service for other application over the network. Applications can be written in any programming language and if they support the statandard they can be integrated.It removes the concern of writing custom interfaces and REST/HTTP Post based calls for each integration point. How [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=118&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><strong>What is web service</strong></p>
<p>Web service is nothing but exposes your software as service for other application over the network. Applications can be written in any programming language and if they support the statandard they can be integrated.It removes the concern of writing custom interfaces and REST/HTTP Post based calls for each integration point.<span id="more-118"></span></p>
<p><strong>How they can be used , examples</strong></p>
<p>As of now we have not used this feature in our platform. but there are several ways this can be used.</p>
<p>1. Data Migration.</p>
<p>2. External third party software integration – Applications like Salesforge</p>
<p><strong>Exposing an entity as a SOAP Webservice in Liferay</strong></p>
<p>In this example we will create a table in Database and expose a method to update this table via web service</p>
<p><em>Create a table</em></p>
<pre>CREATE TABLE [dbo].[MyBook](
  [bookid] [bigint] NOT NULL,
  [bookname] [varchar](500) NULL,
CONSTRAINT [PK_MyBook] PRIMARY KEY CLUSTERED
(
   [bookid] ASC
)</pre>
<p>Generate Service Layer code for table</p>
<p>1) Create service.xml place it in ext-impl\src\com\ext\portlet\mybook\service.xml</p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 5.2.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_5_2_0.dtd"&gt;

&lt;service-builder package-path="com.ext.portlet.mybook"&gt;
 &lt;namespace&gt;MyBook&lt;/namespace&gt;
 &lt;entity name="MyBook" local-service="true" remote-service="true"&gt;
  &lt;column name="bookid" type="long" primary="true" /&gt;
  &lt;column name="bookname" type="String" /&gt;
 &lt;/entity&gt;
 &lt;exceptions&gt;
  &lt;exception&gt;BookEntryName&lt;/exception&gt;
 &lt;/exceptions&gt;
&lt;/service-builder&gt;</pre>
<address> </address>
<address> </address>
<address>2) Go to ext-impl\build-parent.xml and add ant task to build this service.</address>
<pre>&lt;target name="build-service-portlet-mybook"&gt;
  &lt;antcall target="build-service"&gt;
     &lt;param name="service.file" value="src/com/ext/portlet/mybook/service.xml" /&gt;
  &lt;/antcall&gt;
&lt;/target&gt;</pre>
<address> </address>
<address>run the newly created ant task ‘build-service-portlet-mybook’. It will generate service layer code for you.</address>
<p>Now we will write a method to which will add a new book entry to the table.Open the generated file MyBookServiceImpl.java. if your entity name is ‘MyEntity’ in service.xml the generated class name will MyEntityServiceImpl.java</p>
<pre>public MyBook addBook(String bookName) throws PortalException, SystemException {
  MyBook  mybook = null;
  long bookId = CounterLocalServiceUtil.increment(MyBook.class.getName());
  mybook = MyBookUtil.create(bookId);
  mybook.setBookname(bookName);
  return MyBookUtil.update(mybook, false);
}</pre>
<p>Once this is done run the newly created ant task ‘build-service-portlet-mybook’ again. It will propogate this method rest of the interfaces and classes.Generate web service code for this method</p>
<p>Go to ext-impl\build-parent.xml and add a new ant task to generate the web service.</p>
<pre>&lt;target name="build-wssd-portlet-mybook"&gt;
  &lt;antcall target="build-wsdd"&gt;
    &lt;param name="service.file" value="src/com/ext/portlet/mybook/service.xml" /&gt;
  &lt;/antcall&gt;
&lt;/target&gt;</pre>
<p>run the newly created ant task ‘build-wssd-portlet-mybook’. It will generate web service layer code for you.</p>
<p>Later on for easier convenience , you can add following task in ext-impl\build-parent.xml to build service and wsdd at same time.</p>
<pre>&lt;target name="build-mybook-service-wssd"&gt;
   &lt;antcall target="build-service-portlet-mybook" /&gt;
   &lt;antcall target="build-wssd-portlet-mybook" /&gt;
&lt;/target&gt;</pre>
<address> </address>
<address> </address>
<h3>Consuming  Liferay Web services</h3>
<ul>
<li>Enabling web services</li>
</ul>
<p>The portal uses Apache Axis to generate web services. The default Axis configuration is specified in the server-config.wsdd file under the /portal/tunnel-web/ docroot/WEB-INF folder. type http://127.0.0.1:8080/ tunnel-web/axis in your browser, you will see a list of SOAP services.</p>
<p>To access a service remotely, the host must be allowed via the portal-ext. properties properties file. After that, the user must have permission to access the portal resources. The default settings to access a service remotely are specified in the portal.properties file as follows:</p>
<pre>axis.servlet.hosts.allowed=127.0.0.1,SERVER_IP
axis.servlet.https.required=false</pre>
<p>The code above shows the IPs to access the Axis servlet. You can input a blank list to allow any IP to access this servlet. SERVER_IP will be replaced with the IP of the host server. By default, 127.0.0.1 is the IP for local host. This is the reason that you can access web services only by the IP 127.0.0.1</p>
<ul>
<li>Example to access services</li>
</ul>
<blockquote>
<ol>
<li>Service can be browsed at http://127.0.0.1:8080/tunnel-web/axis</li>
<li>To access the wsdl , click on the wsdl for any of the service.This is the example for User Service wsdl http://127.0.0.1:8080/tunnel-web/axis/Portal_UserService?wsdl</li>
<li>From WSDL you can generate stub and other classes using eclipse or netbeans.</li>
<li>Following is the sample client code to call a  user service service</li>
</ol>
</blockquote>
<pre>public class LiferayUserServiceClient {
    public static void main(String[] args) {
         try {
             UserServiceSoapServiceLocator locatorUser = new UserServiceSoapServiceLocator();
             UserServiceSoap soapUser = locatorUser.getPortal_UserService("http://abc:abc@127.0.0.1:8080/tunnel-web/secure/axis/Portal_UserService");
             UserSoap soapUserModel =  soapUser.getUserById(10806);
             System.out.println(" getEmailAddress:" + soapUserModel.getEmailAddress());
        } catch (Exception e) {
           e.printStackTrace();
        }
    }
}

Source: http://arvindm.com/2010/03/23/web-services-in-liferay</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lyphuong10.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lyphuong10.wordpress.com/118/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lyphuong10.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lyphuong10.wordpress.com/118/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/lyphuong10.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/lyphuong10.wordpress.com/118/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/lyphuong10.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/lyphuong10.wordpress.com/118/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lyphuong10.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lyphuong10.wordpress.com/118/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lyphuong10.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lyphuong10.wordpress.com/118/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lyphuong10.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lyphuong10.wordpress.com/118/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=118&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://lyphuong10.wordpress.com/2011/08/10/web-services-in-liferay/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/8b8638691b0148442a47955d24cc60c1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">lyphuong10</media:title>
		</media:content>
	</item>
		<item>
		<title>Using Views 3 and Drupal 7 to Create a Related Pages Block</title>
		<link>http://lyphuong10.wordpress.com/2011/06/17/using-views-3-and-drupal-7-to-create-a-related-pages-block/</link>
		<comments>http://lyphuong10.wordpress.com/2011/06/17/using-views-3-and-drupal-7-to-create-a-related-pages-block/#comments</comments>
		<pubDate>Fri, 17 Jun 2011 13:27:25 +0000</pubDate>
		<dc:creator>lyphuong10</dc:creator>
				<category><![CDATA[Drupal]]></category>

		<guid isPermaLink="false">http://lyphuong10.wordpress.com/?p=112</guid>
		<description><![CDATA[Its really easy in D7. Coding is not at all required. Taxonomy is a field in D7. I will explain how to create a Related Content block using Views. Create an argument by adding the taxonomy field on which you want to find the related nodes. Select &#8220;Provide default argument&#8221;. Argument type = &#8220;Taxonomy Term [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=112&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<div>
<p>Its really easy in D7. Coding is not at all required.</p>
<p>Taxonomy is a <em>field</em> in D7. I will explain how to create a <em>Related Content</em> block using Views.<span id="more-112"></span></p>
<ol>
<li>Create an argument by adding the <em>taxonomy field</em> on which you want to find the related nodes.</li>
<li>Select &#8220;Provide default argument&#8221;.</li>
<li>Argument type = &#8220;Taxonomy Term ID from URL&#8221;</li>
<li>Remove tick from &#8220;Load default argument from term page&#8221;</li>
<li>Tick the &#8220;Load default argument from node page, thats good for related taxonomy blocks.&#8221;</li>
</ol>
<p>To remove duplicates you have to follow the following points.</p>
<ol>
<li>Open &#8220;Query settings&#8221; in the &#8220;Advanced Settings&#8221;.</li>
<li>Tick &#8220;Distinct&#8221;.</li>
</ol>
<p>This gives you a perfect &#8220;Related Articles&#8221; or &#8220;Related Nodes&#8221; using Views.</p>
<div>
<p>This works very nicely. If you&#8217;d like to exclude the active content from the listing (so you don&#8217;t see what you&#8217;re reading in the related links):</p>
<ul>
<li>Add another argument/contextual filter for Content: Nid .</li>
<li>Provide a default value of Content ID from URL.</li>
<li>Under More, click Exclude.</li>
</ul>
<p>Here&#8217;s a screenshot of that setup on a Drupal Gardens site &#8211; <a title="http://screencast.com/t/Sz4gJLsz" href="http://screencast.com/t/Sz4gJLsz" rel="nofollow">http://screencast.com/t/Sz4gJLsz</a></p>
<p>Nguồn: <a href="http://drupal.org/node/65375">http://drupal.org/node/65375</a></p>
<p><strong>Use code:</strong></p>
<div>
<p>I used this documentation and all the great posts in Drupal 6 to build a block with random fotos that are relating to the topic of the viewed node.</p>
<p>I couldn&#8217;t find anything for Drupal 7 and I didn&#8217;t want to use panels cause I fear it would add an unnecessary overhead.</p>
<p>I modified the pieces of code I found here and finally got it working with:</p>
<div><code><code>?php<br />
if (arg(0) != 'node') {<br />
return;<br />
}</code></code>$node = node_load(arg(1));<br />
if($node &amp;&amp; isset($node-&gt;field_kategorie)) /*replace &#8220;field_kategorie&#8221; with your taxonomy reference field*/<br />
{<br />
$terms = array();<br />
foreach($node-&gt;field_kategorie as $lang) /*replace again! */<br />
{<br />
foreach($lang as $item)<br />
{<br />
$terms[]=$item['tid'];<br />
}<br />
}<br />
return(implode(&#8216;+&#8217;,$terms));<br />
}<br />
return;<br />
?</div>
<p>I&#8217;m not sure why, but although it creates a good argument it won&#8217;t work with</p>
<ul>
<li><em>Allow multiple terms per argument</em> and with</li>
<li><em>Reduce duplicates</em>.</li>
</ul>
<p>If I turn them on I get:</p>
<p><em>Notice: Undefined variable: value in views_many to_one_helper-&gt;add_filter() (line 868 in sites/all/modules/views/includes/handlers.inc)</em></p>
<p>So basically follow the steps for D6 and Views 2, use this code instead and don&#8217;t check those two options.</p>
<p>hope this will be useful</p>
<p><a href="http://www.metachunk.com/blog/adding-related-content-view-drupal-7">http://www.metachunk.com/blog/adding-related-content-view-drupal-7</a><br />
<strong>Adding a related content view in Drupal 7</strong><br />
<strong>Update</strong></p>
<p>The most gracious commenter &#8220;nordic material&#8221; provided working instructions for performing this task using Views 3 in D7. I just went through the directions and they work perfectly. Below is a recap. Thanks again Nordic Material!</p>
<div>
<ol>
<li>Create view (block)</li>
<li>Add fields (title, a small image, date, whatever you like). Or teasers, what works as well.</li>
<li>&#8220;Arguments&#8221; is from now on called &#8220;Contextual filters&#8221;, so go there.</li>
<li>Add the filter: &#8220;Content: Has taxonomy term ID&#8221;</li>
<li>Configuration on this filter: -&gt; When the filter value is NOT in the URL: -&gt; Provide default value -&gt; Type: Taxonomy Term ID from URL -&gt; under that, check the box &#8220;Load default filter from node page, that&#8217;s good for related taxonomy blocks.&#8221; -&gt; now check the boxes of the taxonomies you want involved here</li>
<li>Now you need to add the second filter in order to exclude the current node from the list. Click [+] button of the contextual filters section.</li>
<li>Select Content: Nid</li>
<li>Set the &#8216;when argument is not present&#8217; to &#8216;Provide default argument&#8217;</li>
<li>Set the &#8216;Default argument type&#8217; to &#8216;Content ID from URL&#8217;</li>
<li>Go to &#8220;MORE&#8221; , and check the &#8220;Exclude&#8221; box.</li>
<li>Add a block to your view and embed the block on your node pages</li>
<li>Save your view</li>
</ol>
</div>
<p><strong>Note:</strong> The instructions below are outdated and applicable only to Views 2/D7. See the instructions above for latest method.</p>
<p>The way nodes are structured in Drupal 7 is significantly different than in D6. All node attributes are now fields, including taxonomy. I dig it,  but it means one will need to port lots of taxonomy related code from D6.</p>
<p>My task du jour was to setup a &#8220;Related Terms&#8221; block using views. There is a decent documentation article for D6 <a href="http://drupal.org/node/65375">here</a>. I needed to make this work for D7. Listed below is the code. One key difference, however, is the D6 example is able to reference all  terms via the &#8220;$node-&gt;taxonomy&#8221; obj. where as in D7 you can only reference explicitly defined fields &#8220;$node-&gt;field_taxonomy_name&#8221;.</p>
<p>** Disclaimer ** The <a href="http://drupal.org/project/relevant_content">Relevant Content</a> module does a fine job of this so this is more of an academic exercise. Most of this is copypasta from Drupal.org. I just modified for D7. I will also contribute this code on Drupal.org documentation</p>
<h3>Creating a related content block view in Drupal 7</h3>
<p>Creates a related content views block to list content with the same taxonomy of the current node:</p>
<ol>
<li>Create View</li>
<li>Argument &#8220;Taxonomy: Term ID&#8221;</li>
<li>Argument Configuration:
<ul>
<li>Provide default argument</li>
<li>PHP Code:Add this code:
<div>
<pre><code> $node = node_load(arg(1)); if($node) { //Be sure to rename -&gt;field_taxonomy_name to your field name foreach($node-&gt;field_taxonomy_name[LANGUAGE_NONE] as $term) { $terms[] = $term['tid']; } return implode('+',$terms); } else { return; } </code></pre>
</div>
</li>
<li>Check ON: Allow multiple terms per argument.</li>
<li>Check ON: Reduce duplicates</li>
</ul>
</li>
<li>Add Display: Block</li>
<li>Add Field: Title</li>
<li>Optional — Add Filter: Content Type (whatever type you&#8217;d like to filter)</li>
<li>Now you need to add the second argument in order to exclude the current node from the list. Click [+] button of the arguments section.</li>
<li>Select Node: Nid</li>
<li>Set the &#8216;Action to take if argument is not present&#8217; to &#8216;Provide default argument&#8217;</li>
<li>Set the &#8216;Default argument type&#8217; to &#8216;Node ID from URL&#8217;</li>
<li>Check &#8216;Exclude the argument&#8217;</li>
<li>Add a block to your view and embed the block on your node pages</li>
<li>Save your view</li>
<li>PROFIT!</li>
</ol>
</div>
</div>
</div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lyphuong10.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lyphuong10.wordpress.com/112/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lyphuong10.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lyphuong10.wordpress.com/112/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/lyphuong10.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/lyphuong10.wordpress.com/112/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/lyphuong10.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/lyphuong10.wordpress.com/112/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lyphuong10.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lyphuong10.wordpress.com/112/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lyphuong10.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lyphuong10.wordpress.com/112/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lyphuong10.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lyphuong10.wordpress.com/112/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=112&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://lyphuong10.wordpress.com/2011/06/17/using-views-3-and-drupal-7-to-create-a-related-pages-block/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/8b8638691b0148442a47955d24cc60c1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">lyphuong10</media:title>
		</media:content>
	</item>
		<item>
		<title>Related node code term ID của node</title>
		<link>http://lyphuong10.wordpress.com/2011/06/16/related-node-code-term-id-c%e1%bb%a7a-node/</link>
		<comments>http://lyphuong10.wordpress.com/2011/06/16/related-node-code-term-id-c%e1%bb%a7a-node/#comments</comments>
		<pubDate>Thu, 16 Jun 2011 13:08:16 +0000</pubDate>
		<dc:creator>lyphuong10</dc:creator>
				<category><![CDATA[Drupal]]></category>

		<guid isPermaLink="false">http://lyphuong10.wordpress.com/?p=104</guid>
		<description><![CDATA[Nguồn: http://drupaleasy.com/blogs/ryanprice/2008/06/using-views-2-drupal-6-create-a-related-pages-block?page=1 Using Views 2 and Drupal 6 to Create a Related Pages Block Essentially:, what i&#8217;m trying to do is 1. Determine the current nodes taxonomy terms 2. Determine all other pages that share taxonomy terms 3. Display the title (and link) to those pages in a block Using Drupal 6.2 and Views &#8211; [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=104&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Nguồn: <a href="http://drupaleasy.com/blogs/ryanprice/2008/06/using-views-2-drupal-6-create-a-related-pages-block?page=1">http://drupaleasy.com/blogs/ryanprice/2008/06/using-views-2-drupal-6-create-a-related-pages-block?page=1</a><br />
<a href="http://vn.rd.yahoo.com/blog/mod/art_title/*http://vn.360plus.yahoo.com/quangphuc_truong/article?mid=372" target="_parent">Using Views 2 and Drupal 6 to Create a Related Pages Block</a></p>
<div>
<blockquote><p>Essentially:, what i&#8217;m trying to do is<br />
1. Determine the current nodes taxonomy terms<br />
2. Determine all other pages that share taxonomy terms<br />
3. Display the title (and link) to those pages in a block</p>
<p>Using Drupal 6.2 and Views &#8211; Looked at a few modules, but nothing quite<br />
exact &#8211; Reviewing some module snippets right now to see if I can<br />
potentially use an argument to do it.</p></blockquote>
<p><span id="more-104"></span><br />
Dale asks a good question: before the release of Panels for Drupal 6, how can one associate a block with the node it&#8217;s being displayed next to without writing a custom module? It turned out to be simpler than I expected. I actually started going down the path of custom modules, but in the process I noticed that Views still have the ability to load Arguments with PHP Code, and my solution wrote itself.</p>
<p>Dale, you&#8217;re already pretty far along: you know you need a view inside of a block, displayed based on taxonomy terms to relate the view to the pages. Instead of giving you a full-fledged tutorial on Views and the Black Arts, you&#8217;ll be getting a recipe that outlines how to create the block in question.</p>
<p>First, you&#8217;ll want to download and install Views 2 for Drupal 6, currently in Beta 4, then enable the module under <em>admin/build/modules</em> &#8211; remember that Views also requires you to activate Views UI, as the views.module is more of an API for creating views.</p>
<p>The first step in your new Views journey is to Add a new view at <em>admin/build/views</em>. Just click on the tab near the top of the screen:<br />
<img title="add a view" src="http://drupaleasy.com/files/view_01_add.png" alt="add a view" width="318" height="26" /></p>
<p>Now you&#8217;ll be asked to name your view something computer-friendly &#8211; in this case you&#8217;ll name it related_by_term:<br />
<img title="Name your view" src="http://drupaleasy.com/files/view_02_name.png" alt="Name your view" width="174" height="41" /></p>
<p>Once you click through, you&#8217;ll be presented with the granddaddy of all administration screens, but don&#8217;t be afraid, things move pretty quickly in here if you know what you&#8217;re doing. Notice the Orange text in the top right: <em>New view</em>. Until you push the Save button at the bottom of the screen, all you hard work could be lost, and especially don&#8217;t forget to save once you&#8217;ve finished configuring your view.<br />
<img title="Main Views screen" src="http://drupaleasy.com/files/view_04_options.png" alt="Main views screen" width="494" height="550" /></p>
<p>I want you to skip all those fancy options and dive right in: you&#8217;ve got to eat your vegetables, so let&#8217;s get the hard part over with and set up the arguments:<br />
<img title="Add an argument" src="http://drupaleasy.com/files/view_05_add_argument.png" alt="Add an argument" width="117" height="42" /></p>
<p>Arguments were the most powerful (and hardest to understand) feature of the old Views &#8211; think of this as the WHERE clause of your SQL statement. Your first and only argument will be keyed off of a Taxonomy Term ID:<br />
<img title="choose Taxonomy as your argument type" src="http://drupaleasy.com/files/view_06_arg_defaults.png" alt="taxonomy argument type" width="364" height="309" /></p>
<p>Since you don&#8217;t have Panels at your disposal, you&#8217;ll need to specify a Default Argument. There are several (powerful) ways to accomplish this, but in your case, resort to tried-and-true PHP Code. The code displayed here loads the object for the current $node (if any) and concatenates a list of all the Term IDs on that node, then returns the string to Views in the format 1+2+3, just like the arguments on <em>taxonomy/term</em> pages:<br />
<img title="use PHP to specify the default argument" src="http://drupaleasy.com/files/view_07_arg_configure.png" alt="use PHP to specify the default argument" width="512" height="565" /></p>
<p>In order to activate this muitliple-term-driven argument scheme, you need to check a few boxes below the PHP code. The first sets up the fact that you can use the 1+2+3 format, and the second removes duplicate entries that have more than one term. Make sure you read the warnings about performance; if you don&#8217;t use multiple taxonomy terms, leave this box unchecked. You can proceed by clicking the Update button:<br />
<img title="Allow multiple terms, reduce duplicates" src="http://drupaleasy.com/files/view_08_arg_multiple.png" alt="Allow multiple terms, reduce duplicates" width="513" height="347" /></p>
<p>At this point, you&#8217;ll see an error message inviting you to extract some fields in your view, which is set up to display fields by default. If you wanted to view full nodes or teasers, you could change that option and be safe, but the block you want to build needs titles that link to the node:<img title="egads, an error message" src="http://drupaleasy.com/files/view_09_error.png" alt="egads, an error message" width="499" height="28" /></p>
<p>Now you want to tackle adding fields to your view. This is the building block of any view, analogous to the SELECT part of a SQL statement:<br />
<img title="Add a field" src="http://drupaleasy.com/files/view_10_fields.png" alt="Add a field" width="116" height="47" /></p>
<p>You should recognize this next picture, because it&#8217;s very similar to the way you chose your argument type, and how you&#8217;ll choose your filter in the future. Use the Add button to move to the next screen:<br />
<img title="you want to see the node title" src="http://drupaleasy.com/files/view_11_field_options.png" alt="you want to see the node title" width="381" height="310" /></p>
<p>If you don&#8217;t delete the word &#8220;Title&#8221; in the Label text box, it will appear next to all your links. There are some situations where this is wanted; yours is not one of them. You also said you wanted the titles to be links, so check that box:<img title="remove the Label and enable links" src="http://drupaleasy.com/files/view_12_field_configure.png" alt="remove the Label and enable links" width="382" height="261" /></p>
<p>At this stage, you should be able to get a working preview of your view. Just type a number or a 1+2 in the arguments area and push the button to trigger the AJAX. That blue text is your view, and there&#8217;s also some geeky information below. Notice that currently &#8220;This display has no path&#8221;; that&#8217;s OK, you want a block:<br />
<img title="use some arguments to get a live preview" src="http://drupaleasy.com/files/view_13_preview.png" alt="use some arguments to get a live preview" width="492" height="424" /></p>
<p>At this point, you still haven&#8217;t told Views that you want your view to be a block, so make sure you choose block from the drop-down in the main interface. If you&#8217;re working strictly with Page nodes, you may also want to throw a filter on your view to limit the results. You also should never forget the all-important Save button:<img title="filter and save your view" src="http://drupaleasy.com/files/view_14_save.png" alt="filter and save your view" width="498" height="542" /></p>
<p>The last thing you need to view is activate your block on <em>admin/build/block</em> (you may need to use block visibility rules, but that&#8217;s another tutorial), and finally visit one of your Taxonomy-tagged pages to see if your other taxonomy-tagged pages shows up. If you&#8217;ve followed all the steps here, everything should be a snap. Maybe the best feature about your new block is the handy links that pop up when you mouse over your new block (if you have <em>administer views</em> access, at least):<br />
<img title="your finished block with edit links" src="http://drupaleasy.com/files/view_15_block.png" alt="your finished block with edit links" width="128" height="56" /></p>
<p>Well Dale, I think that should just about answer your question. Since this is my first Drupal 6 tutorial, I&#8217;ll have to say, this was a lot more fun for me than I&#8217;m sure the last few days have been for you. Wave hello to Corey and Sterling and Derek and Daniel and the other NFi folks, and I hope I was able to save you some precious time with this post.</p>
<p>Nguồn: <a href="http://vn.360plus.yahoo.com/quangphuc_truong/article?mid=37">http://vn.360plus.yahoo.com/quangphuc_truong/article?mid=37</a>2</p>
<p><strong>code term ID của node Related node?</strong></p>
<p><a href="http://groups.drupal.org/node/43544">http://groups.drupal.org/node/43544</a><br />
<strong>Hỏi về module &#8220;tiêu điểm&#8221;</strong><br />
<a href="http://groups.drupal.org/node/43738">http://groups.drupal.org/node/43738</a></p>
<p><a href="http://www.hankpalan.com/blog/drupal/related-content-views-2-drupal">http://www.hankpalan.com/blog/drupal/related-content-views-2-drupal</a></p>
<p>Show related or similar content in a block with Views 2 in Drupal. Here is a step by step tutorial on how to accomplish this.</p>
<p>I first found this method over at <a href="http://drupaleasy.com/blogs/ryanprice/2008/06/using-views-2-drupal-6-create-a-related-pages-block"><span style="text-decoration:underline;">Drupal Easy: Using Views 2 and Drupal 6 to Create a Related Pages Block</span></a>. I&#8217;m going to show you a similar method with a few minor adjustments.</p>
<p>As of this writing this is accomplished with Views 2 and Drupal 6.</p>
<ul>
<li>Make a new view and call it whatever you want.</li>
<li>Add a Block Display</li>
<li>Add a new argument &#8211; Taxonomy: Term ID</li>
<ul>
<li>Set up the argument with these options:</li>
<li>Provide Default Argument</li>
<li>Php Code:</li>
<li>
<div><code>$node=node_load(arg(1));<br />
if($node){<br />
foreach($node-&gt;taxonomy as $term){$terms[]=$term-&gt;tid;}<br />
return implode('+',$terms);<br />
}else {return;}</code></div>
</li>
<li>Check Allow Multiple Terms per Argument</li>
<li>Check Reduce Duplicates</li>
</ul>
<li>Click Save</li>
</ul>
<p>You need to Define at least one Field. I recommend adding Node Title.<br />
I would also recommend adding some sort of sorting. You can have it by Post Date or if you have Statistics enabled in your Core (optional) modules, you can sort by what content is the most popular.</p>
<p>Now here is the added bonus. It doesn&#8217;t make much sense to display the same piece of content that you are currently looking at. So here is how you remedy that.</p>
<ul>
<li>Add another Argument &#8211; Node: Nid</li>
<li>Then set the argument with these options:</li>
<ul>
<li>Provide Default Argument</li>
<li>Node ID from Url</li>
<li>Check the Exclude from Argument</li>
</ul>
<li>Click Save</li>
</ul>
<p>This takes out the current piece of content that you are currently viewing. Simply drop this block in a sidebar and Views will take care of the rest.</p>
<p>Make sure and <a href="http://feedproxy.google.com/hankpalanblog"><span style="text-decoration:underline;">Subscribe</span></a> to this blog to follow along with other Tips, Tricks, and Tutorials.</p>
</div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lyphuong10.wordpress.com/104/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lyphuong10.wordpress.com/104/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lyphuong10.wordpress.com/104/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lyphuong10.wordpress.com/104/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/lyphuong10.wordpress.com/104/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/lyphuong10.wordpress.com/104/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/lyphuong10.wordpress.com/104/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/lyphuong10.wordpress.com/104/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lyphuong10.wordpress.com/104/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lyphuong10.wordpress.com/104/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lyphuong10.wordpress.com/104/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lyphuong10.wordpress.com/104/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lyphuong10.wordpress.com/104/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lyphuong10.wordpress.com/104/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=104&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://lyphuong10.wordpress.com/2011/06/16/related-node-code-term-id-c%e1%bb%a7a-node/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/8b8638691b0148442a47955d24cc60c1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">lyphuong10</media:title>
		</media:content>

		<media:content url="http://drupaleasy.com/files/view_01_add.png" medium="image">
			<media:title type="html">add a view</media:title>
		</media:content>

		<media:content url="http://drupaleasy.com/files/view_02_name.png" medium="image">
			<media:title type="html">Name your view</media:title>
		</media:content>

		<media:content url="http://drupaleasy.com/files/view_04_options.png" medium="image">
			<media:title type="html">Main Views screen</media:title>
		</media:content>

		<media:content url="http://drupaleasy.com/files/view_05_add_argument.png" medium="image">
			<media:title type="html">Add an argument</media:title>
		</media:content>

		<media:content url="http://drupaleasy.com/files/view_06_arg_defaults.png" medium="image">
			<media:title type="html">choose Taxonomy as your argument type</media:title>
		</media:content>

		<media:content url="http://drupaleasy.com/files/view_07_arg_configure.png" medium="image">
			<media:title type="html">use PHP to specify the default argument</media:title>
		</media:content>

		<media:content url="http://drupaleasy.com/files/view_08_arg_multiple.png" medium="image">
			<media:title type="html">Allow multiple terms, reduce duplicates</media:title>
		</media:content>

		<media:content url="http://drupaleasy.com/files/view_09_error.png" medium="image">
			<media:title type="html">egads, an error message</media:title>
		</media:content>

		<media:content url="http://drupaleasy.com/files/view_10_fields.png" medium="image">
			<media:title type="html">Add a field</media:title>
		</media:content>

		<media:content url="http://drupaleasy.com/files/view_11_field_options.png" medium="image">
			<media:title type="html">you want to see the node title</media:title>
		</media:content>

		<media:content url="http://drupaleasy.com/files/view_12_field_configure.png" medium="image">
			<media:title type="html">remove the Label and enable links</media:title>
		</media:content>

		<media:content url="http://drupaleasy.com/files/view_13_preview.png" medium="image">
			<media:title type="html">use some arguments to get a live preview</media:title>
		</media:content>

		<media:content url="http://drupaleasy.com/files/view_14_save.png" medium="image">
			<media:title type="html">filter and save your view</media:title>
		</media:content>

		<media:content url="http://drupaleasy.com/files/view_15_block.png" medium="image">
			<media:title type="html">your finished block with edit links</media:title>
		</media:content>
	</item>
		<item>
		<title>Panels 2: Creating a mini panel and passing arguments through context</title>
		<link>http://lyphuong10.wordpress.com/2011/05/03/panels-2-creating-a-mini-panel-and-passing-arguments-through-context/</link>
		<comments>http://lyphuong10.wordpress.com/2011/05/03/panels-2-creating-a-mini-panel-and-passing-arguments-through-context/#comments</comments>
		<pubDate>Tue, 03 May 2011 13:23:17 +0000</pubDate>
		<dc:creator>lyphuong10</dc:creator>
				<category><![CDATA[Drupal]]></category>

		<guid isPermaLink="false">http://lyphuong10.wordpress.com/?p=100</guid>
		<description><![CDATA[http://drupal.org/documentation http://drupal.org/node/213733 Overview Passing an argument from the URL into a block is a common thing. The idea is that the content of a block will change according to what is viewed. For example, we would like a block to show us all the taxonomy terms of a certain node. For this reason we need [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=100&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://drupal.org/documentation">http://drupal.org/documentation</a><br />
<a href="http://drupal.org/node/213733">http://drupal.org/node/213733</a></p>
<h2>Overview</h2>
<p>Passing an argument from the URL into a block is a common thing. The idea is that the content of a block will change according to what is viewed. For example, we would like a block to show us all the taxonomy terms of a certain node. For this reason we need to pass to the block the argument of the node id (nid). In the following url <code>http://xxx/node/123</code> argument number 1, which we will call %1, and is equal to 123.<span id="more-100"></span></p>
<p>When creating a mini panel, you get the functionality of Panel pages, but the outcome is a block that can be either configured through the blocks admin (<code>http://xxx/admin/build/block</code>), or added to a panel page.</p>
<h2>Modules</h2>
<ul>
<li>Panels</li>
<li>Panel pages</li>
<li>Mini panels</li>
<li>Views</li>
</ul>
<h2>Requirements</h2>
<ul>
<li>Create a mini panel that shows the comments the currently signed-in user has written in the currently viewed page.</li>
<li>Enable the block on nodes.</li>
</ul>
<h2>Operation</h2>
<ol>
<li>Create a view according to the requirement- user_comments_per_node. (Example attached at bottom of page.)</li>
<li>We need to prepare the integration of our view &#8216;user_comments_per_node&#8217; with panels.
<ol>
<li>Go to Admin, Panels, Views, or <code>http://xxx/admin/panels/views</code>.<img src="http://drupal.org/files/Mini%20panel%202.png" alt="" /></li>
<li>Select the view from the dropdown list and click <strong>create panel view</strong></li>
</ol>
</li>
<li>In the view Select our View &#8211; user_comments_per_node.</li>
<ol>
<li>Set the Panel view title to: User comments per node</li>
<li>Keep the view type as block, since we defined there this should appear as &#8216;List&#8217;.</li>
<li>Set the required context to: Node</li>
<li>Set the amount of items to display to five (5).</li>
<li>Click &#8216;Save&#8217;.</li>
</ol>
<li>Just to understand what&#8217;s going in this page:</li>
<ol>
<li>&#8216;Basic information&#8217; concerns the Visual representation of the Views in the panel admin.</li>
<li>&#8216;Arguments&#8217; defines which argument the view can and is allowed to get. Since panel can have several context it&#8217;s important to make sure the views gets the correct arguments.</li>
<li>&#8216;Paging information&#8217; defines whether the output of the views should be paged (i.e. those <em> | 1 | 2 | next&gt;&gt; | Last | </em> links ). Even if paging wasn&#8217;t defined in the views, it can be defined here. Also the number of posts or offset (i.e. output the view starting from the 2nd result).</li>
<li>&#8216;Pane decorations&#8217; are Merlin&#8217;s way of letting us, grateful people, decide if the panel will allow us to override few settings from the panel itself. This can become handy if you have several pages showing the same views, but need a slightly different behavior.</li>
</ol>
<li>Add a mini-panel by going to Panels -&gt; Mini Panels, or <code>http://xxx/admin/ panels/panel-mini/add</code>.</li>
<li>Set the layout as &#8216;Single column&#8217;.</li>
<li>Enter the mini panel title and name. Set the title to &#8216;My comments&#8217; and the name to &#8216;user_comments&#8217;. Click &#8216;Next&#8217;.<br />
<img src="http://drupal.org/files/Mini%20panel%203.png" alt="" /></li>
<li>We&#8217;ve been redirected to the &#8216;Content&#8217; tab – here we will add the View created previously.</li>
<li>Click on the &#8216;Add content&#8217; Icon <img src="http://drupal.org/files/issues/About%20us%201.png" alt="" /> and select under &#8216;Views&#8217; our view. Click &#8216;Add pane&#8217;.<br />
<img class="alignleft" src="http://drupal.org/files/Mini%20panel%205.png" alt="" /></li>
<li>Our view was added. Don&#8217;t forget to save the panel; just adding it is not enough.</li>
<li>The mini panel is ready, which means that in the blocks admin (<code>http://xxx/admin/build/block</code>) we have a new mini-panel called <em>Mini panel: &#8220;My comments&#8221;</em>. Set it to appear on the &#8216;Right sidebar&#8217;.</li>
<li>How to show the block only on certain content types, and in another place? Use the panel pages node override of course. <a href="http://drupal.org/node/206185" rel="nofollow">Here&#8217;s</a> a tutorial for getting started with node overrides.</li>
</ol>
<p>If you want to import a starting point, <a href="http://drupal.org/files/panels_2_creating_a_mini_panel_and_passing_arguments_through_context_code.txt" rel="nofollow">download the code</a> and import it by clicking the import tab at the top of the Panel pages module.</p>
<p>As an example View, you can start with <a href="http://drupal.org/files/user_comment_per_node.txt" rel="nofollow">this export</a>. (This may not exactly meet the initial specifications, but it does pick up comments for a particular node only.) Import the view using the Import tab under the Views UI.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lyphuong10.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lyphuong10.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lyphuong10.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lyphuong10.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/lyphuong10.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/lyphuong10.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/lyphuong10.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/lyphuong10.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lyphuong10.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lyphuong10.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lyphuong10.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lyphuong10.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lyphuong10.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lyphuong10.wordpress.com/100/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=100&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://lyphuong10.wordpress.com/2011/05/03/panels-2-creating-a-mini-panel-and-passing-arguments-through-context/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/8b8638691b0148442a47955d24cc60c1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">lyphuong10</media:title>
		</media:content>

		<media:content url="http://drupal.org/files/Mini%20panel%202.png" medium="image" />

		<media:content url="http://drupal.org/files/Mini%20panel%203.png" medium="image" />

		<media:content url="http://drupal.org/files/issues/About%20us%201.png" medium="image" />

		<media:content url="http://drupal.org/files/Mini%20panel%205.png" medium="image" />
	</item>
		<item>
		<title>How to display field_image in node&#8211;article.tpl.php with Drupal 7?</title>
		<link>http://lyphuong10.wordpress.com/2011/04/26/how-to-display-field_image-in-node-article-tpl-php-with-drupal-7/</link>
		<comments>http://lyphuong10.wordpress.com/2011/04/26/how-to-display-field_image-in-node-article-tpl-php-with-drupal-7/#comments</comments>
		<pubDate>Tue, 26 Apr 2011 09:43:13 +0000</pubDate>
		<dc:creator>lyphuong10</dc:creator>
				<category><![CDATA[Drupal]]></category>

		<guid isPermaLink="false">http://lyphuong10.wordpress.com/?p=97</guid>
		<description><![CDATA[With Drupal 7, the node type &#8220;article&#8221; comes with a field_image to upload an image. When I create a &#8220;node&#8211;article.tpl.php&#8221; and remove print render($content); I can display the body texte with this &#60;?php print $node-&#62;body['fr'][0]['safe_value'] ?&#62; but how can I display the field_image? That should be a simple thing to do but I&#8217;m looking for [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=97&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>With Drupal 7, the node type &#8220;article&#8221; comes with a field_image to upload an image. When I create a &#8220;node&#8211;article.tpl.php&#8221; and remove <code>print render($content);</code> I can display the body texte with this <code>&lt;?php print $node-&gt;body['fr'][0]['safe_value'] ?&gt;</code> but how can I display the field_image?</p>
<p><span id="more-97"></span>That should be a simple thing to do but I&#8217;m looking for that solution for the past three weeks and the module contemplate didn&#8217;t help.</p>
<div>
<div>
<p>I think this *should* work, but it doesn&#8217;t for me because the Drupal 7 implementation of image cache doesn&#8217;t seem to autogenerate the images on my machine, but maybe you&#8217;ll have better luck.</p>
<blockquote><p><code>&lt;?php<br />
print render($content);<br />
?&gt;</code></p></blockquote>
<p>Modify</p>
<p>First, a simpler way to render the body&#8230;</p>
<blockquote>
<div><code>&lt;?php<br />
print render($content['body']);<br />
?&gt;</code></div>
</blockquote>
<p>Then to render the image field:</p>
<blockquote>
<div><code>&lt;?php<br />
print render($content['field_image']);<br />
?&gt;</code></div>
</blockquote>
<p>This latter generates an element in my html source but the link points to a &#8220;default/files/styles/large/public/field/image/myimage.png&#8221; that doesn&#8217;t exist on my machine.</p>
<p>Nguồn: <a href="http://fusiondrupalthemes.com/forum/using-fusion/how-display-field_image-node-articletplphp-drupal-7">http://fusiondrupalthemes.com/forum/using-fusion/how-display-field_image-node-articletplphp-drupal-7</a></p>
</div>
</div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lyphuong10.wordpress.com/97/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lyphuong10.wordpress.com/97/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lyphuong10.wordpress.com/97/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lyphuong10.wordpress.com/97/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/lyphuong10.wordpress.com/97/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/lyphuong10.wordpress.com/97/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/lyphuong10.wordpress.com/97/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/lyphuong10.wordpress.com/97/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lyphuong10.wordpress.com/97/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lyphuong10.wordpress.com/97/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lyphuong10.wordpress.com/97/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lyphuong10.wordpress.com/97/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lyphuong10.wordpress.com/97/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lyphuong10.wordpress.com/97/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=97&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://lyphuong10.wordpress.com/2011/04/26/how-to-display-field_image-in-node-article-tpl-php-with-drupal-7/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/8b8638691b0148442a47955d24cc60c1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">lyphuong10</media:title>
		</media:content>
	</item>
		<item>
		<title>Drupal 7 ra mắt trên toàn thế giới</title>
		<link>http://lyphuong10.wordpress.com/2011/03/03/drupal-7-ra-m%e1%ba%aft-tren-toan-th%e1%ba%bf-gi%e1%bb%9bi/</link>
		<comments>http://lyphuong10.wordpress.com/2011/03/03/drupal-7-ra-m%e1%ba%aft-tren-toan-th%e1%ba%bf-gi%e1%bb%9bi/#comments</comments>
		<pubDate>Thu, 03 Mar 2011 12:09:28 +0000</pubDate>
		<dc:creator>lyphuong10</dc:creator>
				<category><![CDATA[Drupal]]></category>

		<guid isPermaLink="false">http://lyphuong10.wordpress.com/?p=93</guid>
		<description><![CDATA[Drupal đã phát triển thành một nền tảng được coi là mạnh mẽ nhất để xây dựng các trang web xã hội và ngữ nghĩa, đồng thời trở nên dễ sử dụng hơn bao giờ hết. Nguồn: http://drupal.org/node/1015696 KORTRIJK, BELGIUM &#38; CHICAGO, IL — Ngày 5 tháng 1 năm 2011 &#8211; Cộng đồng Drupal trên [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=93&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h3><em><em>Drupal  đã phát triển thành một nền tảng được coi là mạnh mẽ  nhất để xây dựng các trang web xã hội và ngữ nghĩa, đồng thời trở nên dễ  sử dụng hơn bao giờ hết.<span id="more-93"></span></em></em></h3>
<p>Nguồn: <a href="http://drupal.org/node/1015696">http://drupal.org/node/1015696</a></p>
<p><strong>KORTRIJK, BELGIUM &amp; CHICAGO, IL — Ngày 5 tháng 1 năm 2011</strong> &#8211;  Cộng đồng Drupal trên toàn thế giới cùng với Hiệp hội Drupal đón chào  việc công bố chính thức ra mắt Drupal 7, nền tảng web được đánh giá là  mạnh nhất hiện nay. Drupal là một nền tảng mã nguồn mở để quản lý nội  dung website, hiện đang được ứng dụng trên hàng triệu website và các ứng  dụng web. Những ứng dụng tiêu biểu là trang web của Nhà Trắng của tổng  thống Mỹ WhiteHouse.gov và nhiều trang web của các nghệ sĩ âm nhạc của  hãng Warner Media Group. Drupal phiên bản 7 [D7] mang đến công nghệ web  mới nhất và các cải tiến đáng kể đối với người sử dụng. Drupal 7 cũng  đang được chính thức trong các site có khả năng chịu tải rất cao, như  trang <a rel="nofollow" href="http://examiner.com/">Examiner.com</a>,  đứng trong top 100 website của Mỹ và tăng lưu lượng  19% từ tháng 10 tới  tháng 11, với hơn 22.4 triệu lượt người sử dụng hàng tháng.</p>
<blockquote><p>&#8220;Nền tảng Drupal 7 mới này cung cấp các trường API, lưu  trữ và cache thay đổi, cho phép sử dụng Mongo như là giải pháp &#8216;Không  SQL&#8217; cho các ứng dụng chịu tải cao và có khả năng mở rộng. Bộ khung kiểm  thử đơn vị mới đảm bảo phần lõi ổn định, đã được chứng minh qua những  lần hợp nhất lõi hệ thống khi phát triển dự án của chúng tôi. Trang <a rel="nofollow" href="http://examiner.com/">Examiner.com</a>, với lưu  lượng sử dụng cực lớn và khả năng xuất bản tức thì, sẽ rất khó khăn thậm  chí không thể phát triển được trên các phiên bản trước đây của Drupal&#8221;  ông Jim Davidson, chủ tịch của <a rel="nofollow" href="http://examiner.com/">Examiner.com</a> nói.</p></blockquote>
<p>Dự án phát triển Drupal 7 kết hợp giữa các chỉ dẫn của các chuyên gia  công nghệ, cùng với phản hồi của cộng đồng, để làm cho việc sử dụng  được dễ dàng hơn. Việc cải tiến cách thức sử dụng bao gồm quản lý dễ  dàng hơn, quản lý các cập nhật, truy xuất và tạo nội dung.</p>
<blockquote><p>Angie Byron (hay Webchick), người bảo trì phát triển lõi  của Drupal 7 khẳng định &#8220;Drupal 7 cải tiến giao diện người dùng, nâng  cao truy xuất, quản lý hình ảnh tốt hơn, hỗ trợ các dữ liệu meta đa nội  dung, an toàn bảo mật, khả năng mở rộng và nâng cao trao đổi cơ sở dữ  liệu. Drupal 7 vượt qua 30 nghìn lượt kiểm tra để đảm bảo tính ổn đinh.  Tóm lại, đây là một bước tiến to lớn cho Drupal và cho tất cả các nhà  phát triển website, và chúng tôi rất hạnh phúc vì có thể chính thức giới  thiệu Drupal 7 cho thế giới.&#8221;</p></blockquote>
<p>Drupal là phần mềm mã nguồn mở được sử dụng bởi hơn nửa tỉ người trên  200 quốc gia và 189 ngôn ngữ. Gần 1000 thành viên của cộng đồng Drupal  đã và đang đóng góp trực tiếp phát triển lõi Drupal 7 và các module kèm  theo.</p>
<blockquote><p>&#8220;Drupal đã tăng trưởng như một hiện tượng từ phiên bản 6.  Phiên bản 7 này tạo ra bước cải tiến lớn cho việc sử dụng, tốc độ và  chức năng”, Dries Buytaert, nhà sáng lập và trưởng nhóm phát triển  Drupal cho biết. “Chúng tôi mở ra một chương mới trong việc phát triển  web, và cùng với mọi người trên thế giới đóng chào sự kiện ra mắt Drupal  7 vào ngày 7 tháng 1 năm 2011&#8243;</p></blockquote>
<h4>Những chức năng quan trọng mới của Drupal 7</h4>
<ul>
<li><span style="text-decoration:underline;">Cải tiến giao diện sử dụng</span> đáp ứng nhu cầu của đa số 80%  người sử dụng, cho phép <span style="text-decoration:underline;">thực hiện các công việc thường gặp dễ dáng  hơn</span>, các thiết lập mặc định thông minh, phân quyền cho <span style="text-decoration:underline;">người tạo  nội dung</span> và đơn giản hóa việc quản lý chung.</li>
<li><span style="text-decoration:underline;">Hỗ trợ trong lõi các chức năng hình ảnh</span> như thay đổi kích cỡ,  cắt ảnh.</li>
<li><span style="text-decoration:underline;">Chức năng kiểm thử</span> được xây dựng sẵn và tự động hóa cho mỗi  bản vá giúp cho hệ thống ổn định lâu dài.</li>
<li>Quản lý <span style="text-decoration:underline;">nâng cấp các phiên bản</span> và <span style="text-decoration:underline;">chuyển đổi</span> từ Drupal  6 sang Drupal 7.</li>
<li><span style="text-decoration:underline;">Tốc độ và khả năng mở rộng tốt hơn</span> bằng công nghệ cache tiên  tiến, mạng truyền dữ liệu (CDN) và sao chép dữ liệu master-slave.</li>
<li><span style="text-decoration:underline;">Các trường tùy chỉnh trong lõi</span>, các trường dữ liệu cho mọi  loại nội dung và cho cả người dùng, phân loại cùng với hỗ trợ và đa ngôn  ngữ.</li>
<li><span style="text-decoration:underline;">Lớp cơ sở dữ liệu tóm tắt</span> cho phép sử dụng nhiều loại CSDL  như Maria, DB, Microsoft SQL, MongoDB, Oracle, MySQL, PostgresSQL hoặc  SQLite.</li>
</ul>
<blockquote><p>&#8220;Tại SubHub, chúng tôi giúp mọi người đạt lợi nhuận từ  nội dung trực tuyến của họ. Một năm trước, chúng tôi quyết định bắt đầu  với Drupal 7 để phát triển nền tảng quản lý nội dung thế hệ mới của  chúng tôi&#8221;, Jamie Wiseman, trưởng nhóm phát triển của SubHubLite tại  Cardiff, Wales, Vương quốc Anh nói. &#8220;Khả năng linh hoạt của Drupal giúp  chúng tôi xây dựng được hệ thống chúng tôi hằng mơ ước&#8221;.</p></blockquote>
<p>Drupal nổi tiếng trên thế giới vì mở rộng hỗ trợ đa ngôn ngữ và hỗ  trợ người tàn tật, như đã được chứng nhận tại Hà Lan là thích ứng 100%  với Yêu cầu tiếp cận nội dung web (WCAG 2.0) của tổ chức World Wide  Consortium (W3C)</p>
<h4>Hỗ trợ công nghệ web ngữ nghĩa đa nội dung (RDFa) trong lõi của  Drupal 7</h4>
<p>Drupal 7 đang tiên phong trong việc đẩy mạnh chấp nhận RDFa (chuẩn về  Khung miêu tả đa nội dung trong thuộc tính của W3C). Như chúng ta đã  biết, Google và Bing phụ thuộc vào các dữ liệu tự động lấy từ các trang  web khác.Thiết kế của Drupal 7 nhúng dữ liệu meta ngữ nghĩa vào lõi,  giúp cho nội dung của các trang web ứng dụng Drupal 7 dễ dàng được các  công cụ tìm kiếm lọc và phân tích. RDFa cung cấp thêm thông tin cho các  công cụ tìm kiếm, những thông tin không hiển thị cho người dùng như là  kinh độ và vĩ độ của một điểm trên bản đồ, hay cung cấp chuẩn thời gian  chuẩn ISO cho từng địa phương và hiển thị kết quả tìm kiếm cho từng quốc  gia.</p>
<blockquote><p>Theo Dries, nhà sáng lập Drupal, &#8220;giới thiệu công nghệ  ngữ nghĩa vào lõi của Drupal sẽ là đóng góp lớn cho tương lai của web.&#8221;</p></blockquote>
<h4>Về Hiệp hội Drupal</h4>
<p>Hiệp hội Drupal là tổ chức phi lợi nhuận hỗ trợ cộng đồng Drupal bằng  tài trợ, hạ tầng, tổ chức sự kiện, quảng cáo và phân phối. Được hỗ trợ  bởi các thành viên cá nhân và tổ chức, Hiệp hội sử dụng các nguồn lực để  giúp đẩy mạnh phát triển Drupal.</p>
<p>Hiệp hội <a rel="nofollow" href="http://association.drupal.org/">Drupal</a> có trụ sở đặt tại Bỉ. Xin tham khảo hoặc tải Drupal tại <a rel="nofollow" href="http://drupal.org/">Drupal.org</a>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lyphuong10.wordpress.com/93/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lyphuong10.wordpress.com/93/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lyphuong10.wordpress.com/93/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lyphuong10.wordpress.com/93/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/lyphuong10.wordpress.com/93/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/lyphuong10.wordpress.com/93/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/lyphuong10.wordpress.com/93/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/lyphuong10.wordpress.com/93/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lyphuong10.wordpress.com/93/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lyphuong10.wordpress.com/93/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lyphuong10.wordpress.com/93/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lyphuong10.wordpress.com/93/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lyphuong10.wordpress.com/93/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lyphuong10.wordpress.com/93/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=93&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://lyphuong10.wordpress.com/2011/03/03/drupal-7-ra-m%e1%ba%aft-tren-toan-th%e1%ba%bf-gi%e1%bb%9bi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/8b8638691b0148442a47955d24cc60c1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">lyphuong10</media:title>
		</media:content>
	</item>
		<item>
		<title>Hướng dẫn cài đặt Liferay 6.0.5 Community với Tomcat trên Ubuntu 10.04</title>
		<link>http://lyphuong10.wordpress.com/2010/10/27/h%c6%b0%e1%bb%9bng-d%e1%ba%abn-cai-d%e1%ba%b7t-liferay-6-0-5-community-v%e1%bb%9bi-tomcat-tren-ubuntu-10-04-2/</link>
		<comments>http://lyphuong10.wordpress.com/2010/10/27/h%c6%b0%e1%bb%9bng-d%e1%ba%abn-cai-d%e1%ba%b7t-liferay-6-0-5-community-v%e1%bb%9bi-tomcat-tren-ubuntu-10-04-2/#comments</comments>
		<pubDate>Wed, 27 Oct 2010 05:12:33 +0000</pubDate>
		<dc:creator>lyphuong10</dc:creator>
				<category><![CDATA[Web JSP Servlet]]></category>

		<guid isPermaLink="false">http://lyphuong10.wordpress.com/?p=87</guid>
		<description><![CDATA[Liferay Portal là 1 giải pháp dành cho doanh nghiệp dựa trên nền tảng web với khả năng mang lại kết quả gần như ngay lập tức và giá trị sử dụng lâu dài. Hãy tận hưởng lợi ích của các giải pháp toàn diện và nền tảng ứng dụng dành cho doanh nghiệp chỉ [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=87&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><strong>Liferay Portal là 1 giải pháp dành cho doanh nghiệp dựa trên  nền tảng web với khả năng mang lại kết quả gần như ngay lập tức và giá  trị sử dụng lâu dài</strong>. Hãy tận hưởng lợi ích của các giải pháp  toàn diện và nền tảng ứng dụng dành cho doanh nghiệp chỉ với 1 phần mềm  duy nhất. Trong bài viết sau, Quản Trị Mạng sẽ giới thiệu với các bạn  cách cài đặt Liferay 6.0.5 Community với tài khoản root và MySQL server  có sẵn.<br />
<span id="more-87"></span><br />
<strong><span style="color:#0000ff;">Cài đặt Java JDK</span></strong></p>
<p>Trước tiên, chúng ta cần tạo thư mục dành cho java:</p>
<blockquote><p><em>mkdir /usr/java </em></p></blockquote>
<p>tại hệ thống thử nghiệm này, chúng tôi đang sử dụng hệ điều hành  Ubuntu phiên bản 64bit (với hệ thống Ubuntu 32bit các bạn cần tải gói  i586 tương ứng). Truy cập địa chỉ <a href="http://www.oracle.com/technetwork/java/javase/downloads/jdk6-jsp-136632.html" target="_blank">này</a> và tải file <strong>jdk-6u21-linux-x64.bin</strong>, lưu vào thư mục java vừa tạo ra.</p>
<p>Tiếp theo, chúng ta cần gán thuộc tính thực thi cho file đó và kích hoạt:</p>
<blockquote><p><em>cd /usr/java<br />
chmod +x jdk-6u21-linux-x64.bin<br />
./jdk-6u21-linux-x64.bin</em></p></blockquote>
<p>Hãy thêm dòng mã /etc/profile đối với JDK6 và Liferay Portal. Mở file /etc/profile:</p>
<blockquote><p><em>nano /etc/profile </em></p></blockquote>
<p>và thêm những dòng sau vào phía cuối của file:</p>
<blockquote><p><em>export JAVA_HOME=/usr/java/jdk1.6.0_21<br />
export LIFERAY_HOME=/usr/liferay/liferay-portal-6.0.5/tomcat-6.0.26<br />
export PATH=$JAVA_HOME/bin:$LIFERAY_HOME/bin:$PATH</em></p></blockquote>
<p>Hãy chắc chắn rằng tham số JAVA_HOME và LIFERAY_HOME đã được thiết lập chuẩn xác. Để làm việc này, mở Terminal và gõ lệnh:</p>
<blockquote><p><em>echo $JAVA_HOME<br />
echo $LIFERAY_HOME </em></p></blockquote>
<p><strong><span style="color:#0000ff;">Tạo cơ sở dữ liệu</span></strong></p>
<p>Đăng nhập vào MySQL bằng tài khoản root:</p>
<blockquote><p><em>mysql -u root –p </em></p></blockquote>
<p>và bước đầu tạo cơ sở dữ liệu như sau:</p>
<blockquote><p><em>CREATE DATABASE lportal DEFAULT CHARACTER SET utf8;<br />
quit;</em></p></blockquote>
<p><strong><span style="color:#0000ff;">Tạo thư mục cho Liferay</span></strong></p>
<blockquote><p><em>mkdir /usr/liferay </em></p></blockquote>
<p><span style="color:#0000ff;"><strong>Cài đặt Liferay<br />
</strong><br />
</span>Tải và giải nén gói Liferay cùng với <a href="http://sourceforge.net/projects/lportal/files/Liferay%20Portal/6.0.5/liferay-portal-tomcat-6.0.5.zip/download" target="_blank">Tomcat</a> vào thư mục /usr/liferay. Tiếp đến, tạo file Portal-Ext.Properties:</p>
<blockquote><p><em>cd $LIFERAY_HOME/webapps/ROOT/WEB-INF/classes<br />
nano portal-ext.properties</em></p></blockquote>
<p>Và chèn thêm dòng mã sau:</p>
<blockquote><p><em>#<br />
# MySQL<br />
#<br />
jdbc.default.driverClassName=com.mysql.jdbc.Driver<br />
jdbc.default.url=jdbc:mysql://localhost/lportal?useUnicode=true&amp;characterEn<br />
coding=UTF-8&amp;useFastDateParsing=false<br />
jdbc.default.username=root<br />
jdbc.default.password=password<br />
schema.run.enabled=true<br />
schema.run.minimal=true</em></p></blockquote>
<p>Thay đổi lại giá trị username và password mong muốn.</p>
<p>Sử dụng tiếp lệnh sau:</p>
<blockquote><p><em>cd $LIFERAY_HOME/bin<br />
chmod +x *.sh</em></p></blockquote>
<p>để gán thuộc tính thực thi cho các file đó.<br />
<strong><br />
<span style="color:#0000ff;">Khởi động Liferay</span></strong></p>
<p>Lần khởi động đầu tiên này thông thường sẽ mất từ 10 – 15 phút (phụ thuộc vào cấu hình và tình trạng phần cứng):</p>
<blockquote><p><em>$LIFERAY_HOME/bin/startup.sh </em></p></blockquote>
<p>và để truy cập vào Liferay, các bạn áp dụng mẫu sau:</p>
<blockquote><p><em>http://&lt;địa chỉ IP của server Liferay&gt;:8080 </em></p></blockquote>
<p>ví dụ ở đây là:</p>
<blockquote><p><em>http://192.168.0.1:8080 </em></p></blockquote>
<p>Trên đây là 1 số thao tác cơ bản để cài đặt và sử dụng Liferay 6.0.5  Community cùng với Tomcat trên nền tảng Ubuntu 10.04. Chúc các bạn thành  công!</p>
<p>http://www.quantrimang.com.vn/hedieuhanh/linux/70690_Huong-dan-cai-dat-Liferay-6-0-5-Community-voi-Tomcat-tren-Ubuntu-10-04.aspx</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lyphuong10.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lyphuong10.wordpress.com/87/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lyphuong10.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lyphuong10.wordpress.com/87/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/lyphuong10.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/lyphuong10.wordpress.com/87/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/lyphuong10.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/lyphuong10.wordpress.com/87/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lyphuong10.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lyphuong10.wordpress.com/87/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lyphuong10.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lyphuong10.wordpress.com/87/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lyphuong10.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lyphuong10.wordpress.com/87/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lyphuong10.wordpress.com&amp;blog=14812623&amp;post=87&amp;subd=lyphuong10&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://lyphuong10.wordpress.com/2010/10/27/h%c6%b0%e1%bb%9bng-d%e1%ba%abn-cai-d%e1%ba%b7t-liferay-6-0-5-community-v%e1%bb%9bi-tomcat-tren-ubuntu-10-04-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/8b8638691b0148442a47955d24cc60c1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">lyphuong10</media:title>
		</media:content>
	</item>
	</channel>
</rss>
