http://jkoz.thew.net/LiferayDevNotes.html
NOTE: These are my personal notes that I made while trying to disect the open source portal system Liferay. I makes these types of notes whenever I am trying to figure out a new open source software system. These are my impressions and assumptions based on what I found. Since I am NOT a member of the Liferay development team, I make no guarantees that what you will read here is accurate. These are my notes as of Liferay Profession v4.0.0
![](https://i-blog.csdnimg.cn/blog_migrate/17873ad9d5188511051a2a936ca1bc42.png)
click to enlarge
SourceForge holds latest development build (use subversion to retrieve).
Latest stable version should be obtained by following these directions: http://content.liferay.com/4.0.0/docs/quickstart/ch04s01.html#d0e815
App is authored using Eclipse
Compilation, bundling, and deployment are done using an extensive set of Ant scripts
JIRA is at http://support.liferay.com
To get started to get an installation going (Professional version on Tomcat 5.5, which is the most lightweight), follow the "Easy" directions here: http://content.liferay.com/4.0.0/docs/developers/ch02s01.html#d0e1803
To get started for development, following the steps to set up a development enviornment (called the "Extension environment") here: http://content.liferay.com/4.0.0/docs/quickstart/ch04s01.html
Notes: create <projectdir>/liferay/portal, and unzip the source into that directory. Use <projectdir>/liferay as the "workspace" dir. The "extension environment" directory will be <projectdir>/liferay/ext
once the build-ext Ant target has run, the script for mysql is in /ext/sql/create/create-mysql.sql. Other db scripts are also in /ext/sql/create dir.
To configure to use mysql:
1. Run the create-mysql.sql script throuh mysql's command line (it may take a while to execute).
2. Change the Tomcat 5.5 config to utilize MySQL database by following directions here: http://content.liferay.com/4.0.0/docs/developers/ch02s02.html#d0e3189
Note: correct entry in config is url="jdbc:mysql://localhost/lportal?useUnicode=true&characterEncoding=UTF-8"
Portlets can be disabled by editing WEB-INF/liferay-portlet-ext.xml
Notes: problems with the "out of box" entries (as of professional 4.0.0) once comments are removed:
line 116: (two <include> entries)
line 211: (two <include> entries)
line 215: (two <include> entries)
The "Add content" options are controlled by the contents of WEB-INF/liferay-display.xml. A portlet also has to be active to be displayed. If no portlets in the category are active, the category is suppressed (bug: if it has a sub-category, it will always be displayed).
If you change the id of a category (or you want to "rephrase" an existing category), add an entry into WEB-INF/classes/content/Language-ext.properties (see "Language display/customization" below).
A key configuration file is /portal/portal-ejb/classes/portal.properties located in the source tree (and stored in the WEB-INF/lib/portal-ejb.jar in the deployed app). It contains many interesting configuration settings:
·
"OmniAdmin" users who can administer the entire portal (omniadmin.users=)
·
Turning off "terms of use"
Entries in portal.properties should be overridden by defining properties in the "extension" version namedportal-ext.properties (not by modifying portal.properties). They can also be overridden on a virtual host basis by defining a portal-companyId.properties file. This file is located in the /ext/ext-ejb/classes dir in the source tree (and in WEB-INF/classes dir of the deployed app).
Multiple portal instances can be hosted with a single server and single DB: http://content.liferay.com/4.0.0/docs/developers/ch02s05.html
Development is done in the /ext directory. When new versions of Liferay come out, the /portal directory can be toasted, and the /ext directory "updated" by re-running the build-ext target found in /portal/build.xml.
Any new jar files required by your extensions should be placed in /ext/ext-lib
To develop a sample application, follow the directions here: http://content.liferay.com/4.0.0/docs/quickstart/ch04s02.html
Note: The Language-ext.properties file referred to in the docs is located at /ext/ext-ejb/classes/content/Language-ext.properties
Multiple web sites can be developed by modifying /portal/web-sites/web-sites.xml. <- Investigate this more? It is used by com.liferay.portal.tools.WebSiteBuilder to build various sites under the /ext/web-sites dir.
Language/display information is defined in /portal/portal-ejb/classes/content/Language.properties (and various other Language_*.properties files for foreign languages). It can be re-defined on a deployment by deployment basis by overriding in WEB-INF/classes/content/Language-ext.properties
The "entry point" into the system (if you want to do a code trace) is com.liferay.portal.servlet.MainServlet (assuming the request URL starts with "/c"). It is a specialized version of org.apache.struts.action.ActionServlet (the standard Struts "controller"). A custom request processor (com.liferay.portal.struts.PortletRequestProcessor) handles the actual requests. It is an extension of org.apache.struts.tiles.TilesRequestProcessor. The primary struts config file can be found in the source tree at /portal/portal-web/docroot/WEB-INF/struts-config.xml. It is ultimately merged in with other Struts config files and stored in the deployed app at WEB-INF/struts-config.xml
A "new" company id, upon first entry to the first portal, is created (i.e. added to the database) by the code at
com.liferay.portal.service.impl.CompanyLocalServiceImpl::checkCompany().
Note: CompanyLocalServiceImpl implements the CompanyLocalService interface. A NEW service could be written, and replaced using the Spring configuration if a custom "new company" configuration were desireable!
com.liferay.portal.util.WebKeys
holds a series of identifiers for attributes that are stored in the "portal context" (i.e. the javax.servlet.ServletContext), the session, and/or the request. Many of these values are initialized by the com.liferay.portal.servlet.MainServlet
The default main path to be displayed (assuming no specific path is asked of by the caller) is "/c", and it is defined as the "Root path" plug the com.liferay.portal.servlet.MainServlet.DEFAULT_MAIN_PATH. The "root path" is defined as a serverlet configuration parameter to the MainServlet in its web.xml.
com.liferay.portal.util.PortalUtil
is a helper class that can be used to retrieve a variety of information about the portal runtime environment.
Re: source organization, there are two major groups of modules: those in the ../portal dir represent the "core" modules to the portal system, and those in the ../portlet dir represent individual portlet modules. Some of the "portlets" are actually critical to the administration of the portal, so not all modules in ../portlet are optional. It is unclear (to me at this point) which are and which are not "critical."
Most of the "core" portal code can be found in /portal/portal-ejb/src, esp in the package com.liferay.portal.service.impl.
*.properties
files are read and managed by the open source library EasyConf. See http://easyconf.sourceforge.net/index.html
Notes on EasyConf: it appears that for each property file named <someprefix>.properties, a "development environment override" file named <someprefix>.<username>.properties can be created, where <username> is the user name of the OS. My Windows XP has a user name of "Joel", so indiviual build properties can by overridden by creating a file named build.Joel.properties, and making entries for just the entries I wanted changed for my dev environment.
A key configuration file is /portal-ejb/classes/portal.properties. It contains many configuration settings:
registration of "event handlers." Various events (e.g. application start-up, session creation and destruction, etc.) can have one or more handler classes listed. If a class is listed, it is called by the event management system. Key players in this mechanism are:
com.liferay.portal.events.EventsProcessor
(the dispatcher)
com.liferay.portal.servlet.MainServlet
(calls EventsProcessor for most events)
com.liferay.portal.servlet.PortalSessionListener
(calls EventsProcessor for session creation and destruction events)
com.liferay.portal.action.LogoutAction
(calls EventsProcessor when user logs out)
com.liferay.portal.util.InitUtil
(calls EventsProcessor during initialization)
com.liferay.portal.events.ServicePreAction
is a key class that is the "pre-processor" action for all calls to the portlet. It handles validating the current user, determining which theme and layout to display, etc. "Which layout to display" is a key part of the "guest" page.
Entries in portal.properties should be overridden by defining properties in the "extension" version namedportal-ext.properties (not by modifying portal.properties). They can also be overridden on a virtual host basis by defining a portal-companyId.properties file.
Portlet definitions (i.e. which portlets exist and are available to users) are defined in:
A. Source tree
/portal-web/docroot/WEB-INF/portlet.xml
/portal-web/docroot/WEB-INF/liferay-portlet.xml
/portal-web/docroot/WEB-INF/liferay-display.xml
/portal-ejb/classes/content/Language.properties
B. Distribution tree
<JBOSS_HOME>
/server/default/deploy/ext.ear/_portal-web-complete.war/WEB-INF/portlet.xml
<JBOSS_HOME>
/server/default/deploy/ext.ear/_portal-web-complete.war/WEB-INF/liferay-portlet.xml
<JBOSS_HOME>
/server/default/deploy/ext.ear/_portal-web-complete.war/WEB-INF/liferay-display.xml
<JBOSS_HOME>/
server/default/deploy/ext.ear/portal-ejb.jar/content
or, if using Tomcat, they are in <tomcat_home>/<domain/company_id>/WEB-INF/...
explanations of these structures can be found at http://content.liferay.com/4.0.0/docs/developers/ch08s01.html
/ext/sql/portal-tables.sql
contains the database definitions (generic definitions). This file is a mix of "core" and portlet required tables.
The build of the database script is executed by the DBBuilder class, which supports macro expansion, and sql dialect translation.
DBBuilder reads sql fragments, with the primary fragment being in ext/sql/portal.sql
Hibernate mappings are stored primarily in /portal-ejb/classes/META-INF/portal-hbm.xml in the source tree (<JBOSS_HOME>/server/default/deploy/ext.ear/portal-ejb.jar/META-INF in the distribution), but there are others. All Hibernate mapping files to be used are defined under the hibernate.configs option of portal.properties.
The hibernate session is managed by com.liferay.portal.spring.hibernate.HibernateUtil.
Spring definitions are stored primarily in /portal-ejb/classes/META-INF/portal-spring-enterprise.xml (or /portal-ejb/classes/META-INF/portal-spring-professional.xml for the "professional" version). Spring definitions to load are listed in portal.properties under the spring.configs entry.
LifeRay developers use a special code generator to create source code, not unlike AndroMDA. The "model" that is input to this code generator is a file named service.xml, which contains a proprietary definition of entities, finder methods required for each entity, and exceptions that the module may throw. There is a single service.xml for the ../portal subsystem. Each individual ../portlet module seems to have its own service.xml. The actual code generator is the class com.liferay.portal.tools.ServiceBuilder located in /portal-ejb/src/com/liferay/portal/tools/ServiceBuilder.java. It is called by the build-service target in the Ant file located in /portal-ejb/build.xml. See http://forums.liferay.com/index.php?showtopic=622
In general, "services" of the portal container have their interfaces defined in the source tree at portal/portal-ejb/src/com/liferay/portal/service/spring (or ./ejb, or ./http), and the implementation is located in portal/portal-ejb/src/com/liferay/portal/service/impl
Th default user roles "Guest", "Power User", and "User" are hard coded, defined in com.liferay.portal.util.RoleNames
The default pre-defined system group "Guest" is hard coded and defined in com.liferay.portal.util.GroupNames
The portlets available to the portal are defined in WEB-INF/portlet.xml (the JSR168 portlet descriptor file), and WEB-INF/liferay-portlet.xml (the liferay specific portlet descriptor file). Liferay specific configuration includes options such as:
1. Are the preferences of the portlet unique for each individual page (a.k.a. layout) that contains it?
2. Are the preferences owned by the group (a.k.a. community) that the user is in (i.e. is there a single configuration for the entire group?)
Users are members of one or more "Groups". A "System Group" is a base set of groups that is auto created. These groups are added to the database in com.liferay.portal.service.impl.GroupLocalServiceImpl.checkSystemGroups() starting at line 163.
Every user is a member of their own private group (i.e. a specific group is created for each user, and that user is the only member of that group). This is done because groups own layout sets, and a layout set represents the portal (and users can have their own private portal).
Every group (whether a public group or a private group) has two layout sets associated with it: a public layout set, and a private layout set.
The "guest" user is actually an anonymous user. When the portal is first visited, if no user can be identified, the "default" (a.k.a. "guest") user is created. This user is assigned to a com.liferay.portal.model.User object (which also exists in the database and is used by Hibernate to populate the "guest" User entity when needed). The guest user has a default user ID, and is assigned to a default group, which has a default layout. Once in the database, the default user can be retrieved by calling UserLocalServiceUtil.getDefaultUser(companyId). The user ID of the default user is the company id of the portal, plus the suffix ".default".
The default user is added to the database in com.liferay.portal.service.impl.CompanyLocalServiceImpl at line 178. This in turn calls GroupLocalServiceUtil.checkSystemGroups(), which ends up calling GroupLocalServiceImpl.addDefaultLayouts():
The default user's layout is added to the database in com.liferay.portal.service.impl.GroupLocalServiceImpl.addDefaultLayouts() starting at line 436. The default user's group name is defined in com.liferay.portal.util.GroupNames.
A "layout" is an instance of a single page, composed of one or more portlets arranged inside of various columns (sometimes referred to as the "narrow" and "wide" columns). A layout is somewhat synonymous with a "page" (i.e. a single web page). They have a unique internal ID known as the "portlet layout Id". They are stored in the Layout table. The primary key of the Layout table (com.liferay.portal.service.persistence.LayoutPK) is composed of the "owner id" and the "layout id". The "owner id" is composed of a prefix indicating if it is "public" (PUB.) or "private" (PRI.), followed by the "group id" (i.e. the community that owns the layout). A "public" layout is one that is shared by more than one user, and thus changes to the layout by the end user should not be persisted. To facilitate this, the portal system will "clone" a temporary version of the public layout for the user to configure. This temporary version survives only for the duration of the session.
The layout Id is sequential number unique for the specified owner Id.
Every group has both a public and a private layout set associated with it. Thus (theoritically), every group has both a public and a private web site).
Only users who are in the "Power User" category are allowed to create/modify layouts for the portal.
The default user layout name is "Home", defined in portal.properties under default.user.layout.name
Sometimes in the code, you'll see reference to the request parameter p_l_id (which may be represented by the variable plid). The "plid" is an encoded string that contains "owner ID" and "layout id" components concatinated. Call Layout.getLayoutId(plid) or Layout.getOwnerId(plid) to extract the desired component. The owner ID can further be de-composed into the group ID by calling Layout.getGroupId(ownerId).
A layout is assigned one of three types:
1. Porlet: A standard page that is a container for one or more portlets
2. Embedded: Embeds the contents of another URL into the page (i.e. the page contents will be the page contents of the specified URL).
3. URL: Selecting this page will redirect the user to the new URL. Unlike Embedded, the browser's address will become the new URL (vs. having the contents found at the URL embedded in the portal).
4. Article: Unknown purpose. Does not seem to be referenced in the code.
Internal code: A layout has an associated "type settings" (type as in class, not as in typeface), which holds type specific configuration. For example, the "type settings" for a Portlet layout is actually a comma separated list of name/value pairs (properties) that contains, among other things, the individual portlets that are contained within the layout. The "type settings" for URL are the URL iteself.
Each "layout" (a.k.a. page) has a layout template associated with it. The layout template is stored in the layout-template-id property in a "portlet layout"'s "type settings."
A "layout template" describes how various columns and rows are arranged to display the portlets. Layout templates are located in the deployed servlet's html/layouttpl/standard and html/layouttpl/custom directories as a series of .tpl files. The templates are defined in the source tree at /portal/portal-web/docroot/html/layouttpl/custom. They appear to be Velocity files.
The layout templates that are available to a portal are described (initially) in WEB-INF/liferay-layout-templates.xml (as well as WEB-INF/liferay-layout-templates-ext.xml). These layouts are read in by com.liferay.portal.service.impl.LayoutTemplateLocalUtil (which is called by MainServlet at startup time, or by com.liferay.portal.deploy.HotDeployLayoutTemplateListener if deployed at runtime). Layout definitions are held in in-memory collections of com.liferay.portal.model.LayoutTemplate objects (and not in the database).
A "theme" is a portal "skin" that has a particular look and feel. It is a collection of .jsp or velocity templates that contain fragments of the various components that make up the HTML sent to the client browser. Though most theme template bundles contain a variety of template files, the "required" template files are:
portal_normal.[vm|jsp]
Controls the layout of portal templates for "normal" pages
portal_pop_up.[vm|jsp]
Controls the layout of portal templates for "pop-up" pages
portal_init.[vm|jsp]
is not really a required template, but by convention, it exists, and is included by both the portal_normal and portal_pop_up template.
NOTE: It appears that Velocity is now the template engine of choice. The Velocity context is created and initialized in com.liferay.taglib.util.ThemeUtil.includeVM().
Each layout is a member of (?one and only one?) layout set (com.liferay.portal.model.LayoutSet). A layout set represents a group of layout pages, and thus a layout set can be thought of as a "web site", or more specifically, a "portal instance." Since each user has a private group associated with them, this allows each individual user to maintain their own custom portal.
The theme and color scheme used by a layout can either be set individually for the layout, or it is inherited from its layout set.
A theme can have one or more "color schemes", which gives even more flexability to the look and feel of a theme. The Ant script /portal/portal-web/build.xml contains the target build-color-scheme that is capable of generating images that match a color scheme (using the services of com.liferay.portal.tools.ColorSchemeBuilder). Developer information on the theme system (the "look and feel") can be found here: http://content.liferay.com/4.0.0/docs/users/ch05s03.html
The themes that are available to a portal are described in WEB-INF/liferay-look-and-feel.xml (as well as WEB-INF/liferay-look-and-feel-ext.xml). These themes are read in by com.liferay.portal.service.impl.ThemeLocalUtil. Theme definitions are held in in-memory collections of com.liferay.portal.model.Theme objects (and not in the database).
Themes can be limited to certain company Ids (by including or excluding the themes in the <company-limit> section of WEB-INF/liferay-look-and-feel.xml).
A variety of community contributed themes are available for download from here: http://www.liferay.com/web/guest/downloads/themes
Though a little out of date (it was for version 3.6.1), there is a more thourough guide to creating themes in this pdf file: http://content.liferay.com/3.6.1/Liferay%20Themes.pdf
Pages are rendered via the following mechanism:
1. Request comes in through MainServlet. Various attributes are stored in the session and request. The request attribute WebKeys.CURRENT_URL holds the currently requested path (stripped of protocol,host, and port)
2. The "service pre action" handler com.liferay.portal.events.ServicePreAction is called, where the layout and theme to display are determined. The current layout is stored as a request attribute under the key WebKeys.LAYOUT. The other available layouts are stored as a request attribute under the key WebKeys.LAYOUTS. The theme to display is stored as a request attribute under the WebKeys.THEME key, and the color scheme to use is stored as the request attribute WebKeys.COLOR_SCHEME. The theme and color scheme are usually determined by querying the layout once it has been determined.
3. Struts is called to handle the request, and Liferay uses the custom Struts request processor com.liferay.portal.struts.PortalRequestProcessor. The PortalRequestProcessor.getLastPath() method computes the last path visited, and supplies a default path for the first entry into the portal. The default path upon entry into the portal is <protocol>://<hostName>:<port>/portal/layout. This url may optionally contain the query parameters ?p_l_id=default if the user is known (i.e. they have just logged in).
4. This initial request for /portal/layout is handled by com.liferay.portal.action.LayoutAction.
5. /html/common/themes/portal.jsp is the "top level" display page. It selects...
6. the portal_normal.jsp or portal_pop_up.jsp based on the current state of the theme's display, and includes it using the <liferay-theme:include> custom tag, implemented by com.liferay.taglib.theme.IncludeTag, which in turn calls com.liferay.taglib.util.ThemeUtil.include().
A "friendly URL" is one that calls the portal system using an end user friendly URL, vs. one that has a lot of parameters and is more machine derived. Friendly URLs are served by com.liferay.portal.servlet.FriendlyURLServlet, which is configured in WEB-INF/web.xml for both "public" and "private" URLs. The default "public" friendly URL is a request that starts with /web/* (vs. the normal /c/* which calls the MainServlet). A "private" URL starts with /group/*. These can be configured by changing the servlet mapping in web.xml, as well as layout.friendly.url.private.servlet.mapping and layout.friendly.url.public.servlet.mapping properties in the portal.properties file (overwrite them in portal-ext.properties).
(These instructions do not yet exist in the Liferay docs)
0. Insure mysql connector .jar is in <tomcat>/common/lib/ext
1. copy <tomcat>/liferay to <tomcat>jkoz.com
2. Edit <tomcat>jkoz.com/WEB-INF/web.xml and change the company_id parameter to jkoz.com
3. copy <tomcat>/liferay/conf/Catalina/localhost to <tomcat>/liferay/conf/Catalina/www.jkoz.com
4. Edit <tomcat>/liferay/conf/Catalina/www.jkoz.com/ROOT.xml, change the docBase attribute of the <Context> tag to read docBase="../jkoz.com", and insure the jdbc/LiferayPool is configured for mySQL (or whatever other database you are using)
5. Edit <tomcat>/liferay/conf/server.xml and add the following just before </Engine>:
<Host name="www.jkoz.com" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
<DefaultContext cookies="true" crossContext="true" override="true" />
</Host>
To get started to get an installation going (Enterprise version (JBoss+Tomcat )), follow the "Easy" directions here: http://content.liferay.com/4.0.0/docs/developers/ch02s01.html#d0e486
To configure to use mysql:
1. Run the create-mysql.sql script throuh mysql's command line (it may take a while to execute).
2. Change the JBoss+Tomcat config to utilize MySQL database by following directions here: http://content.liferay.com/4.0.0/docs/developers/ch02s02.html#d0e3093
In this example, "jkoz.com" will be the domain to use. Complete directions are here: http://content.liferay.com/4.0.0/docs/developers/ch02s05.html#d0e4449
1. Make a new copy of the portal .war directory (i.e. copy <JBOSS_HOME>/server/default/deploy/ext.ear/_portal-web-complete.war directory to <JBOSS_HOME>/server/default/deploy/ext.ear/_portal-web-<domain-name-without-dot-com>.war)
2. Modify /WEB-INF/web.xml, in the new dir, changing the <context-param> value of company_id to the new domain name.
3. Modify /WEB-INF/jboss-web.xml to add the new virtual-host entry
4. Modify the portal app's /server/default/deploy/ext.ear/META-INF/application.xml to add the new portal .war dir as a module.
5. Modify /server/default/deploy/jbossweb-tomcat50.sar/server.xml to add the new host entries