Sun, JavaServer, JSP, Java, JMX, JDK, Java runtime environment, J2EE, JVM, Javadoc, 100% Pure Java, JDBC, and JavaScript are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.
JBoss is a registered trademark of Red Hat, Inc. in the U.S. and other countries.
Red Hat is a registered trademark of Red Hat, Inc. in the United States and other countries.
Oracle is a registered trademark of Oracle International Corporation.
Microsoft, Windows, Active Directory, and SQL Server are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.
Linux® is the registered trademark of Linus Torvalds in the U.S. and other countries.
UNIX is a registered trademark of The Open Group.
MySQL is a trademark or registered trademark of MySQL AB in the U.S. and other countries.
Apache is a trademark of The Apache Software Foundation.
Mac and Mac OS are trademarks of Apple Inc., registered in the U.S. and other countries.
All other trademarks referenced herein are the property of their respective owners.

Many IT organizations look to achieve a competitive advantage for the enterprise by improving business productivity and reducing costs. Today's top enterprises are realizing this goal by deploying enterprise portals within their IT infrastructure. Enterprise portals simplify access to information by providing a single source of interaction with corporate information. Although today's packaged portal frameworks help enterprises launch portals more quickly, only JBoss® Portal can deliver the benefits of a zero-cost open source license, combined with a flexible and scalable underlying platform.
JBoss Portal provides an open source and standards-based environment for hosting and serving a portal's Web interface, publishing and managing its content, and customizing its experience. It is entirely standards-based, and supports the JSR-168 Portlet Specification (Portlet 1.0) and JSR-286 Portlet Specification (Portlet 2.0) , which allows you to easily plug-in standards-compliant portlets to meet your specific portal needs. JBoss Portal is available through the business-friendly LGPL open source license, and the JBoss Enterprise Portal Plarform is supported by JBoss Enterprise Middleware Professional Support and Consulting. JBoss support services are available to assist you in designing, developing, deploying, and ultimately managing your portal environment. JBoss Portal is currently developed by JBoss Enterprise Middleware developers, and community contributors.
The JBoss Portal framework and architecture include the portal container, and support a wide range of features, including standard portlets, single sign-on, clustering, and internationalization. Portal themes and layouts are configurable. Fine-grained security administration -- down to portlet permissions -- rounds out the security model.
JBoss Portal Resources:
The JBoss Portal team encourages you to use this guide to install and configure JBoss Portal. If you encounter any configuration issues or simply want to take part in our community, we would love to hear from you in our forums.
The following list details features found in this release of JBoss Portal. For a technical view of the JBoss Portal features, refer to the Project Roadmap and Task List .
Technology and Architecture
JEMS: leverages the power of JBoss Enterprise Middleware Services: JBoss Application Server, JBoss Cache, JGroups, and Hibernate.
Database Agnostic: works with any RDBMS supported by Hibernate.
Java™ Authentication and Authorization Service (JAAS): custom authentication via JAAS login modules.
Caching: utilizes render-view caching for improved performance.
Clustering: cluster support allows the portal state to be clustered for all portal instances.
Hot-deployment: leverages JBoss dynamic auto-deployment features.
SAR Installer: browser-based installer makes installation and initial configuration a breeze.
Single Sign On
Leverages Apache Tomcat and JBoss Single Sign On (SSO) solutions.
Integrates with Java Open Single Sign-On (JOSSO) and Central Authentication Service (CAS) out of the box. Experimental support for the Open Web SSO project (OpenSSO).
LDAP
Connect to virtually any LDAP server.
Integrates with Sun™ Active Directory and OpenLDAP out of the box. Experimental support for Microsoft® Active Directory®.
Supported Standards
Portlet Specification and API 1.0 (JSR-168).
Portlet Specification and API 2.0 (JSR-286).
Content Repository for Java™ technology API (JSR-170).
JavaServer™ Faces 1.2 (JSR-252).
JavaServer™ Faces 2.0 (JSR-314).
Java Management Extension (JMX™) 1.2.
Web Services for Remote Portlets (WSRP) 1.0: refer to WSRP support in JBoss Portal for further details.
Full J2EE™ 1.4 compliance when used with JBoss Application Server.
Portal and Portal Container
Multiple Portal Instances: the ability to have multiple portal instances running inside one portal container.
IPC: the Inter-Portlet Communication API enables portlets to create links to other objects, such as pages, portals, and windows.
Dynamic: the ability for administrators and users to create and destroy objects such as portlets, pages, portals, themes, and layouts at runtime.
Internationalization: the ability to use internationalization resource files for every portlet.
Pluggable Services: with authentication performed by the servlet container and JAAS, it is possible to swap the authentication scheme.
Page-based Architecture: allows the grouping and division of portlets on a per-page basis.
Existing Framework Support: portlets utilizing Apache Struts, Spring Web MVC, Sun JSF-RI, AJAX, and Apache MyFaces are supported.
Themes and Layouts
Swapping Themes and Layouts: new themes and layouts containing images can easily be deployed in WAR archives.
Flexible API: the Theme and Layout APIs are designed to separate the business layer from the presentation layer.
Per-page Layout Strategy: different layouts can be assigned to different pages.
User and Group Functionality
User Registration and Validation: configurable registration parameters allow user email validation before activation.
Workflow: ability to define your own jBPM workflow on user registration.
User Log In: makes use of servlet container authentication.
Create and Edit Users: ability for administrators to create and edit user profiles.
Create and Edit Roles: ability for administrators to create and edit roles.
Role Assignment: ability for administrators to assign users to roles.
CAPTCHA Support: distinguish between humans and machines when registering.
Permissions Management
Extendable Permissions API: allows custom portlet permissions based on role definition.
Administrative Interface: allows permission assignments to roles at any time for any deployed portlet, page, or portal instance.
Content Management System
JCR-compliant: the CMS is powered by Apache Jackrabbit, an open source implementation of the Java™ content repository API.
Database and File System Store Support: configure the content store for either a file system or an RDBMS.
External Blob Support: configurable content store, allowing large blobs to reside on a file system, and content node references and properties to reside in an RDBMS.
Version and History Support: all content edited and created is auto-versioned with a history of edits, that can be viewed at any time.
Content Serving Search-engine-friendly URLS:
http://your-domain/portal/content/index.html (does not apply to portlet actions).
No Long Portal URLS:
serve binaries with simple URLs
(http://your-domain/files/products.pdf).
Multiple HTML Portlet Instance Support: allows extra instances of static content from the CMS to be served under separate windows.
Directory Support: create, move, delete, copy, and upload entire directory trees.
File Functions: create, move, delete, copy, and upload files.
Embedded Directory-browser: when creating, moving, deleting, or copying files, administrators can navigate the directory tree to find the collection they want to perform the action on.
Ease-of-use Architecture: all actions to be performed on files and folder are one mouse-click away.
Full-featured HTML Editor: the HTML editor contains a WYSIWYG mode, preview functionality, and HTML source editting mode. HTML commands support tables, fonts, zooming, image and URL linking, flash movie support, bullet and numbered list, and dozens more.
Editor Style Sheet Support: to easily chose classes, the WYSIWYG editor displays the current portal style sheet.
Internationalization Support: content can be attributed to a specific locale, and then served to the user based on his or hers Web browser settings.
Workflow Support: basic submit for review and approval process.
This guide is aimed towards portlet developers, portal administrators, and those wishing to implement and extend the JBoss Portal framework. For end-user documentation, please refer to the JBoss Portal User Manual from the JBoss Portal Documentation Library .
We would like to thank the developers that participate in the JBoss Portal project.
Specifically:
Luca Stancapiano, Luc Boudreau and Anton Borisow for their Italian, Canadian French and Russian localization contributions.
Antoine Herzog and Peter Johnson for helping in the forums.
Mark Fernandes and Paul Tamaro from Novell, for their hard work in supplying the portal project with usable and attractive themes and layouts in the 2.4 version of JBoss Portal.
Martin Holzner from Novell, for his work on themes in the 2.4 version of JBoss Portal.
Kev "kevs3d" Roast for supplying us with two working portlets that integrate existing frameworks in to the portal: Sun JSF-RI and Spring MVC portlets.
Swarn "sdhaliwal" Dhaliwal for supplying us with the Struts-Bridge, that will allow for existing Apache Struts applications to work with JBoss Portal.
A few Red Hat employees: Remy Maucherat for Apache Tomcat configuration, Magesh Kumar Bojan and Martin Putz for always being there to help our customers, Prabhat Jha for making sure that JBoss Portal runs great everywhere, Murray Mc Allister for his work on the doc, Noel Rocher for his contributions and early feedback on JBoss Portal 2.6, James Cobb for the renaissance theme and many others !
The JBoss Labs (http://www.jboss.org) team for building a great infrastructure on top of JBoss Portal 2.6, providing very useful feedback, and giving us the initial Drag and Drop implementation.
Everyone in general who participates on the code, in the forums and on the Wiki.
Contributions of any kind are always welcome. You can contribute by providing ideas, filing bug reports, producing code, designing a theme, writing documentation, and so on. If you think your name is missing from this page, please let us know.
The following chapter details hardware and software versions that are compatible with JBoss Portal. The hardware and software listed has either been tested, or reported as working by users. Before reporting a problem, make sure you are using compatible hardware and software.
If you successfully installed JBoss Portal on versions not listed here, please let us know so it can be added to this section.
JBoss Portal is 100% Pure Java™, and therefore it is interoperable with most operating systems capable of running a Java Virtual Machine (JVM™), including Linux®, Windows®, UNIX® operating systems, and Mac OS X.
JBoss Portal 2.7.0 is tested with JBoss Application Server (AS) JBoss AS 4.2.3, JBoss Enterprise Application Platform (EAP) 4.2 and JBoss EAP 4.3. It is highly recommended that customers who have access to the JBoss Customer Support Portal (CSP) use JBoss EAP 4.3. Customers who do not have access to the JBoss CSP should use JBoss AS.
JBoss AS versions 4.0.x are not supported.
JBoss Portal is database-agnostic. The following list outlines known-to-be-working database vendor and version combinations:
xJBoss Portal employs Hibernate as an interface to a Relational Database Management System (RDBMS). Most Relational Database Management Systems supported by Hibernate will work with JBoss Portal.
Depending on your needs, there are several different methods to install JBoss
Portal. Pre-configured clustered versions (
JBoss Portal Binary (Clustered)
) are available from the
JBoss Portal Downloads
page. Clustered versions of JBoss Portal must be deployed in the
JBOSS_INSTALLATION_DIRECTORY/server/all/deploy/
directory. All JBoss AS instances must reference the same datasource. Refer to
Section 2.3.2.2, “Operating System Environment Settings”
for details on how to configure JBoss Portal for clustering.
An environment variable,
JBOSS_HOME
, is configured in
Section 2.3.2.2, “Operating System Environment Settings”
. References to
$JBOSS_HOME
assume this to be your
JBOSS_INSTALLATION_DIRECTORY
.
This is the easiest and fastest way to get JBoss Portal installed and running. The JBoss Portal and JBoss AS bundle contains JBoss AS, JBoss Portal, and the embedded Hypersonic SQL database. To install the JBoss Portal and JBoss AS bundle:
Get the bundle:
the bundle is available from the
JBoss Portal Downloads
page. Bundles use the
JBoss Portal + JBoss AS
naming convention.
Extract the bundle:
extract the ZIP archive. It does not matter which directory is used. On
Windows, the recommended directory is
C:\jboss-
.
version-number
Start the server:
change into the
JBOSS_PORTAL_INSTALLATION_DIRECTORY/bin/
directory. On Windows, execute
run.bat
. On Linux, run the
sh run.sh
command. To specify a configuration to use, for example, the default
configuration, append the
-c default
option to the
run.bat
or
sh run.sh
commands.
Log in to JBoss Portal: using a Web browser, navigate to http://localhost:8080/portal to open the JBoss Portal homepage. Log in using one of the two default accounts: username user , password user , or username admin , password admin :

Tables are automatically created the first time JBoss Portal starts. When deployed for the first time, JBoss Portal checks for the existence of the initial tables, which have not been created yet. This causes errors such as the following, which can safely be ignored:
WARN [JDBCExceptionReporter] SQL Error: -22, SQLState: S0002 ERROR [JDBCExceptionReporter] Table not found in statement ... WARN [JDBCExceptionReporter] SQL Error: 1146, SQLState: 42S02 ERROR [JDBCExceptionReporter] Table 'jbossportal.jbp_cms_repositoryentry' doesn't exist WARN [JDBCExceptionReporter] SQL Error: 1146, SQLState: 42S02 ERROR [JDBCExceptionReporter] Table 'jbossportal.jbp_cms_version_refs' doesn't exist
The binary package typically consists of the
jboss-portal.sar/
directory, documentation such as the JBoss Portal User Guide and the JBoss Portal
Reference Guide, and a set of pre-configured Datasource descriptors that allow
JBoss Portal to communicate with an external database. This installation method
is recommended for users who already have JBoss EAP or JBoss AS installed, or
those who need to install JBoss Portal in a clustered environment.
The binary download is available from the
JBoss Portal Downloads
page. Look for the
JBoss Portal Binary
package. Once the binary ZIP file has been downloaded and extracted, the
folder hierarchy will look similar to the following:

Files contained in this download are used in later sections. Download and extract the JBoss Portal binary ZIP file before proceeding.
Before deploying JBoss Portal, make sure you have JBoss EAP or JBoss AS installed. Customers who have access to the JBoss Customer Support Portal (CSP) are advised to download and install JBoss EAP 4.3. Customers who do not have access to the JBoss CSP are advised to use JBoss AS . For JBoss AS installation instructions, please refer to the JBoss AS Installation Guide .
Only use the JBoss EAP and JBoss AS ZIP file versions. DO NOT ATTEMPT to deploy JBoss Portal on the installer version of JBoss EAP or JBoss AS.
For JBoss EAP, JBoss AS, and build targets to work, you must configure a
JBOSS_HOME
environment variable. This environment variable must point to the root
directory of the JBoss EAP or JBoss AS installation directory, which is the
directory where the JBoss EAP or JBoss AS files were extracted to.
On Windows, this is accomplished by going to
Start > Settings > Control Panel > System > Advanced > Environment
Variables
. Under the
System Variables
section, click
New
. Set the
JBOSS_HOME
environment variable to the location of your JBoss EAP or JBoss AS
installation directory:

To configure the
JBOSS_HOME
environment variable on Linux:
Add the following line to the
~/.bashrc
file. Note: this must be configured while logged in as the user
who runs JBoss EAP or JBoss AS:
export JBOSS_HOME=/path/to/jboss/installation/
Run the following command to enable the
JBOSS_HOME
environment variable:
source ~/.bashrc
JBOSS_HOME
Environment Variable
If you are running JBoss EAP, configure the
JBOSS_HOME
environment variable to point to the
/path/to/jboss-eap-
directory.
version
/jboss-as/
A database is required for JBoss Portal to run. JBoss EAP and JBoss AS include an embedded Hypersonic SQL database that JBoss Portal can use; however, this is only recommended for developer use. The following databases are recommended for production use, and have had test suites run against them: MySQL® 4 and 5, Microsoft® SQL Server® , PostgreSQL 8, and Oracle® Database 9 and 10. JBoss Portal can use any database that is supported by Hibernate.
To configure a database to use with JBoss Portal:
Create a new database: this guide assumes that the new database is called jbossportal .
Grant access rights for a user to the jbossportal database: JBoss Portal needs to create tables and modify table data. Grant access rights to a desired user to the jbossportal database. Configure the same username and password in the Datasource descriptor.
Deploy an RDBMS
JDBC™
connector:
an RDBMS JDBC connector is required for JBoss Portal to
communicate with a database. Copy the connector into the
$JBOSS_HOME/server/default/lib/
directory. For example, an RDBMS JDBC connector for MySQL can be
download from
http://www.mysql.com/products/connector/j/
. For the correct RDMBS JDBC connector, please refer to the
database documentation.
The JBoss Portal binary download that was extracted in
Section 2.2.1.1, “Getting the Binary”
, contains pre-configured Datasource descriptors for the more popular
databases. Datasource descriptors are provided for the MySQL 4 and 5,
PostgreSQL, Microsoft SQL Server, and Oracle databases, and can be found in
the
setup
subdirectory where the JBoss Portal binary was extracted to:

Copy the Datasource descriptor that matches your database into the
$JBOSS_HOME/server/
directory, where
configuration
/deploy/
configuration
is either all, default, minimal or production. The production configuration
only exists on JBoss EAP, and not JBoss AS. For example, if you are using
the all configuration, copy the Datasource descriptor into the
$JBOSS_HOME/server/all/deploy/
directory.
After the Datasource descriptor has been copied into the
deploy
directory, make sure the
user-name
,
password
,
connection-url
, and
driver-class
, are correct for your chosen database. Datasource descriptor files can be
deployed to test before being used in production. The following is an
example Datasource descriptor for a PostgreSQL database:
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>
<jndi-name>PortalDS</jndi-name>
<connection-url>jdbc:postgresql:jbossportal</connection-url>
<driver-class>org.postgresql.Driver</driver-class>
<user-name>portal</user-name>
<password>portalpassword</password>
</local-tx-datasource>
</datasources>
For further details about Datasource descriptors, please refer to the JBoss JDBC Datasource Wiki page .
To start JBoss EAP or JBoss AS and deploy JBoss Portal:
Datasource descriptor:
if you have not done so already, change into the
setup
subdirectory where the JBoss Portal binary was extracted to. Copy the
correct Datasource descriptor file (
*-ds.xml
) you modified in the previous steps into the
$JBOSS_HOME/server/
directory.
configuration
/deploy/
Start the server:
change into the
$JBOSS_HOME/bin/
directory. On Windows, execute
run.bat
. On Linux, run the
sh run.sh
command. To specify a configuration to use, for example, the default
configuration, append the
-c default
option to the
run.bat
or
sh run.sh
commands.
Log in to JBoss Portal: using a Web browser, navigate to http://localhost:8080/portal to open the JBoss Portal homepage. Log in using one of the two default accounts: username user , password user , or username admin , password admin .
Tables are automatically created the first time JBoss Portal starts. When deployed for the first time, JBoss Portal checks for the existence of the initial tables, which have not been created yet. This causes errors such as the following, which can safely be ignored:
WARN [JDBCExceptionReporter] SQL Error: -22, SQLState: S0002 ERROR [JDBCExceptionReporter] Table not found in statement ... WARN [JDBCExceptionReporter] SQL Error: 1146, SQLState: 42S02 ERROR [JDBCExceptionReporter] Table 'jbossportal.jbp_cms_repositoryentry' doesn't exist WARN [JDBCExceptionReporter] SQL Error: 1146, SQLState: 42S02 ERROR [JDBCExceptionReporter] Table 'jbossportal.jbp_cms_version_refs' doesn't exist
The JBoss Portal source files can be obtained from the
JBoss Portal Downloads
page. The source files download uses a
JBoss Portal Source Code
naming convention. As well, the sources can be obtained from SVN. The latest
sources for the 2.7.
x
versions are located at
http://anonsvn.jboss.org/repos/portal/branches/JBoss_Portal_Branch_2_7
.
Several modules have been extracted from the JBoss Portal SVN repository. These modules have a different lifecycle and a different version scheme. The following is a list of modules used in JBoss Portal 2.7.0, and the locations of their source code:
JBoss Portal Common 1.2.2: http://anonsvn.jboss.org/repos/portal/modules/common/tags/JBP_COMMON_1_2_2
JBoss Portal Web 1.2.2: http://anonsvn.jboss.org/repos/portal/modules/web/tags/JBP_WEB_1_2_2
JBoss Portal Test 1.0.3: http://anonsvn.jboss.org/repos/portal/modules/test/tags/JBP_TEST_1_0_3
JBoss Portal Portlet 2.0.4: http://anonsvn.jboss.org/repos/portal/modules/portlet/tags/JBP_PORTLET_2_0_4
JBoss Portal Identity 1.0.5: http://anonsvn.jboss.org/repos/portal/modules/identity/tags/JBP_IDENTITY_1_0_5
JBoss Portal CMS 1.2.1: http://anonsvn.jboss.org/repos/portal/modules/cms/tags/JBP_CMS_1_2_1
After checking out the source from SVN, or after extracting the
JBoss Portal Source Code
ZIP file, a directory structure similar to the following will be created:

If the source files were obtained from SVN, change into the
trunk/src/
directory to see the directories from the above image. As well, there is an
empty
thirdparty
directory. This directory contains files after building the JBoss Portal
source code (refer to
Section 2.3.3, “Building and Deploying from the Sources”
). For more information about the JBoss Portal SVN repository, and accessing
different versions of the JBoss Portal codebase, refer to the
JBoss Portal SVN Repo
page on the JBoss Wiki.
Before deploying JBoss Portal, make sure you have JBoss EAP or JBoss AS installed. Customers who have access to the JBoss Customer Support Portal (CSP) are advised to download and install JBoss EAP 4.3. Customers who do not have access to the JBoss CSP are advised to use JBoss AS . For JBoss AS installation instructions, please refer to the JBoss AS Installation Guide .
Only use the JBoss EAP and JBoss AS ZIP file versions. DO NOT ATTEMPT to deploy JBoss Portal on the installer version of JBoss EAP or JBoss AS. We are currently working on aligning the Application installer with JBoss Portal.
For JBoss EAP, JBoss AS, and build targets to work, you must configure a
JBOSS_HOME
environment variable. This environment variable must point to the root
directory of the JBoss EAP or JBoss AS installation directory, which is the
directory where the JBoss EAP or JBoss AS files were extracted to.
On Windows, this is accomplished by going to
Start > Settings > Control Panel > System > Advanced > Environment
Variables
. Under the
System Variables
section, click
New
. Set the
JBOSS_HOME
environment variable to the location of your JBoss EAP or JBoss AS
installation directory:

To configure the
JBOSS_HOME
environment variable on Linux:
Add the following line to the
~/.bashrc
file. Note: this must be configured while logged in as the user
who runs JBoss EAP or JBoss AS:
export JBOSS_HOME=/path/to/jboss/installation/
Run the following command to enable the
JBOSS_HOME
environment variable:
source ~/.bashrc
JBOSS_HOME
Environment Variable
If you are running JBoss EAP, configure the
JBOSS_HOME
environment variable to point to the
/path/to/jboss-eap-
directory.
version
/jboss-as/
During the first build, third-party libraries are obtained from an online
repository, so you must be connected to the Internet, and if you are behind a
proxy server, you need to define your proxy server address and proxy server
port number. To define a proxy server, add the following line to the
$JBOSS_HOME/bin/run.conf
file:
JAVA_OPTS=-Dhttp.proxyHost=<proxy-hostname> -Dhttp.proxyPort=<proxy-port>
Replace
proxy-hostname
with the proxy server's hostname, and
proxy-port
with the correct proxy server port number.
To build and deploy JBoss Portal from the sources, change into the
JBOSS_PORTAL_SOURCE_DIRECTORY/build/
directory, where
JBOSS_PORTAL_SOURCE_DIRECTORY
is the directory where the JBoss Portal source code was downloaded to. Then,
Windows users need to run the
build.bat deploy
command, and Linux users need to run the
sh build.sh deploy
command.
At the end of the build process, the
jboss-portal.sar
file is copied into the
$JBOSS_HOME/server/default/deploy/
directory:

The previous steps install a bare version of JBoss Portal. In previous
versions, several additional modules were deployed as well, but this has
since been modularized to provide greater flexibility. To deploy
additional modules, refer to the
Portal's module list
for more information. To deploy all modules at once, change into the
build
directory. If you are running Linux, run the
sh build.sh deploy-all
command. On Windows, run the
build.bat deploy-all
command.
To build the clustered version on Linux operating systems:
Change into the
JBOSS_PORTAL_SOURCE_DIRECTORY/build/
directory, and run the following command:
sh build.sh main
Change into the
JBOSS_PORTAL_SOURCE_DIRECTORY/core/
directory, and run the following command:
sh build.sh deploy-ha
After the
sh build.sh deploy-ha
command completes, the
jboss-portal-ha.sar
file is copied into the
$JBOSS_HOME/server/all/deploy/
directory.
To build the clustered version on Windows, repeat the previous steps,
replacing
sh build.sh
with
build.bat
.
A database is required for JBoss Portal to run. JBoss EAP and JBoss AS include an embedded Hypersonic SQL database that JBoss Portal can use; however, this is only recommended for developer use. The following databases are recommended for production use, and have had test suites run against them: MySQL 4 and 5, Microsoft SQL Server, PostgreSQL 8, and Oracle Database 9 and 10. JBoss Portal can use any database that is supported by Hibernate.
To configure a database to use with JBoss Portal:
Create a new database: this guide assumes that the new database is called jbossportal .
Grant access rights for a user to the jbossportal database: JBoss Portal needs to create tables and modify table data. Grant access rights to a desired user to the jbossportal database. Configure the same username and password in the Datasource descriptor.
Deploy an RDBMS JDBC connector:
an RDBMS JDBC connector is required for JBoss Portal to communicate
with a database. Copy the connector into the
$JBOSS_HOME/server/default/lib/
directory. For example, an RDBMS JDBC connector for MySQL can be
download from
http://www.mysql.com/products/connector/j/
. For the correct RDMBS JDBC connector, please refer to the database
documentation.
The JBoss Portal binary download that was extracted in
Section 2.2.1.1, “Getting the Binary”
, contains pre-configured Datasource descriptors for the more popular
databases. Datasource descriptors are provided for the MySQL 4 and 5,
PostgreSQL, Microsoft SQL Server, and Oracle databases, and can be found in
the
setup
subdirectory where the JBoss Portal binary was extracted to:

Copy the Datasource descriptor that matches your database into the
$JBOSS_HOME/server/
directory, where
configuration
/deploy/
configuration
is either all, default, minimal, or production. For example, if you are using
the production configuration, copy the Datasource descriptor into the
$JBOSS_HOME/server/production/deploy/
directory. The production configuration only exists on JBoss EAP
installations, and not JBoss AS.
After the Datasource descriptor has been copied into the
deploy
directory, make sure the
user-name
,
password
,
connection-url
, and
driver-class
, are correct for your chosen database. Datasource descriptor files can be
deployed to test before being used in production. The following is an example
Datasource descriptor for a PostgreSQL database:
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>
<jndi-name>PortalDS</jndi-name>
<connection-url>jdbc:postgresql:jbossportal</connection-url>
<driver-class>org.postgresql.Driver</driver-class>
<user-name>portal</user-name>
<password>portalpassword</password>
</local-tx-datasource>
</datasources>
For further details about Datasource descriptors, please refer to the JBoss JDBC Datasource Wiki page .
To start JBoss EAP or JBoss AS and deploy JBoss Portal:
Datasource descriptor:
if you have not done so already, change into the
setup
subdirectory where the JBoss Portal binary was extracted to. Copy the
correct Datasource descriptor file (
*-ds.xml
) you modified in the previous steps into the
$JBOSS_HOME/server/
directory.
configuration
/deploy/
Start the server:
change into the
$JBOSS_HOME/bin/
directory. On Windows, execute
run.bat
. On Linux, run the
sh run.sh
command. To specify a configuration to use, for example, the default
configuration, append the
-c default
option to the
run.bat
or
sh run.sh
commands.
Log in to JBoss Portal: using a Web browser, navigate to http://localhost:8080/portal to open the JBoss Portal homepage. Log in using one of the two default accounts: username user , password user , or username admin , password admin .
Tables are automatically created the first time JBoss Portal starts. When deployed for the first time, JBoss Portal checks for the existence of the initial tables, which have not been created yet. This causes errors such as the following, which can safely be ignored:
WARN [JDBCExceptionReporter] SQL Error: -22, SQLState: S0002 ERROR [JDBCExceptionReporter] Table not found in statement ... WARN [JDBCExceptionReporter] SQL Error: 1146, SQLState: 42S02 ERROR [JDBCExceptionReporter] Table 'jbossportal.jbp_cms_repositoryentry' doesn't exist WARN [JDBCExceptionReporter] SQL Error: 1146, SQLState: 42S02 ERROR [JDBCExceptionReporter] Table 'jbossportal.jbp_cms_version_refs' doesn't exist
This chapter describes how to customize the default installation. This includes the JBoss EAP or JBoss AS listening port, email and proxy settings, and database dialect settings. For further configuration details, refer to Section 6.3, “JBoss Portal Descriptors” and Chapter 27, Troubleshooting and FAQ.
It is common for web services to run on port 80. By default, JBoss EAP and JBoss AS use port 8080. If you can not use port forwarding, it is recommended to change the port JBoss EAP or JBoss AS listens on. To change the default port, open the $JBOSS_HOME/server/default/deploy/jboss-web.deployer/server.xml file, and edit the Connector port value for the jboss.web service; however, this configuration only applies to Apache Tomcat:
<Service name="jboss.web">
<Connector port="8088" address="${jboss.bind.address}"
This example changes the default port to port 8088. The JBoss EAP or JBoss AS server must be restarted before the new port settings take affect.
The default SSL port is 8843. To enable HTTPS support, refer to the JBoss AS Guide. For further information, refer to the Apache Tomcat SSL configuration how-to.
Please refer to Section 15.3.1, “Considerations to use WSRP when running Portal on a non-default port or hostname” to update the WSRP service after having changed the port.
Linux operating systems require root user privileges to run a service on a port less than 1024. Starting JBoss EAP or JBoss AS on port 80 as a non-privileged user will not work. Running JBoss EAP or JBoss AS as the root user could lead to security breaches.
By default, the main JBoss Portal page is accessible by navigating to http://localhost:8080/portal/index.html. This
can be changed to a different path, for example,
http://localhost:8080/index.html. The context path can be changed when using the deployed jboss-portal.sar/, or before building from source. To change the context path when using the JBoss Portal binary package:
Open the $JBOSS_HOME/server/default/deploy/jboss-portal.sar/portal-server.war/WEB-INF/jboss-web.xml file. If this file does not exist, copy and save the following example:
<?xml version="1.0"?>
<jboss-web>
<security-domain>java:jaas/portal</security-domain>
<context-root>/portal</context-root>
<replication-config>
<replication-trigger>SET</replication-trigger>
</replication-config>
<resource-ref>
<res-ref-name>jdbc/PortalDS</res-ref-name>
<jndi-name>java:PortalDS</jndi-name>
</resource-ref>
</jboss-web>Edit the
<context-root> element with the desired context path:
<context-root>/testing</context-root>
Using this example, the main JBoss Portal page would be reached by navigating to http://localhost:8080/testing.
To change the context path when building from source:
Change into the directory where the JBoss Portal Source Code ZIP file was extracted to, or where the source from SVN was checked out to. Copy the build/etc/local.properties-example file and save it as build/local.properties.
Open the build/local.properties file and edit the portal.web.context-root option with the desired context path:
# Context root for the portal main servlet portal.web.context-root=/testing
Using this example, the main JBoss Portal page would be reached by navigating to http://localhost:8080/testing.
To clean the project, make sure you are connected to the Internet, and change into the build/ directory. Run the ant clean command.
Rebuild and redeploy JBoss Portal. Refer to Section 2.3, “Installing from the Sources” for build instructions.
By default, Apache Tomcat holds on to the root context, /. You may need to remove the $JBOSS_HOME/server/default/deploy/jboss-web.deployer/ROOT.war/ directory,
or add a jboss-web.xml file, which declares another
context-root other than /, under the $JBOSS_HOME/server/default/deploy/jboss-web.deployer/ROOT.war/WEB-INF/ directory, for the above changes to take affect. The following is an example jboss-web.xml file, which changes the Apache Tomcat context path to /tomcat-root:
<?xml version="1.0"?>
<jboss-web>
<context-root>/tomcat-root</context-root>
</jboss-web>
This sections describes how to override the Database (DB) dialect settings. Under most circumstances, the auto-detect feature works. If the Hibernate dialect is not working correctly, override the default behavior by following the instructions in this section.
All hibernate.cfg.xml files in all JBoss Portal modules you intend to use need to be modified. The hibernate.cfg.xml files are found in the jboss-portal.sar/ directory, where module/conf/hibernate/directory/module is the module name, and directory is a directory that, depending on the module, may or may not exist.
To modify these files to force the DB dialect, un-comment the following line from each hibernate.cfg.xml file in each JBoss Portal module you intend to use, so that it looks like the following:
<!-- Force the dialect instead of using autodetection -->
<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
Note: this example is for a PostgreSQL database. If you use another database, you need to modify org.hibernate.dialect.PostgreSQLDialect to reflect the correct database. For a list of supported dialects, refer to the dialects list on the Hibernate website.
To modify the DB dialect setting for the JBoss Portal CMS component:
Open the jboss-portal.sar/portal-cms.sar/conf/hibernate/cms/hibernate.cfg.xml file.
Un-comment the following line, so that it looks like the following:
<!-- Force the dialect instead of using autodetection --> <property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
Note: this example is for a PostgreSQL database. If you use another database, you need to modify org.hibernate.dialect.PostgreSQLDialect to reflect the correct database. For a list of supported dialects, refer to the dialects list on the Hibernate website.
If you have a standard setup and a mail server installed, the email service should work without any extra configuration. Most Linux distributions have a mail server installed by default. The email service, for example, can be used to verify a user's email address when a user subscribes, or for CMS workflow notifications.
The email service is configured using the $JBOSS_HOME/server/default/deploy/jboss-portal.sar/META-INF/jboss-service.xml file. The following is an example of the section which is used to configure the email service:
<mbean
code="org.jboss.portal.core.impl.mail.MailModuleImpl"
name="portal:service=Module,type=Mail"
xmbean-dd=""
xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
<xmbean/>
<depends>jboss:service=Mail</depends>
<depends>portal:service=Module,type=IdentityServiceController</depends>
<attribute name="QueueCapacity">-1</attribute>
<attribute name="Gateway">localhost</attribute>
<attribute name="SmtpUser"></attribute>
<attribute name="SmtpPassword"></attribute>
<attribute name="JavaMailDebugEnabled">false</attribute>
<attribute name="SMTPConnectionTimeout">100000</attribute>
<attribute name="SMTPTimeout">10000</attribute>
<attribute name="JNDIName">java:portal/MailModule</attribute>
</mbean>
A different SMTP server (other than localhost) can be configured, along with a SMTP username and an SMTP password. The following is an example configuration that uses the Gmail SMTP server:
<mbean
code="org.jboss.portal.core.impl.mail.MailModuleImpl"
name="portal:service=Module,type=Mail"
xmbean-dd=""
xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
<xmbean/>
<depends>jboss:service=Mail</depends>
<depends>portal:service=Module,type=IdentityServiceController</depends>
<attribute name="QueueCapacity">-1</attribute>
<attribute name="Gateway">smtp.gmail.com</attribute>
<attribute name="SmtpUser">username@gmail.com</attribute>
<attribute name="SmtpPassword">myPassword</attribute>
<attribute name="JavaMailDebugEnabled">false</attribute>
<attribute name="SMTPConnectionTimeout">100000</attribute>
<attribute name="SMTPTimeout">10000</attribute>
<attribute name="JNDIName">java:portal/MailModule</attribute>
</mbean>
Using this example, replace username@gmail.com and myPassword with your correct Gmail username and password.
There are a couple of scenarios where you need your proxy to be correctly defined at the JVM™ level so that you can access documents from Internet. It could be to get the thirdparty libraries if you decided to build JBoss Portal from the sources, to access RSS feeds or weather information in the samples portlet we provide or for your own needs.
To configure the proxy settings, you need to know the proxy host and the port to use. Then, add them when starting Java.
Usually setting up JAVA_OPTS environment variable to -Dhttp.proxyHost=YOUR_PROXY_HOST -Dhttp.proxyPort=YOUR_PROXY_PORT
is enough.
JBoss Portal uses the JBoss Microkernel for the service infrastructure. The JBoss Microkernel provides injection of services into other services, otherwise known as wiring. Due to the Microkernel being JMX™ based, it is only possible to inject dynamic proxies that talk to the MBeanServer. The overhead at runtime is minimal since the Microkernel implementation is highly optimized; however, when it is used with Java 5, a noticeable bottleneck occurs due to the fact that the implementation of the JMX API classes, javax.management.*, provided by the Java Platform, perform synchronization. This does not occur under JDK™ 1.4, since those classes are implemented by JBoss MX.
JBoss Portal services use a special kind of Model MBean called JBossServiceModelMBean, which allows the un-wrapping of injected dynamic proxies, and replaces them with Plain Old Java Object (POJO) services. This removes the bottleneck when using Java 5, and also provides a performance boost on JDK 1.4. By default this feature is enabled, but it is possible to disable. To do this on Linux operating systems, change into the $JBOSS_HOME/bin/ directory and run the following command:
sh run.sh -Dportal.kernel.no_proxies=false
On Windows, run the following command:
run.bat -Dportal.kernel.no_proxies=false
Before performing any instructions or operations in this chapter, back up your database and the entire JBoss EAP or JBoss AS directory!
JBoss Portal 2.7 compatibility with JBoss Portal 2.6 is very high. The main differences are the use of JSR-286 features to replace JBoss Portal specific features. The database schema hasn't changed.
Usage of JBossActionRequest is not available directly anymore. From now on it is only accessible if the org.jboss.portlet.filter.JBossPortletFilter is applied on the portlet. To do so, first you will need to change the portlet.xml descriptor in order to declare the new portlet as a JSR-286 portlet so that the filter can be applied. For a portlet named MyFooPortlet it would now look like this:
<portlet-app
xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
version="2.0">
<filter>
<filter-name>JBoss Portlet Filter</filter-name>
<filter-class>org.jboss.portlet.filter.JBossPortletFilter</filter-class>
<lifecycle>ACTION_PHASE</lifecycle>
<lifecycle>RENDER_PHASE</lifecycle>
</filter>
<filter-mapping>
<filter-name>JBoss Portlet Filter</filter-name>
<portlet-name>MyFooPortlet</portlet-name>
</filter-mapping>
<portlet>
<description>My foo portlet</description>
<portlet-name>MyFooPortlet</portlet-name>
...
</portlet>
</portlet-app>
By not adding this filter on a portlet using JBossActionRequest/JBossActionResponse, an error message such as: The request isn't a JBossRenderRequest, you probably need to activate the JBoss Portlet Filter: org.jboss.portlet.filter.JBossPortletFilter on MyFooPortlet
The Portlet Specifications aims at defining portlets that can be used by any JSR-168 (Portlet 1.0) or JSR-286 (Portlet 2.0) portlet container. Most Java EE portals include one, it is obviously the case for JBoss Portal which includes the JBoss Portlet container supporting the two versions. This chapter gives a brief overview of the Portlet Specifications but portlet developers are strongly encouraged to read the JSR-286 Portlet Specification .
JBoss Portal is fully JSR-286 compliant, which means any JSR-168 or JSR-286 portlet behaves as it is mandated by the respective specifications inside the portal.
A portal can be seen as pages with different areas, and inside areas, different windows, and each window having one portlet:

A portlet can have different view modes. Three modes are defined by the JSR-286 specification:
view - generates markup reflecting the current state of the portlet.
edit - allows a user to customize the behavior of the portlet.
help - provides information to the user as to how to use the portlet.
Window states are an indicator of how much page real-estate a portlet consumes on any given page. The three states defined by the JSR-168 specification are:
normal - a portlet shares this page with other portlets.
minimized -a portlet may show very little information, or none at all.
maximized - a portlet may be the only portlet displayed on this page.
The tutorials contained in this chapter are targeted toward portlet developers. Although they are a good starting and reference point, it is highly recommend that portlet developers read and understand the JSR-286 Portlet Specification . Feel free to use the JBoss Portal User Forums for user-to-user help.
This section describes how to deploy a portlet in JBoss Portal. You will
find the
SimplestHelloWorld
portlet in the
examples
directory at the root of your JBoss Portal binary package.
This example is using Maven to compile and build the web archive. If you don't have Maven already installed, you will find a version for your operating system here
To compile and package the application, go to the SimplestHelloWorld
directory and type
mvn package
.
Once successfully packaged, the result should be available in:
SimplestHelloWorld/target/SimplestHelloWorld-0.0.1.war
. Simply copy that file into
JBOSS_HOME/server/default/deploy
, then start JBoss Application Server if it was not already started.
You should now see a new page called
SimplestHelloWorld
, with a window inside containing the portlet instance we have created, as
seen below.

Like other Java Platform, Enterprise Edition (Java EE) applications, portlets are packaged in WAR files. A typical portlet WAR file can include servlets, resource bundles, images, HTML, JavaServer™ Pages ( JSP™ ), and other static or dynamic files. The following is an example of the directory structure of the HelloWorldPortlet portlet:
|-- SimplestHelloWorld-0.0.1.war | `-- WEB-INF | |-- classes | | `-- org | | `-- jboss | | `-- portal | | `-- portlet | | `-- samples | |`-- SimplestHelloWorldPortlet.class | |-- de
fault-object.xml | |-- po
rtlet-instances.xml | |-- po
rtlet.xml | `-- we
b.xml
![]() | The compiled Java class implementing javax.portlet.Portlet (through javax.portlet.GenericPortlet ) |
![]() | default-object.xml is an optional file, it is used to define the layout of the portal. It can be used to define the different portals, pages and windows. The same result can be obtained through the administration portal. Note that the definition of the layout is stored in database, this file is then used to populate the database during deployment which can be very useful during development. |
![]() | portlet-instances.xml is also optional, it allows to create a portlet instance from the SimpleHelloWorld portlet definition. Creating instances can also be done through the administration portal. Note that the definition of instances is stored in database, this file is then used to populate the database during deployment which can be very useful during development. Having portlet-instances.xml and default-object.xml included in this package ensures that the portlet will appear directly on the portal by just deploying the web application. |
![]() | This is the mandatory descriptor files for portlets. It is used during deployment.. |
![]() | This is the mandatory descriptor for web applications. |
The following file is the
SimplestHelloWorldPortlet/src/main/java/org/jboss/portal/portlet/samples/SimplestHelloWorldPortlet.java
Java source.
package org.jboss.portal.portlet.samples;
import java.io.IOException;
import java.io.PrintWriter;
import javax.portlet.GenericPortlet;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;public class SimplestHelloWorldPortlet extends GenericPortlet
{
public void doView(RenderRequest request,RenderResponse response) throws IOException
{PrintWriter writer = response.getWriter();
writer.write("Hello World !");
writer.close();
}
}
![]() |
All portlets must implement the
|
![]() |
As we extend from
|
![]() | Use the RenderResponse to obtain a writer to be used to produce content. |
![]() | Write the markup to display. |
![]() | Closing the writer. |
Portlets are responsible for generating markup fragments, as they are
included on a page and are surrounded by other portlets. In
particular, this means that a portlet outputting HTML must not output
any markup that cannot be found in a
<body>
element.
JBoss Portal requires certain descriptors to be included in a portlet WAR file. Some of these descriptors are defined by the Portlet Specification, and others are specific to JBoss Portal.
The following is an example of the
SimplestHelloWorldPortlet/WEB-INF/portlet.xml
file. This file must adhere to its definition in the JSR-286 Portlet
Specification. You may define more than one portlet application in this
file:
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd
http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
version="2.0">
<portlet>
<portlet
-name>SimplestHelloWorldPortlet</portlet-name>
<portlet
-class>
org.jboss.portal.portlet.samples.SimplestHelloWorldPortlet
</portlet-class>
<support
s>
<mime-type>text/html</mime-type>
</supports>
<portlet
-info>
<title>Simplest Hello World Portlet</title>
</portlet-info>
</portlet>
</portlet-app>
![]() | Define the portlet name. It does not have to be the class name. |
![]() | The Fully Qualified Name (FQN) of your portlet class must be declared here. |
![]() |
The
|
![]() |
When rendered, the portlet's title is displayed as the header in
the portlet window, unless it is overridden programmatically. In
this example, the title would be
|
The
SimplestHelloWorldPortlet/WEB-INF/portlet-instances.xml
file is a JBoss Portal specific descriptor, that allows you to create
instances of portlets. The
<portlet-ref>
value must match the
<portlet-name>
value given in the
SimplestHelloWorldPortlet/WEB-INF/portlet.xml
file. The
<instance-id>
value can be named anything, but it must match the
<instance-ref>
value given in the
*-object.xml
file, which in this example, would be the
SimplestHelloWorldPortlet/WEB-INF/default-object.xml
file.
The following is an example of the
SimplestHelloWorldPortlet/WEB-INF/portlet-instances.xml
file:
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE deployments PUBLIC
"-//JBoss Portal//DTD Portlet Instances 2.6//EN"
"http://www.jboss.org/portlet/dtd/portlet-instances_2_6.dtd">
<deployments>
<deployment>
<instance>
<instance-id>SimplestHelloWorldInstance</instance-id>
<portlet-ref>SimplestHelloWorldPortlet</portlet-ref>
</instance>
</deployment>
</deployments>
The
*-object.xml
file is a JBoss Portal specific descriptor that allow users to define the
structure of their portal instances, and create and configure their windows
and pages. In the following example:
a portlet window is created.
specifies that the window displays the markup generated by the
SimplestHelloWorldInstance
portlet instance.
the window is assigned to the page that we are creating and called
SimplestHelloWorld
page.
the
<region>
element specifies where the window appears on the page.
The following is an example
SimplestHelloWorldPortlet/WEB-INF/default-object.xml
file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE deployments PUBLIC
"-//JBoss Portal//DTD Portal Object 2.6//EN"
"http://www.jboss.org/portal/dtd/portal-object_2_6.dtd">
<deployments>
<deployment>
<parent-
ref>default</parent-ref>
<if-exis
ts>overwrite</if-exists>
<page>
<page-name>SimplestHelloWorld</page-name>
<window>
<w
indow-name>SimplestHelloWorldWindow</window-name>
<i
nstance-ref>SimplestHelloWorldInstance</instance-ref>
<r
egion>center</region>
<h
eight>0</height>
</window>
</page>
</deployment>
</deployments>
![]() |
Tells the portal where this portlet appears. In this case,
|
![]() |
Instructs the portal to overwrite or keep this object if it
already exists. Accepted values are
|
![]() | Here we are creating a new page to put the new window on. We give that new page a name that will be by default used on the tab of the default theme. |
![]() | A unique name given to the portlet window. This can be named anything. |
![]() |
The value of
|
![]() | Specifies where the window appears within the page layout. |
![]() | Specifies where the window appears within the page layout. |
The following diagram illustrates the relationship between the
portlet.xml
,
portlet-instances.xml
, and
default-object.xml
descriptors:

JBoss Portal 2.6 introduced the notion of
content-type
, which is a generic mechanism to specify what content displayed by a given
portlet window. The
window
section of the previous example,
SimplestHelloWorldPortlet/WEB-INF/default-object.xml
, can be re-written to take advantage of the new content framework. The
following is an example deployment descriptor that uses the new content
framework:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE deployments PUBLIC
"-//JBoss Portal//DTD Portal Object 2.6//EN"
"http://www.jboss.org/portal/dtd/portal-object_2_6.dtd">
<deployments>
<deployment>
<parent-ref>default.default</parent-ref>
<if-exists>overwrite</if-exists>
<window>
<window-name>SimplestHelloWorldWindow</window-name>
<content>
<content-type>portlet</content-type>
<content-uri>SimplestHelloWorldInstance</content-uri>
</content>
<region>center</region>
<height>1</height>
</window>
</deployment>
</deployments>
This declaration is equivalent to the previous
SimplestHelloWorldPortlet/WEB-INF/default-object.xml
example. Use
<content-type>
to specify the content to display. In this example, the content being
displayed by the
SimplestHelloWorldWindow
is a
portlet
. The
<content-uri>
element specifies which content to display, which in this example, is the
SimplestHelloWorldInstance
:
<content>
<content-type>portlet</content-type>
<content-uri>SimplestHelloWorldInstance</content-uri>
</content>
To display certain content or a file, use the
cms
content-type, with the
<content-uri>
element being the path to the file in the CMS. This behavior is pluggable:
you can plug in almost any type of content.
If the context-path change the portal may not be able to find a
reference on your portlets anymore. For that reason it's recommended to
add the following descriptor
WEB-INF/jboss-portlet.xml
which is not mandatory:
<!DOCTYPE portlet-app PUBLIC
"-//JBoss Portal//DTD JBoss Portlet 2.6//EN"
"http://www.jboss.org/portal/dtd/jboss-portlet_2_6.dtd">
<portlet-app>
<app-id>SimplestHelloWorld</app-id>
</portlet-app>
Now we will add more features to the previous example and also use a JSP
page to render the markup. We will use the portlet tag library to generate
links to our portlet in different ways and use the other standard portlet
modes. This example can be found in the directory
JSPHelloUser.
Use mvn package then copy JSPHelloUser/target/JSPHelloUser-0.0.1.war
in the deploy directory of JBoss Application Server.
Point your brwoser to , you should see the following:

The EDIT button only appears with logged-in users, which is not the case
on the screenshot
The structure doesn't change much at the exception of adding some JSP files detailed later.
The JSPHelloUser portlet contains the traditional portlet and JBoss Portal specific application descriptors. The following is an example of the directory structure of the JSPHelloUser portlet:
JSPHelloUser-0.0.1.war
|-- META-INF
| |-- MANIFEST.MF
| `-- maven
| `-- org.jboss.portal.example
| `-- JSPHelloUser
| |-- pom.properties
| `-- pom.xml
|-- WEB-INF
| |-- classes
| | `-- org
| | `-- jboss
| | `-- portal
| | `-- portlet
| | `-- samples
| | `-- JSPHelloUserPortlet.class
| |-- default-object.xml
| |-- jboss-portlet.xml
| |-- portlet-instances.xml
| |-- portlet.xml
| `-- web.xml
`-- jsp
|-- edit.jsp
|-- hello.jsp
|-- help.jsp
`-- welcome.jsp
The following file is the
JSPHelloUser/src/main/java/org/jboss/portal/portlet/samples/JSPHelloUserPortlet.java
Java source. It is split in different pieces.
package org.jboss.portal.portlet.samples;
package org.jboss.portal.portlet.samples;
import java.io.IOException;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.UnavailableException;
public class JSPHelloUserPortlet extends GenericPortlet
{
public void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException
{String sYourName = (String) request.getParameter("yourname");
if (sYourName != null)
{
request.setAttribute("yourname", sYourName);PortletRequestDispatcher prd =
getPortletContext().getRequestDispatcher("/jsp/hello.jsp");
prd.include(request, response);
}
else
{
PortletRequestDispatcher prd = getPortletContext().getRequestDispatcher("/jsp/welcome.jsp");
prd.include(request, response);
}
}
...
![]() | As in the first portlet, we override the doView method. |
![]() |
Here we try to obtain the value of the render parameter names
|
![]() | Very similar to the Servlet way, we get a request dispatcher on a file located within the web archive. |
![]() | The last step is to perform the inclusion of the markup obtained from the JSP. |
We have seen the
VIEW
portlet mode, the spec defines two other modes that can be used called
EDIT
and
HELP
. In order to enable those modes, they will need to be defined in the
portlet.xml
descriptor as we will see later. Having those modes defined will enable the
corresponding buttons on the portlet's window.
The generic portlet that is inherited dispatches the different views to
methods named:
doView
,
doHelp
and
doEdit
. Let's watch the code for those two last portlet modes.
...
protected void doHelp(RenderRequest rRequest, RenderResponse rResponse) throws PortletException, IOException,
UnavailableException
{
rResponse.setContentType("text/html");
PortletRequestDispatcher prd = getPortletContext().getRequestDispatcher("/jsp/help.jsp");
prd.include(rRequest, rResponse);
}
protected void doEdit(RenderRequest rRequest, RenderResponse rResponse) throws PortletException, IOException,
UnavailableException
{
rResponse.setContentType("text/html");
PortletRequestDispatcher prd = getPortletContext().getRequestDispatcher("/jsp/edit.jsp");
prd.include(rRequest, rResponse);
}
...
If you have read the portlet specification carefully you should have notice that portlet calls happen in one or two phases. One when the portlet is just rendered, two when the portlet is actionned then rendered. An action phase is a phase where some state change. The render phase will have access to render parameters that will be passed each time the portlet is refreshed (with the exception of caching capabilities).
The code to be executed during an action has to be implemented in the processAction method of the portlet.
...public void processAction(ActionRequest aRequest, ActionResponse aResponse) throws PortletException, IOException,
UnavailableException
{String sYourname = (String) aRequest.getParameter("yourname");
aResponse.setRenderParameter("yourname", sYourname);
}
...
![]() |
|
![]() | Here we retrieve the parameter obtained through an action URL . |
![]() |
Here we need to keep the value of
|
The
help.jsp
and
edit.jsp
files are very simple, they simply display some text. Note that we used CSS
styles as defined in the portlet specification. It ensures that the portlet
will look "good" within the theme and accross portal vendors.
<div class="portlet-section-header">Help mode</div>
<div class="portlet-section-body">This is the help mode, a convenient place to give the user some help information.</div>
<div class="portlet-section-header">Edit mode</div>
<div class="portlet-section-body">This is the edit mode, a convenient place to let the user change his portlet preferences.</div>
Now let's have a look at the landing page, it contains the links and form to call our portlet:
<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %> <div class="portlet-section-header">Welcome !</div> <br/> <div class="portlet-font">Welcome on the JSP Hello User portlet, my name is JBoss Portal. What's yours ?</div> <br/> <div class="portlet-font">Method 1: We simply pass the parameter to the render phase:<br/> <a href="<port
let:renderURL><portlet:param name="yourname" value="John Doe"/> </portlet:renderURL>">John Doe</a></div> <br/> <div class="portlet-font">Method 2: We pass the parameter to the render phase, using valid XML: Please check the source code to see the difference with Method 1. <portlet:rende
rURL var="myRenderURL"> <portlet:param name="yourname" value='John Doe'/> </portlet:renderURL> <br/> <a href="<%= m
yRenderURL %>">John Doe</a></div> <br/> <div class="portlet-font">Method 3: We use a form:<br/> <portlet:actio
nURL var="myActionURL"/> <form action="
<%= myActionURL %>" method="POST"> <span class="portlet-form-field-label">Name:</span> <input class="portlet-form-input-field" type="text" name="yourname"/> <input class="portlet-form-button" type="Submit"/> </form> </div>
![]() | Since we will use the portlet taglib, we first need to declare it. |
![]() |
The first method showed here is the simplest one,
|
![]() |
In this method instead of having a tag within another tag, which
is not XML valid, we use the
|
![]() |
The variable
|
![]() | The third method mixes form submission and action request. Like in the second method, we used a temporary variable to put the created URL into. |
![]() | The action URL is used in the HTML form. |
On the third method, first the action phase is triggered then later in the request, the render phase is triggered, which output some content back to the web browser based on the available render parameters.

Such an example is available in examples/JSFHelloUser, it uses the JBoss Portlet Bridge. The configuration is slightly different from a JSP application, since it is a bit tricky it is usally a good idea to copy an existing application that starting from scratch.
First, as any JSF application, the file faces-config.xml is required. It includes
the following required information in it:
<!-- XML : generated by JHighlight v1.0 (http://jhighlight.dev.java.net) --> <span class="xml_tag_symbols"><</span><span class="xml_tag_name">faces-config</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain">...</span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">application</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">view-handler</span><span class="xml_tag_symbols">></span><span class="xml_plain">org.jboss.portletbridge.application.PortletViewHandler</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">view-handler</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">state-manager</span><span class="xml_tag_symbols">></span><span class="xml_plain">org.jboss.portletbridge.application.PortletStateManager</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">state-manager</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">application</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain">...</span><br /> <span class="xml_tag_symbols"></</span><span class="xml_tag_name">faces-config</span><span class="xml_tag_symbols">></span><span class="xml_plain"> </span><br />
The portlet bridge libraries must be available and are usually bundled with the WEB-INF/lib
directory of the web archive.
The other difference compare to a regular portlet application, can be found in the portlet descriptor. All details about it can be found in the JSR-301 specification that the JBoss Portlet Bridge implements.
<!-- XML : generated by JHighlight v1.0 (http://jhighlight.dev.java.net) --> <span class="xml_processing_instruction"><?xml version="1.0" encoding="UTF-8"?></span><span class="xml_plain"></span><br /> <span class="xml_tag_symbols"><</span><span class="xml_tag_name">portlet-app</span><span class="xml_plain"> </span><span class="xml_attribute_name">xmlns</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">"http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"</span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_attribute_name">xmlns:xsi</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">"http://www.w3.org/2001/XMLSchema-instance"</span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_attribute_name">xsi:schemaLocation</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">"http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd </span><br /> <span class="xml_attribute_value"> http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"</span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_attribute_name">version</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">"2.0"</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">portlet</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">portlet-name</span><span class="xml_tag_symbols">></span><span class="xml_plain">JSFHelloUserPortlet</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">portlet-name</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">portlet-class</span><span class="xml_tag_symbols">></span><span class="xml_plain">javax.portlet.faces.GenericFacesPortlet</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">portlet-class</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">supports</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">mime-type</span><span class="xml_tag_symbols">></span><span class="xml_plain">text/html</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">mime-type</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">portlet-mode</span><span class="xml_tag_symbols">></span><span class="xml_plain">view</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">portlet-mode</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">portlet-mode</span><span class="xml_tag_symbols">></span><span class="xml_plain">edit</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">portlet-mode</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">portlet-mode</span><span class="xml_tag_symbols">></span><span class="xml_plain">help</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">portlet-mode</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">supports</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">portlet-info</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">title</span><span class="xml_tag_symbols">></span><span class="xml_plain">JSF Hello User Portlet</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">title</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">portlet-info</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><br /> <span class="x
ml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">init-param</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">name</span><span class="xml_tag_symbols">></span><span class="xml_plain">javax.portlet.faces.defaultViewId.view</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">name</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">value</span><span class="xml_tag_symbols">></span><span class="xml_plain">/jsf/welcome.jsp</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">value</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">init-param</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"></span><br /> <span class="x
ml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">init-param</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">name</span><span class="xml_tag_symbols">></span><span class="xml_plain">javax.portlet.faces.defaultViewId.edit</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">name</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">value</span><span class="xml_tag_symbols">></span><span class="xml_plain">/jsf/edit.jsp</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">value</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">init-param</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"></span><br /> <span class="x
ml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">init-param</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">name</span><span class="xml_tag_symbols">></span><span class="xml_plain">javax.portlet.faces.defaultViewId.help</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">name</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">value</span><span class="xml_tag_symbols">></span><span class="xml_plain">/jsf/help.jsp</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">value</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">init-param</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">portlet</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_tag_symbols"></</span><span class="xml_tag_name">portlet-app</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br />
![]() | All JSF portlets define |
![]() | This is a mandatory parameter to define what's the default page to display. |
![]() | This parameter defines which page to display on the 'edit' mode. |
![]() | This parameter defines which page to display on the 'help' mode. |
To use a DTD, add the following declaration to the start of the desired descriptors:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE deployments PUBLIC
"-//JBoss Portal//DTD Portal Object 2.6//EN"
"http://www.jboss.org/portal/dtd/portal-object_2_6.dtd">
If you do not use the DTD declaration, the previous mechanism for XML validation is used. The DTD is more strict, specifically with the order of XML elements. The following is an example from a *-object.xml descriptor, which is valid if you are not using the DTD, but is rejected if you are:
<if-exists>overwrite</if-exists>
<parent-ref>default.default</parent-ref>
The correct element order, and one which is valid against the DTD, is as follows:
<parent-ref>default.default</parent-ref>
<if-exists>overwrite</if-exists>
The following DTDs are available:
for -object.xml descriptors: "-//JBoss Portal//DTD Portal Object 2.6//EN"
for jboss-app.xml descriptors: "-//JBoss Portal//DTD JBoss Web Application 2.6//EN"
for jboss-portlet.xml descriptors: "-//JBoss Portal//DTD JBoss Portlet 2.6//EN"
for portlet-instances.xml descriptors: "-//JBoss Portal//DTD Portlet Instances 2.6//EN"
The DTDs are located in the $JBOSS_HOME/server/ directory.
configuration/deploy/jboss-portal.sar/dtd/
The following items refer to elements found in the JBoss Portlet DTD, $JBOSS_HOME/server/:
configuration/deploy/jboss-portal.sar/dtd/jboss-portlet_version_number.dtd
<!ELEMENT portlet-app (remotable?,portlet*,service*)>
Use the <remotable> element to configure the default behavior of portlets with respect to WSRP exposure: if no value is given, the value is either the value globally defined at the portlet application level, or false. Accepted values are true and false.
You can configure specific settings of the portlet container for each portlet defined in the WEB-INF/portlet.xml file. Use the <service> element to inject services into the portlet context of applications.
<!ELEMENT portlet (portlet-name,remotable?,ajax?,session-config?,transaction?, header-content?,portlet-info?)>
Additional configuration of the portlet. The <portlet-name> element defines the portlet name. It must match a portlet defined in the WEB-INF/portlet.xml file for that application.
Use the <remotable> element to configure the default behavior of portlets with respect to WSRP exposure: if no value is given, the value is either the value globally defined at the portlet application level, or false.
The <trans-attribute> element specifies the behavior of the portlet when it is invoked at runtime with respect to the transactional context. Depending on how the portlet is
invoked, a transaction may or may not exist before the portlet is invoked. The portal transaction is usually present in the local context. The default value is NotSupported, which means that the portal transaction is suspended for the duration of the portlet's invocation. Accepted values are Required, Mandatory, Never, Supports, NotSupported, and RequiresNew.
The following is an example section from a WEB-INF/portlet.xml file, which uses the <portlet-name>, <remotable>, and <trans-attribute> elements:
<portlet>
<portlet-name>MyPortlet</portlet-name>
<remotable>true</remotable>
<trans-attribute>Required</trans-attribute>
</portlet>
<!ELEMENT portlet-name (#PCDATA)>
The portlet name.
<!ELEMENT remotable (#PCDATA)>
Accepted values are true and false.
<!ELEMENT ajax (partial-refresh)>
Use the ajax element to configure the Asynchronous JavaScript and XML (AJAX) capabilities of the portlet.
<!ELEMENT partial-refresh (#PCDATA)>
If a portlet uses the true value for the <partial-refresh> element, the portal uses partial-page refreshing and only renders that portlet. If the <partial-refresh> element uses a false value, the portal uses a full-page refresh when the portlet is refreshed.
<!ELEMENT session-config (distributed)>
The <session-config> element configures the portlet session for the portlet. The <distributed> element instructs the container to distribute the session attributes using portal session replication. This only applies to local portlets, not remote portlets.
The following is an example of the <session-config> and <distributed> elements:
<session-config>
<distributed>true</distributed>
</session-config>
<!ELEMENT distributed (#PCDATA)>
Accepted values are true and false. The default value is false.
<!ELEMENT transaction (trans-attribute)>
The <transaction> element defines how the portlet behaves with regards to the transactional context. The <trans-attribute> element specifies the behavior of the portlet when it is invoked at runtime, with respect to the transactional context. Depending on how the portlet is invoked, a transaction may or may not exist before the portlet is invoked. The portal transaction is usually present in the local context.
The following is an example of the <transaction> and <trans-attribute> elements:
<transaction>
<trans-attribute>Required</transaction>
<transaction>
<!ELEMENT trans-attribute (#PCDATA)>
The default value is NotSupported, which means that the portal transaction is suspended for the duration of the portlet's invocation. Accepted values are Required, Mandatory, Never, Supports, NotSupported, and RequiresNew.
<!ELEMENT header-content (link|script|meta)*>
Specify the content to be included in the portal aggregated page when the portlet is present on that page. This setting only applies when the portlet is used in the local mode.
<!ELEMENT link EMPTY>
No content is allowed inside a link element.
<!ELEMENT script (#PCDATA)>
Use the <script> element for inline script definitions.
<!ELEMENT meta EMPTY>
No content is allowed for the <meta> element.
<!ELEMENT service (service-name,service-class,service-ref)>
Declare a service that will be injected by the portlet container as an attribute of the portlet context.
The following is an example of the <service> element:
<service>
<service-name>UserModule</service-name>
<service-class>org.jboss.portal.identity.UserModule</service-class>
<service-ref>:service=Module,type=User</service-ref>
</service>
To use an injected service in a portlet, perform a lookup of the <service-name>, for example, using the init() lifecycle method:
public void init()
{
UserModule userModule = (UserModule)getPortletContext().getAttribute("UserModule");
}
<!ELEMENT service-name (#PCDATA)>
The <service-name> element defines the name that binds the service as a portlet context attribute.
<!ELEMENT service-class (#PCDATA)>
The <service-class> element defines the fully qualified name of the interface that the service implements.
<!ELEMENT service-ref (#PCDATA)>
The <service-ref> element defines the reference to the service. In the JMX Microkernel environment, this consist of the JMX name of the service MBean. For an MBean reference, if the domain is left out, the current domain of the portal is used.
The following items refer to elements found in the JBoss Portlet Instance DTD, $JBOSS_HOME/server/:
configuration/deploy/jboss-portal.sar/dtd/portlet-instances_version_number.dtd
<!ELEMENT deployments (deployment*)>
The <deployments> element is a container for <deployment> elements.
<!ELEMENT deployment (if-exists?,instance)>
The <deployment> element is a container for the <instance> element.
<!ELEMENT if-exists (#PCDATA)>
The <if-exists> element defines the action to take if an instance with the same name already exists. Accepted values are overwrite and keep. The overwrite option destroys the existing object, and creates a new one based on the content of the deployment. The keep option maintains the existing object deployment, or creates a new one if it does not exist.
<!ELEMENT instance (instance-id,portlet-ref,display-name*,preferences?, security-constraint?, (display-name* | (resource-bundle, supported-locale+)))>
The <instance> element is used in the WEB-INF/portlet-instances.xml file, which creates instances of portlets. The portlet will only be created and configured if the portlet is present, and if an instance with the same name does not already exist.
The following is an example of the <instance> element, which also contains the <security-constraint> element. Descriptions of each element follow afterwards:
<instance>
<instance-id>MyPortletInstance</instance-id>
<portlet-ref>MyPortlet</portlet-ref>
<preferences>
<preference>
<name>abc</name>
<value>def</value>
</preference>
</preferences>
<security-constraint>
<policy-permission>
<role-name>User</role-name>
<action-name>view</action-name>
</policy-permission>
</security-constraint>
</instance>
<!ELEMENT instance-id (#PCDATA)>
The instance identifier. The <instance-id> value can be named anything, but it must match the <instance-ref>value given in the *-object.xml file.
<!ELEMENT portlet-ref (#PCDATA)>
The <portlet-ref> element defines the portlet that an instance represents. The <portlet-ref> value must match the <portlet-name> given in the WEB-INF/portlet.xml file.
<!ELEMENT preferences (preference+)>
The <preferences> element configures an instance with a set of preferences.
<!ELEMENT preference (name,value)>
The <preference> element configures one preference, which is part of a set of preferences. Use the <preferences> element to define a set of preferences.
<!ELEMENT name (#PCDATA)>
A name.
<!ELEMENT value (#PCDATA)>
A string value.
<!ELEMENT security-constraint (policy-permission*)>
The <security-constraint> element is a container for <policy-permission> elements. The following is an example of the <security-constraint> and <policy-permission> elements:
<security-constraint>
<policy-permission>
<role-name>User</role-name>
<action-name>view</action-name>
</policy-permission>
</security-constraint>
<security-constraint>
<policy-permission>
<unchecked/>
<action-name>view</action-name>
</policy-permission>
</security-constraint>
<!ELEMENT policy-permission (action-name*,unchecked?,role-name*)>
The <policy-permission> element secures a specific portlet instance based on a user's role.
<!ELEMENT action-name (#PCDATA)>
The <action-name> element defines the access rights given to the role defined. Accepted values are:
view: users can view the page.
viewrecursive: users can view the page and child pages.
personalize: users are able personalize the page's theme.
personalizerecursive: users are able personalize the page and child pages themes.
<!ELEMENT unchecked EMPTY>
If present, the <unchecked> element defines anyone can view the instance.
<!ELEMENT role-name (#PCDATA)>
The <role-name> element defines a role that the security constraint will apply to. The following example only allows users that are part of the EXAMPLEROLE role to access the instance:
<role-name>EXAMPLEROLE</role-name>
The following items refer to elements found in the JBoss Portal Object DTD, $JBOSS_HOME/server/:
configuration/deploy/jboss-portal.sar/dtd/portal-object_version_number.dtd
<!ELEMENT deployments (deployment*)>
The <deployments> element is a container for <deployment> elements.
<!ELEMENT deployment (parent-ref?,if-exists?,(context|portal|page|window))>
The <deployment> element is a generic container for portal object elements. The <parent-ref> child element gives the name of the parent object that the current object will use as parent. The optional <if-exists> element defines the action to take if an instance with the same name already exists. The default behavior of the <if-exists> element is to keep the existing object, and not to create a new object.
The following is an example of the <deployment> and <parent-ref> elements:
<deployment>
<parent-ref>default</parent-ref>
<page>
...
</page>
</deployment>
All portal objects have a common configuration which can include:
a listener: specifies the ID of a listener in the listener registry. A listener object is able to listen to portal events, which apply to the portal node hierarchy.
properties: a set of generic properties owned by the portal object. Certain properties drive the behavior of the portal object.
security-constraint: defines the security configuration for the portal object.
<!ELEMENT parent-ref (#PCDATA)>
The <parent-ref> element contains a reference to the parent object. The naming convention for naming objects is to concatenate the names of the path to the object, and separate the names using a period. If the path is empty, the empty string must be used. The <parent-ref> element tells the portal where the portlet appears. The syntax for the <parent-ref> element is .
portal-instance.portal-page
The following is an example of the root having an empty path:
<parent-ref />
The following specifies that the portlet appears in the portal instance named default:
<parent-ref>default</parent-ref>
The following specifies that the portlet appear in the portal instance named default, and on the page named default:
<parent-ref>default.default</parent-ref>
<!ELEMENT if-exists (#PCDATA)>
The <if-exists> element defines the action to take if an instance with the same name already exists. Accepted values are overwrite and keep. The overwrite option destroys the existing object, and creates a new one based on the content of the deployment. The keep option matains the existing object deployment, or creates a new one if it does not exist.
<!ELEMENT context (context-name,properties?,listener?,security-constraint?,portal*, (display-name* | (resource-bundle, supported-locale+)))>
The context type of the portal object. A context type represent a node in a tree, which does not have a visual representation, and only exists under the root. A context can only have children that use the portal type.
<!ELEMENT context-name (#PCDATA)>
The context name.
<!ELEMENT portal (portal-name,supported-modes,supported-window-states?,properties?,listener?, security-constraint?,page*, (display-name* | (resource-bundle, supported-locale+)))>
A portal object that uses the portal type. A portal type represents a virtual portal, and can only have children that use the page type. In addition to the common portal object elements, it also allows you to declare modes and window states that are supported.
<!ELEMENT portal-name (#PCDATA)>
The portal name.
<!ELEMENT supported-modes (mode*)>
The <supported-modes> elements defines the supported modes of the portal. Accepted values are view, edit, and help.
The following is an example of the <supported-mode> and <mode> elements:
<supported-mode>
<mode>view</mode>
<mode>edit</mode>
<mode>help</mode>
</supported-mode>
<!ELEMENT mode (#PCDATA)>
The portlet mode value. If there are no declarations of modes or window states, the default values are view, edit, help, and normal, minimized, maximized, respectively.
<!ELEMENT supported-window-states (window-state*)>
Use the <supported-window-states> element to define the supported window states of the portal. The following is an example of the <supported-window-states> and <window-state> elements:
<supported-window-states>
<window-state>normal</window-state>
<window-state>minimized</window-state>
<window-state>maximized</window-state>
</supported-window-states>
<!ELEMENT window-state (#PCDATA)>
Use the <window-state> element to define a window states. Accepted values are normal, minimized, and maximized.
<!ELEMENT page (page-name,properties?,listener?,security-constraint?,(page | window)*, (display-name* | (resource-bundle, supported-locale+)))>
A portal object that uses the page type. A page type represents a page, and can only have children that use the page and window types. The children windows are the windows of the page, and the children pages are the subpages of the page.
<!ELEMENT page-name (#PCDATA)>
The page name.
<!ELEMENT window (window-name,(instance-ref|content),region,height,initial-window-state?, initial-mode?,properties?,listener?, (display-name* | (resource-bundle, supported-locale+)))>
A portal object that uses the window type. A window type represents a window. Besides the common properties, a window has content, and belongs to a region on the page.
The <instance-ref> and <content> elements, configured in the WEB-INF/*-object.xml files, define the content of a window. The <content> element is generic, and describes any kind of content. The <instance-ref> element is a shortcut to define the content-type of the portlet, which points to a portlet instance. The value of <instance-ref> must match the value of one of the <instance-id> elements in the WEB-INF/portlet-instances.xml file.
<!ELEMENT window-name (#PCDATA)>
The window name value.
<!ELEMENT instance-ref (#PCDATA)>
Define the content of the window as a reference to a portlet instance. This value is the ID of a portlet instance, and must much the value of one of the <instance-id> elements in the WEB-INF/portlet-instances.xml file. The following is an example of the <instance-ref> element:
<instance-ref>MyPortletInstance</instance-ref>
<!ELEMENT region (#PCDATA)>
The region the window belongs to. The <region> element specifies where the window appears on the page.
<!ELEMENT height (#PCDATA)>
The height of the window in a particular region.
<!ELEMENT listener (#PCDATA)>
Define a listener for a portal object. This value is the ID of the listener.
<!ELEMENT content (content-type,content-uri)>
Define the content of a window in a generic manner. The content is defined by the type of content, and a URI, which acts as an identifier for the content. The following is an example of the <content> element, which is configured in the WEB-INF/*-object.xml files:
<content>
<content-type>portlet</content-type>
<content-uri>MyPortletInstance</content-uri>
</content>
<content>
<content-type>cms</content-type>
<content-uri>/default/index.html</content-uri>
</content>
<!ELEMENT content-type (#PCDATA)>
The content type of the window. The <content-type> element specifies the content to display, for example, a portlet.
<!ELEMENT content-uri (#PCDATA)>
The content URI of the window. The <content-uri> element specifies which content to display, for example, a portlet instance. To display a file from the CMS, use the <content-uri> element to define the full path to that file in the CMS.
<!ELEMENT properties (property*)>
A set of generic properties for the portal object. The <properties> elements contain definitions specific to a portal object.
<!ELEMENT property (name,value)>
A generic string property. The following table lists accepted values. This table is not exhaustive:
Table 6.1. Properties
<!ELEMENT name (#PCDATA)>
A name value.
<!ELEMENT value (#PCDATA)>
A value.
<!ELEMENT security-constraint (policy-permission*)>
The <security-constraint> element is a container for <policy-permission> elements. The following is an example of the <security-constraint> and <policy-permission> elements:
<security-constraint>
<policy-permission>
<role-name>User</role-name>
<action-name>view</action-name>
</policy-permission>
</security-constraint>
<security-constraint>
<policy-permission>
<unchecked/>
<action-name>view</action-name>
</policy-permission>
</security-constraint>
<!ELEMENT policy-permission (action-name*,unchecked?,role-name*)>
The <policy-permission> element is secures a specific portlet instance based on a user's role.
<!ELEMENT action-name (#PCDATA)>
The <action-name> element defines the access rights given to the role defined. Accepted values are:
view: users can view the page.
viewrecursive: users can view the page and child pages.
personalize: users are able personalize the page's theme.
personalizerecursive: users are able personalize the page and child pages themes.
<!ELEMENT unchecked EMPTY>
If present, the <unchecked> element defines that anyone can view the instance.
<!ELEMENT role-name (#PCDATA)>
The <role-name> element defines a role that the security constraint applies to. The following example only allows users that are part of the EXAMPLEROLE role to access the instance:
<role-name>EXAMPLEROLE</role-name>
The following items refer to elements found in the JBoss Portal App DTD, $JBOSS_HOME/server/:
configuration/jboss-portal.sar/dtd/jboss-app_version_number.dtd
<Element <
*-object.xml descriptors required?Technically, they are not. The portal object hierarchy, such as creating portals, pages, instances, and organizing them on the page, can be defined using the management portlet, which is accessible to JBoss Portal administrators.
The portlet-instances.xml descriptor is JBoss Portal specific, and allows developers to instantiate one-or-many instances of one-or-many portlets. The benefit of this allows one portlet to be instantiated several times, with different preference parameters. The following example instantiates two separate instances of the NewsPortlet, both using different parameters. One instance draws feeds from Red Hat announcements, and the other from McDonalds announcements:
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE deployments PUBLIC
"-//JBoss Portal//DTD Portlet Instances 2.6//EN"
"http://www.jboss.org/portal/dtd/portlet-instances_2_6.dtd">
<deployments>
<deployment>
<instance>
<instance-id>NewsPortletInstance1</instance-id>
<portlet-ref>NewsPortlet</portlet-ref>
<preferences>
<preference>
<name>expires</name>
<value>180</value>
</preference>
<preference>
<name>RssXml</name>
<value>http://finance.yahoo.com/rss/headline?s=rhat</value>
</preference>
</preferences>
<security-constraint>
<policy-permission>
<action-name>view</action-name>
<unchecked/>
</policy-permission>
</security-constraint>
</instance>
</deployment>
<deployment>
<instance>
<instance-id>NewsPortletInstance2</instance-id>
<portlet-ref>NewsPortlet</portlet-ref>
<preferences>
<preference>
<name>expires</name>
<value>180</value>
</preference>
<preference>
<name>RssXml</name>
<value>http://finance.yahoo.com/rss/headline?s=mcd</value>
</preference>
</preferences>
<security-constraint>
<policy-permission>
<action-name>view</action-name>
<unchecked/>
</policy-permission>
</security-constraint>
</instance>
</deployment>
</deployments>
<deployments>...</deployments>
The <deployments> element encapsulates the entire document, and is a container for <deployment> elements. Multiple deployments can be specified within the <deployments> element.
<deployment> <instance>...</instance> </deployment>
The <deployment> element, and the embedded <instance> element, specify a portlet instance. The <deployment> element specifies object deployments, such as portals, pages, windows, and so on. The <instance> element creates instances of portlets. The portlet will only be created and configured if the portlet is present, and if an instance with the same name does not already exist.
<instance-id>...</instance-id>
The <instance-id> elements defines a unique name given to an instance of a portlet. The <instance-id> value can be named anything, but it must match the value of one of the <instance-ref> elements in the WEB-INF/*-object.xml file.
<portlet-ref>...</portlet-ref>
The <portlet-ref> element defines the portlet that an instance represents. The <portlet-ref> value must match the <portlet-name> given in the WEB-INF/portlet.xml file.
<preferences> <preference>...</preference> </preferences>
The <preference> element configures a preference as a key-value pair. This value can be composed of a single string value, for example, the preference fruit can have the apple value. As well, this value can be composed of multiple strings, for example, the preference fruits can have values of apple, orange, and kiwi:
<preferences>
<preference>
<name>fruits</name>
<value>apple</value>
<value>orange</value>
<value>kiwi</value>
</preference>
</preferences>
The <preference> element configures one preference, which is part of a set of preferences. Use the <preferences> element to define a set of preferences.
<security-constraint>
<policy-permission>
<action-name>viewrecursive</action-name>
<unchecked/>
</policy-permission>
</security-constraint>
The <security-constraint> element is a container for <policy-permission> elements. This example demonstrates the <security-constraint> and <policy-permission> elements.
The <action-name> element defines the access rights given to the role defined. Accepted values are:
view: users can view the page.
viewrecursive: users can view the page and child pages.
personalize: users are able personalize the page's theme.
personalizerecursive: users are able personalize the page and child pages themes.
You must define a role that the security constraint will apply to:
unchecked: anyone can view the page.
<role-name>EXAMPLEROLE</role-name>: only allow users that are part of the EXAMPLEROLE role to access the instance.
The previous portlet-instances.xml example makes reference to items found in other descriptor files. The following diagram illustrates the relationship between the portlet.xml, portlet-instances.xml, and *-object.xml descriptors:

portlet-instances.xml descriptor required?Technically, it is not. The portal object hierarchy, such as creating portals, pages, instances, and organizing them on the page, can be defined using the management portlet, which is accessible to JBoss Portal administrators.
The jboss-portlet.xml descriptor allows you to use JBoss-specific functionality within your portlet application. This descriptor is covered by the JSR-168 Portlet Specification, and is normally packaged inside your portlet WAR file, alongside the other descriptors in these sections.
The following example injects a specific style sheet, /images/management/management.css, allowing the portlet to leverage a specific style:
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE portlet-app PUBLIC
"-//JBoss Portal//DTD JBoss Portlet 2.6//EN"
"http://www.jboss.org/portal/dtd/jboss-portlet_2_6.dtd">
<portlet-app>
<portlet>
<portlet-name>ManagementPortlet</portlet-name>
<header-content>
<link rel="stylesheet" type="text/css" href="/images/management/management.css"
media="screen"/>
</header-content>
</portlet>
</portlet-app>
Use the <header-content> and <link> elements to specify a style sheet.
The following example injects the UserModule service as an attribute to the portlet context:
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE portlet-app PUBLIC
"-//JBoss Portal//DTD JBoss Portlet 2.6//EN"
"http://www.jboss.org/portal/dtd/jboss-portlet_2_6.dtd">
<portlet-app>
<service>
<service-name>UserModule</service-name>
<service-class>org.jboss.portal.identity.UserModule</service-class>
<service-ref>:service=Module,type=User</service-ref>
</service>
</portlet-app>
This allows the portlet to leverage the service, for example:
UserModule userModule = (UserModule) getPortletContext().getAttribute("UserModule");
String userId = request.getParameters().getParameter("userid");
User user = userModule.findUserById(userId);
As of JBoss Portal 2.6.3, icons can be defined for a portlet by using the <icon>, <small-icon>, and <large-icon> elements:
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE portlet-app PUBLIC
"-//JBoss Portal//DTD JBoss Portlet 2.6//EN"
"http://www.jboss.org/portal/dtd/jboss-portlet_2_6.dtd">
<portlet-app>
<portlet>
<portlet-name>ManagementPortlet</portlet-name>
<portlet-info>
<icon>
<small-icon>/images/smallIcon.png</small-icon>
<large-icon>/images/largeIcon.png</small-icon>
</icon>
</portlet-info>
</portlet>
</portlet-app>
References to icons can be absolute, for example, http://www.example.com/images/smallIcon.png, or relative to the web application context, for example, /images/smallIcon.png. Icons can be used by different parts of the portlet user interface.
For information about portlet session replication in clustered environments, refer to Section 14.5, “Portlet Session Replication”.
jboss-portlet.xml descriptor required?Technically, it is not; however, it may be required to access JBoss-specific functionality that is not covered by the Portlet specification.
The portlet.xml descriptor is the standard portlet descriptor covered by the JSR-168 Portlet Specification. Developers are strongly encouraged to read the JSR-168 Portlet Specification items covering the correct use of this descriptor, as it is only covered briefly in these sections. Normally the portlet.xml descriptor is packaged inside your portlet WAR file, alongside the other descriptors in these sections. The following example is a modified version of the JBoss Portal UserPortlet definition:
<?xml version="1.0" encoding="UTF-8"?>
<portlet-app
xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd
http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
version="1.0">
<portlet>
<description>Portlet providing user login/logout and profile management</description>
<portlet-name>UserPortlet</portlet-name>
<display-name>User Portlet</display-name>
<portlet-class>org.jboss.portal.core.portlet.user.UserPortlet</portlet-class>
<init-param>
<description>Initialize the portlet with a default page to render</description>
<name>>default-view</name>
<value>/WEB-INF/jsf/objects.xhtml</value>
</init-param>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<supported-locale>en</supported-locale>
<supported-locale>fr</supported-locale>
<supported-locale>es</supported-locale>
<resource-bundle>Resource</resource-bundle>
<portlet-info>
<title>User portlet</title>
</portlet-info>
</portlet>
</portlet-app>
<portlet-app>...</portlet-app>
The <portlet-app> element encapsulates the entire document. Multiple portlets can be specified using the <portlet-app> element.
<portlet>...</portlet>
The <portlet> element defines one portlet that is deployed within this archive.
<description>...</description>
The <description> element is a verbal description of the portlet's function.
<portlet-name>...</portlet-name>
The <portlet-name> element defines the portlet name. It does not have to be the class name.
<portlet-class>...</portlet-class>
The <portlet-class> element defines the Fully Qualified Name (FQN) of the portlet class.
<init-param> <name>...</name> <value>...</value> </init-param>
The <init-param> element specifies initialization parameters to create an initial state inside your portlet class. This is usually used in the portlet's init() method, but not necessarily. Unlike a preference, an init-parameter is data that does not change at runtime and does not go into a database. If the value is changed in the descriptor, the change takes immediate effect after re-deploying the portlet. Multiple <init-param> elements can be used.
<supports>...</supports>
The <supports> element declares all of the markup types that a portlet supports. Use the <mime-type> element to declare supported capabilities, for example, if the only outputs are text and HTML, use <mime-type>text/html</mime-type>. Use the <portlet-mode> element to define the supported portlet modes for the portlet. For example, all portlets must support the view portlet mode, which is defined using <portlet-mode>view</portlet-mode>.
<supported-locale>...</supported-locale>
The <supported-locale> elements advertise the supported locales for the portlet. Use multiple <supported-locale> elements to specify multiple locales.
<resource-bundle>...</resource-bundle>
The <resource-bundle> element specifies the resource bundle that contains the localized information for the specified locales.
<portlet-info> <title>...</title> </portlet-info>
The <title> element defines the portlet's title, which is displayed in the portlet window's title bar.
portlet.xml Example
This portlet.xml example is not a replacement for what is covered in the JSR-168 Portlet Specification.
This section describes Datasource descriptors, which are required for JBoss Portal to communicate with a database, and briefly covers the jboss-portal.sar/conf/config.xml descriptor, which can be used for configuring logging, and configuring which page a user goes to when they log in.
JBoss Portal requires a Datasource descriptor to be deployed alongside the jboss-portal.sar, in order to communicate with a database. This section explains where to obtain template Datasource descriptors, how to compile them from source, and how to configure them for your installation. For an in-depth introduction to datasources, refer to the JBoss AS documentation online on the JBoss Datasource Wiki page.
Several template Datasource descriptors are included in the binary and bundled distributions of JBoss Portal. They are commonly located in the jboss-portal- directory:
version/setup/

The jboss-portal- directory contains sample Datasource descriptors for the MySQL, Microsoft SQL Server, PostgreSQL, and Oracle databases, which can be customized for your own database:
version/setup/

To build the Datasource descriptors from source:
Obtain the JBoss Portal source code: Section 2.3, “Installing from the Sources”.
Configure the JBOSS_HOME environment variable: Section 2.3.2.2, “Operating System Environment Settings”.
Change into the JBOSS_PORTAL_SOURCE_DIRECTORY/build/ directory. To build the JBoss Portal source code on Linux, run the sh build.sh deploy command, or, if you are running Windows, run the build.bat deploy command. If this is the first build, third-party libraries are obtained from an online repository, so you must be connected to the Internet. After building, if the JBOSS_PORTAL_SOURCE_DIRECTORY/thirdparty/ directory does not exist, it is created, and populated with the files required for later steps. For further details, refer to Section 2.3.3, “Building and Deploying from the Sources”.
Change into the JBOSS_PORTAL_SOURCE_DIRECTORY/core/ directory, and run the sh build.sh datasource command, or, if you are running Windows, run the build.bat datasource command:

Note: if the JBoss Portal source was not built as per step 3, the sh build.sh datasource and build.bat datasource commands fail with an error, such as the following:
BUILD FAILED java.io.FileNotFoundException: /jboss-portal-2.6.3.GA-src/core/../thirdparty/libraries.ent (No such file or directory)
The datasource build process produces the following directory and file structure, with the Datasource descriptors in the JBOSS_PORTAL_SOURCE_DIRECTORY/core/output/resources/setup directory:

The following is an example Datasource descriptor for a PostgreSQL database:
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>
<jndi-name>PortalDS</jndi-name>
<connection-url>jdbc:postgresql:jbossportal</connection-url>
<driver-class>org.postgresql.Driver</driver-class>
<user-name>portal</user-name>
<password>portalpassword</password>
</local-tx-datasource>
</datasources>
Make sure the user-name, password, connection-url, and driver-class, are correct for your chosen database.
By default, JBoss Portal is configured to display all errors. This behavior can be configured by modifying the jboss-portal.sar/conf/config.xml file:
<!-- When a window has restrictedaccess : show or hide values are permitted --> <entry key="core.render.window_access_denied">show</entry> <!-- When a window is unavailable : show or hide values are permitted --> <entry key="core.render.window_unavailable">show</entry> <!-- When a window produces an error : show, hide or message_only values are permitted --> <entry key="core.render.window_error">message_only</entry> <!-- When a window produces an internal error : show, hide are permitted --> <entry key="core.render.window_internal_error">show</entry> <!-- When a window is not found : show or hide values are permitted --> <entry key="core.render.window_not_found">show</entry>
For these parameters, accepted values are show and hide. Depending on the setting, and the actual error, either an error message is displayed, or a full stack trace within the portlet window occurs. Additionally, the core.render.window_error property supports the message_only value. The message_only value will only display an error message, whereas the show value will, if available, display the full stack trace.
By default, when a user logs in they are forwarded to the default page of the default portal. In order to
forward a user to their Dashboard, set the core.login.namespace value to dashboard in the jboss-portal.sar/conf/config.xml file:
<!-- Namespace to use when logging-in, use "dashboard" to directly log-in the dashboard otherwise use "default" --> <entry key="core.login.namespace">dashboard</entry>
The sample application descriptor in this section creates a new page, MyPage, in a portal. To illustrate this example, download the HelloWorldPortalPage portlet. To use the HelloWorldPortalPage portlet:
Download the HelloWorldPortalPage portlet.
Unzip the HelloWorldPortalPage ZIP file.
To expand the WAR file, which gives you access to the XML descriptors, change into the HelloWorldPortalPage/ directory, and run the ant explode command.
If you did not expand the helloworldportalpage.war file, copy the helloworldportalpage.war file into the correct JBoss AS or JBoss EAP deploy/ directory. If you expanded the helloworldportalpage.war file, copy the HelloWorldPortalPage/output/lib/exploded/helloworldportalpage.war/ directory into the correct JBoss AS or JBoss EAP deploy/ directory. For example, if you are using the default JBoss AS profile, copy the WAR file or the expanded directory into the $JBOSS_HOME/server/default/deploy/ directory.
The HelloWorldPortalPage portlet is hot-deployable, so the JBoss EAP or JBoss AS server does not have to be restarted after deploying the HelloWorldPortalPage portlet. The following is an example of the HelloWorldPortalPage/WEB-INF/helloworld-object.xml descriptor:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE deployments PUBLIC
"-//JBoss Portal//DTD Portal Object 2.6//EN"
"http://www.jboss.org/portal/dtd/portal-object_2_6.dtd">
<deployments>
<deployment>
<if-exists>overwrite</if-exists>
<parent-ref>default</parent-ref>
<properties/>
<page>
<page-name>MyPage</page-name>
<window>
<window-name>HelloWorldPortletPageWindow</window-name>
<instance-ref>HelloWorldPortletPageInstance</instance-ref>
<region>center</region>
<height>0</height>
</window>
<security-constraint>
<policy-permission>
<unchecked/>
<action-name>viewrecursive</action-name>
</policy-permission>
</security-constraint>
</page>
</deployment>
</deployments>
A depoloyment is composed of a <deployments> element, which is a container for <deployment> elements. In the previous example, a page is defined, the portlet is placed as a window on a page, and an instance of the portlet is created. The Mangement portlet (bundled with JBoss Portal) can modify portal instances, page position, and so on.
The following list describes elements in a *-object.xml file:
<if-exists>
The <if-exists> element defines the action to take if an instance with the same name already exists. Accepted values are overwrite and keep. The overwrite option destroys the existing object, and creates a new one based on the content of the deployment. The keep option matains the existing object deployment, or creates a new one if it does not exist.
<parent-ref>
The <parent-ref> element contains a reference to the parent object. The naming convention for naming objects is to concatenate the names of the path to the object, and separate the names using a period. If the path is empty, the empty string must be used. The <parent-ref> element tells the portal where the portlet appears. The syntax for the <parent-ref> element is .
portal-instance.portal-page
<properties>
A set of generic properties for the portal object. The <properties> elements contains definitions specific to a page. This is commonly used to define the specific theme and layout to use. If not defined, the default portal theme and layout are used.
<page>
The start of a page definition. Among others, the <page> element is a container for the <page-name>, <window>, and <security-constraint> elements.
<page-name>
The page name.
<window>
The <window> element defines a portlet window. The <window> element requires an <instance-ref> element, which assigns a portal instance to a window.
<window-name>
The <window-name> element defines the unique name given to a portlet window. This can be named anything.
<instance-ref>
The <instance-ref> elements define the portlet instances that windows represent. This value is the ID of a portlet instance, and must match the value of one of the <instance-id> elements in the WEB-INF/portlet-instances.xml file.
<region>...</region> <height>...</height>
The <region> and <height> elements define where the window appears within the page layout. The <region> element specifies where the window appears on the page. The <region> element often depends on other regions defined in the portal layout. The <height> element can be assigned a value between one and X.
<instance>
The <instance> element creates instances of portlets. The portlet will only be created and configured if the portlet is present, and if an instance with the same name does not already exist.
<instance-name>
The <instance-name> element maps to the <instance-ref> element.
<component-ref>
The <component-ref> element takes the name of the application, followed by the name of the portlet, as defined in the WEB-INF/portlet.xml file.
The <security-constraint> element is a container for <policy-permission> elements. The following is an example of the <security-constraint> and <policy-permission> elements:
<security-constraint> <policy-permission> <role-name>User</role-name> <action-name>view</action-name> </policy-permission> </security-constraint> <security-constraint> <policy-permission> <unchecked/> <action-name>view</action-name> </policy-permission> </security-constraint>
<action-name>
The <action-name> element defines the access rights given to the role defined. Accepted values are:
view: users can view the page.
viewrecursive: users can view the page and child pages.
personalize: users are able personalize the page's theme.
personalizerecursive: users are able personalize the page and child pages themes.
<unchecked/>
If present, the <unchecked> element defines that anyone can view the instance.
<role-name>
The <role-name> element defines a role that the security constraint will apply to. The following example only allows users that are part of the EXAMPLEROLE role to access the instance:
<role-name>EXAMPLEROLE</role-name>
The sample application descriptor in this section creates a new portal instance, HelloPortal, that contains two pages. To illustrate this example, download the HelloWorldPortal portlet. To use the HelloWorldPortal portlet:
Download the HelloWorldPortal portlet.
Unzip the HelloWorldPortal ZIP file.
To expand the WAR file, which gives you access to the XML descriptors, change into the HelloWorldPortal/ directory, and run the ant explode command.
If you did not expand the helloworldportal.war file, copy the helloworldportal.war file into the correct JBoss AS or JBoss EAP deploy/ directory. If you expanded the helloworldportal.war file, copy the HelloWorldPortal/output/lib/exploded/helloworldportal.war/ directory into the correct JBoss AS or JBoss EAP deploy/ directory. For example, if you are using the default JBoss AS profile, copy the WAR file or the expanded directory into the $JBOSS_HOME/server/default/deploy/ directory.
The HelloWorldPortal portlet is hot-deployable, so the JBoss EAP or JBoss AS server does not have to be restarted after deploying the HelloWorldPortal portlet. The following is an example of the HelloWorldPortal/WEB-INF/helloworld-object.xml descriptor:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE deployments PUBLIC
"-//JBoss Portal//DTD Portal Object 2.6//EN"
"http://www.jboss.org/portal/dtd/portal-object_2_6.dtd">
<deployments>
<deployment>
<parent-ref/>
<if-exists>overwrite</if-exists>
<portal>
<portal-name>HelloPortal</portal-name>
<supported-modes>
<mode>view</mode>
<mode>edit</mode>
<mode>help</mode>
</supported-modes>
<supported-window-states>
<window-state>normal</window-state>
<window-state>minimized</window-state>
<window-state>maximized</window-state>
</supported-window-states>
<properties>
<!-- Set the layout for the default portal -->
<!-- see also portal-layouts.xml -->
<property>
<name>layout.id</name>
<value>generic</value>
</property>
<!-- Set the theme for the default portal -->
<!-- see also portal-themes.xml -->
<property>
<name>theme.id</name>
<value>renaissance</value>
</property>
<!-- set the default render set name (used by the render tag in layouts) -->
<!-- see also portal-renderSet.xml -->
<property>
<name>theme.renderSetId</name>
<value>divRenderer</value>
</property>
</properties>
<security-constraint>
<policy-permission>
<action-name>personalizerecursive</action-name>
<unchecked/>
</policy-permission>
</security-constraint>
<page>
<page-name>default</page-name>
<security-constraint>
<policy-permission>
<action-name>viewrecursive</action-name>
<unchecked/>
</policy-permission>
</security-constraint>
<window>
<window-name>MyPortletWindow</window-name>
<instance-ref>MyPortletInstance</instance-ref>
<region>center</region>
<height>0</height>
</window>
</page>
</portal>
</deployment>
<deployment>
<parent-ref>HelloPortal</parent-ref>
<if-exists>overwrite</if-exists>
<page>
<page-name>foobar</page-name>
<security-constraint>
<policy-permission>
<action-name>viewrecursive</action-name>
<unchecked/>
</policy-permission>
</security-constraint>
<window>
<window-name>MyPortletWindow</window-name>
<instance-ref>MyPortletInstance</instance-ref>
<region>center</region>
<height>0</height>
</window>
</page>
</deployment>
</deployments>
When deployed, this example registers a new portal instance, HelloPortal, that contains two pages. To view the default page in the HelloPortal instance, navigate to http://localhost:8080/portal/portal/HelloPortal, and for the second page, http://localhost:8080/portal/portal/HelloPortal/foobar.
default PageFor a portal instance to be accessible via a Web browser, you must define a default page.
Portal URLs are often very complicated; however, it is possible to setup entry points in portals that follow simple patterns.
Each portal container can contain multiple portals. Within a given portal, windows are organized into pages, with a page being a collection of windows associated to a name:

Before reading the following sections, be familiar with how to define pages and portal. Refer to Section 6.4.1, “Defining a new Portal Page” for details.
The default portal is used when no portal is specified. How selection is done:
/portal/ points to the default page of the default portal.
/portal/ points to the default page of the portal-name/portal-name portal.
Each portal can have multiple pages, with each portal having a default page. When a portal is selected, a page must be used, and all windows in that page are rendered. The page selection mechanism is as follows:
/portal/default/ renders the page-namepage-name page.
The CMSPortlet delivers content transparently, without modifying the displayed URL. It is desirable to display binary content, such as GIF, JPEG, PDF, ZIP, and so on, outside of the confines of the portal. For example, /content/default/images/jboss_logo.gif displays the jboss_logo.gif file outside of the portal.
To display content outside of the portal, the portal interprets any path beginning with /content as a request for CMS content. As long as the <mime-type> is not text/html, or text/text, and the path to the content begins with /content, the content is rendered independently, outside of the portal.
While the Portlet 2.0 specification provides for more advanced coordination between portlets than the 1.0 version of the specification, it is left up to specific implementations how portlets are wired together. This chapter will look into how the coordination features are implemented in JBoss Portal.
If you are interested in these features, we strongly encourage you to read the Portlet 2.0 (JSR-286) specification as we will assume in this chapter that you are familiar with the different coordination concepts.
Most JSR-286 specification implementations support the coordination features using what is called an implicit coordination model. This model is called implicit because the relations between the different interacting portlets are inferred based on the event or parameter names that are used to pass information between the portlets. This follows the well-known principle of convention over configuration and provides a good default behavior as it doesn't require explicit user action to wire portlets.
However, such an implicit model of how portlets are wired together fails to handle more complex cases. In particular, it is often the case that semantically related events or public parameters are named differently by different portlet providers. As it is not always possible to modify the portlets to adjust for this minor naming difference of otherwise semantically compatible portlets, JBoss Portal introduces an explicit coordination model that takes precedence over the implicit model when so required.
Consider, for example, the following case: we have 3 windows (A, B
and C) on a given page. Each window is associated to a given portlet
(Portlet A, Portlet B and Portlet C, respectively).
Portlet A can produce the Event A event, while
Portlet B and Portlet C can consume Event B and
Event C, respectively. Assuming that these events are semantically equivalent, we would
like to wire these portlets via their events such that when Portlet A emits an
Event A, it gets converted to the appropriate event and transmitted to both
Portlet B and Portlet C so that their respective windows can be
appropriately updated. This scenario, as depicted below, is impossible using implicit
wiring of events:
We look at how to bypass the default implicit model using JBoss Portal's explicit model in the rest of this chapter. It is, however, interesting to note that JBoss Portal can function with both models at the same time. More precisely, it is possible to use the implicit handling of coordination while still specifying explicit wirings, as we will see later.
As most other features of JBoss Portal, the coordination functionality can be configured either declaratively
using the now familiar *-object.xml descriptors (see Chapter 6, XML Descriptors for
a refresher on these descriptors) or, at runtime, using the administration configuration GUI. We detail, below,
both configuration options for each type of coordination entities.
Launching JBoss Portal's administration interface, you will notice a few changes. In particular, a new option
is available on page configuration screens: the ability to configure coordination using the
Coordination action:
Clicking on that link will bring you to the coordination configuration for that particular page. The interface is organized in three sections, each of which is collapsible by clicking on the section header. These sections detail the configuration for each coordination element that can be controlled by JBoss Portal:
Alias bindings
Parameter bindings
Event wirings
We will look at the specific configuration and what each of these concepts mean later. Here is how the interface looks like for a page, with both the alias and parameter bindings section collapsed:
Alias bindings are a JBoss Portal specific feature which allows users to define an
alias to a public render parameter that can be used in URLs to pass a value to all portlet windows reacting
to the aliased public parameter(s). The syntax for the URL is as follows:
{portal URL}/{page name}?{alias name}={alias value}.
It is, for example, possible to alias public render parameters paramA and
paramC to the "alias" name so that JBoss Portal's event bus can
transmit that value to interested portlets on a given page when the requested page URL contains a value
for the appropriate URL parameter:
Explicit alias bindings can be defined in any page definition of your *-object.xml
descriptors. For example, this is how the example that we detailed above would be implemented, within a
page definition:
... <coordination><bindings>
<implici
t-mode>FALSE</implicit-mode> <alias-b
inding> <id>alias</id> <qname>paramA</qname> <qname>paramC</qname> </alias-binding> </bindings> </coordination>
![]() |
Coordination configuration is done via the newly introduced |
![]() |
Alias bindings are defined using the |
![]() |
We specify here that we want JBoss Portal to send parameter values when an explicit bindings are
defined ( |
![]() | An alias binding definition consists of:
In this example, we defined an alias binding named " |
Creating a new alias binding is done by first selecting one or more public parameters that will be used for the binding:
The interface will prompt you for a name for this new binding:
Clicking on Create alias will create the new binding and it will appear in the existing binding lists:
A parameter binding allows users to specify that public render parameters with different names are semantically equivalent so that when one such parameter is updated, all the portlets that can handle such a parameter receive the update, regardless of the name of the parameter that got updated. In the implicit case, portlets can only react to changes of values in parameters whose name they know.
Consider the following example. We are deploying two portlets, Portlet A and
Portlet B, from different vendors and assign them to
Window A and Window B, respectively. Each portlet can react to a
specific public render parameter ({nsA}paramA and {nsB}paramB,
respectively). Under the implicit coordination model, these portlets wouldn't be able
to communicate even if both parameters were semantically equivalent. JBoss Portal's explicit coordination
model allows users to explicit the semantic link between both parameter names such that, when
Portlet A updates the value of {nsA}paramA, Portlet B
gets notified of the update via a change of value of {nsB}paramB:
Explicit parameter bindings can be defined in any page definition of your *-object.xml
descriptors. For example, this is how the example that we detailed above would be implemented, within a
page definition:
... <coordination><bindings>
<paramet
er-binding> <id>parameterBinding</id> <wind
ow-coordination> <window-name>Window A</window-name> <qname>{nsA}paramA</qname> </window-coordination> <window-coordination> <window-name>Window B</window-name> <qname>{nsB}paramB</qname> </window-coordination> </parameter-binding> </bindings> </coordination>
![]() |
Coordination configuration is done via the newly introduced |
![]() |
Parameter bindings are defined using the |
![]() | A parameter binding definition consists of:
In this example, we defined a parameter binding named " |
![]() | A window / parameter name pair identifying either a public parameter to be wired. |
Creating a new parameter binding is done by first selecting a public parameter / window from the list:
The interface will prompt you for a name for this new binding:
Clicking on Create binding will create the new binding and it will appear in the existing binding lists:
An event wiring wires an event produced by specified portlet windows to consumer portlet windows. In the implicit form, this wiring associates producer and consumer via the event's qualified name (QName).
Explicit event wirings can be defined in any page definition of your *-object.xml
descriptors. For example, this is how the example that we detailed above would be implemented, within a
page definition:
... <coordination><wirings>
<implicit
-mode>TRUE</implicit-mode> <event-wi
ring> <name
>wiring</name> <sour
ces> <
window-coordination> <window-name>Window A</window-name> <qname>Event A</qname> </window-coordination> </sources> <dest
inations> <window-coordination> <window-name>Window B</window-name> <qname>Event B</qname> </window-coordination> <window-coordination> <window-name>Window C</window-name> <qname>Event C</qname> </window-coordination> </destinations> </event-wiring> </wirings> </coordination>
![]() |
Coordination configuration is done via the newly introduced |
![]() |
Event wirings are defined using the |
![]() | We specify here that we default to implicit wiring of events for this page. However, we will define one explicit event wiring that will take precedence over the implicit wiring when needed. |
![]() | An event wiring definition consists of:
|
![]() | The name of the event wiring which must be unique in the scope of the specified page. |
![]() |
The list of source events, each being identified by a
|
![]() | A window / event name pair identifying either a source or destination of event to be mapped. |
![]() |
The list of destination events, each being identified by a
|
Creating a new event wiring is fairly easy as the interface will guide you. First, it will present a list of available produced events on this page:
Select an event. The interface will display the list of all windows producing this event for this page. Note
also that your selection is summarized on the right side of the screen:
Selecting one or more windows (here we selected two) will continue the process. The interface will now
present you with the list of consumed events on this page, while your new event wiring is still be being
built up on the right side of the screen:
Select a destination event and be presented with the list of windows consuming that event:
Select one or more destination windows to which the source event will be mapped via the destination event.
You will now be ask to name your new event wiring after having the opportunity to review what will be
created. We name our new event wiring foo here:
Click on the Create wiring button. Your new event wiring has been created and will appear
in the list of existing wirings:
While the new <coordination> element can be used in both
<page> and <portal> elements, the only configuration that
can be specified at the portal level is whether to use the implicit mode or not:
<portal>
...
<coordination>
<bindings>
<implicit-mode>TRUE</implicit-mode>
</bindings>
<wirings>
<implicit-mode>FALSE</implicit-mode>
</wirings>
</coordination>
...
</portal>
Specifying this <implicit-mode> element at the portal level allows the user to specify
which default behavior to apply to child pages. Quite reasonably, if <implicit-mode>
is set to TRUE then the implicit mode will be used by default. This does not, however,
preclude specific pages to define explicit associations where needed. Setting
<implicit-mode> to FALSE, however, completely deactivates the
implicit handling of coordination features, leaving it up to users to configure only the associations that
need to be made. Note also that the implicit mode can be set for either bindings or
wirings. If no value is provided, implicit mode is used by default.
As part of the core-samples module, JBoss Portal provides several examples of how
coordination can be used. These examples are gathered in the Coordination Samples page. You
can look at how the examples are configured using the administration interface or by looking at the
portal-coordination-samples.war/WEB-INF/default-object.xml file.
The JBoss Portal request pipeline allows fine-grained, dynamic configuration of how JBoss Portal behaves when errors occur during runtime.
There are several types of errors that can occur during a request:
Access denied: the user does not have the required permissions to access the resource.
Error: an anticipated error, such as when a portlet throws an exception.
Internal error: an unexpected error.
Resource not found: the resource was not found.
Resource unavailable: the resource was found, but was not serviceable.
If an error occurs, the request control-flow changes according to the configuration. This configuration is known as the control policy.
When a control policy is invoked, the response sent by the control flow can be changed. If the control policy ignores the error, the error is handled by the next policy. If the control policy provides a new response, the next policy is not invoked, since the new response is not an error.
If a portlet in a page produces an exception, the following reactions are possible:
the error is displayed in the window.
the window is removed from the aggregation.
a portal error page is displayed.
a HTTP 500 error response is sent to the Web browser.
The default policy applies when errors are not handled by another level. By default, errors are translated into the most appropriate HTTP response:
Access denied: HTTP 403 Forbidden
Error: HTTP 500 Internal Server Error
Internal error: HTTP 500 Internal Server Error
Resource not found: HTTP 404 Not Found
Resource unavailable: HTTP 404 Not Found
The portal error-policy controls the response sent to the Web browser when an error occurs. A default error policy exists, which can be configured per portal. If an error occurs, the policy can either handle a redirect to a JSP page, or ignore it. If the error is ignored, it is handled by the default policy, otherwise a JSP page is invoked with the appropriate request attributes, allowing page customization.
The window error-policy controls how pages react to aggregation errors. Most of the time pages are an aggregation of several portlet windows, and the action to take when an error occurs differs from other policies. When an error occurs, the policy can either handle it, or ignore it. If the error is ignored, it is handled by the portal policy. Possible actions taken after such errors are:
remove the window from the aggregation.
replace the markup of the window using a redirect to a JSP page.
Different policies are configured using portal object properties, allowing the error-handling policy for objects to be configured in XML descriptors -- the *-object.xml files -- for a portal deployment.
A set of properties configure the the behavior of the portal policy. These properties are only taken into account for objects that use the portal type. The following table represents possible portal-policy properties:
Table 9.1.
| Property Name | Description | Possible Values |
|---|---|---|
control.portal.access_denied | when access is denied | ignore and jsp |
control.portal.unavailable | when a resource is unavailable | ignore and jsp |
control.portal.not_found | when a resource is not found | ignore and jsp |
control.portal.internal_error | when an unexpected error occurs | ignore and jsp |
control.portal.error | when an expected error occurs | ignore and jsp |
control.portal.resource_uri | the path to the JSP used for redirections | a valid path to a JSP located in the portal-core.war/ directory |
The following portal configuration demonstrates the use of portal-policy properties:
<portal>
<portal-name>MyPortal</portal-name>
...
<properties>
<property>
<name>control.portal.access_denied</name>
<value>ignore</value>
</property>
<property>
<name>control.portal.unavailable</name>
<value>ignore</value>
</property>
<property>
<name>control.portal.not_found</name>
<value>ignore</value>
</property>
<property>
<name>control.portal.internal_error</name>
<value>jsp</value>
</property>
<property>
<name>control.portal.error</name>
<value>jsp</value>
</property>
<property>
<name>control.portal.resource_uri</name>
<value>/WEB-INF/jsp/error/portal.jsp</value>
</property>
...
</properties>
...
</portal>
A set of properties configure the behavior of the page policy. These properties are only taken into account for objects that use the portal type. The following table represents possible page-policy properties:
Table 9.2.
| Property name | Description | Possible values |
|---|---|---|
control.page.access_denied | when access is denied | ignore, jsp and hide |
control.page.unavailable | when a resource is unavailable | ignore, jsp and hide |
control.page.not_found | when a resource is not found | ignore, jsp and hide |
control.page.internal_error | when an unexpected error occurs | ignore, jsp and hide |
control.page.error | when an expected error occurs | ignore, jsp and hide |
control.page.resource_uri | the path to the JSP used for redirections | ignore, jsp and hide |
The following page configuration demonstrates the use of page-policy properties:
<page>
<page-name>MyPortal</page-name>
...
<properties>
<property>
<name>control.page.access_denied</name>
<value>hide</value>
</property>
<property>
<name>control.page.unavailable</name>
<value>hide</value>
</property>
<property>
<name>control.page.not_found</name>
<value>hide</value>
</property>
<property>
<name>control.page.internal_error</name>
<value>jsp</value>
</property>
<property>
<name>control.page.error</name>
<value>jsp</value>
</property>
<property>
<name>control.page.resource_uri</name>
<value>/WEB-INF/jsp/error/page.jsp</value>
</property>
...
</properties>
...
</page>
When page properties are configured for objects that use the portal type, the properties are inherited by pages in that portal.
As described in previous sections, error handling can be redirected to a JSP™ page. Two pages can be created to handle errors: one for the portal level, and the other for the page level. Portal level error-handling requires a page that produces a full page, and page-level handling requires a page that produces markup, but only for a window. When the page is invoked, a set of request attributes are passed. The following table represents possible request attributes:
Table 9.3.
| Attribute Name | Attribute Description | Attribute Value |
|---|---|---|
org.jboss.portal.control.ERROR_TYPE | the error type | possible values are ACCESS_DENIED, UNAVAILABLE, ERROR, INTERNAL_ERROR, and NOT_FOUND |
org.jboss.portal.control.CAUSE | a cause which is thrown, that can be null | the object is a subclass of java.lang.Throwable |
org.jboss.portal.control.MESSAGE | an error message that can be null | text |
jboss-portal.sar/portal-core.war/ web application.
The error handling policy can be configured via the portal management application. To access the portal management application:
Use a Web browser to navigate to http://localhost:8080/portal.
Click the Login button on the top right-hand of the welcome page, and log in as the admin user.
Click the Admin tab on the top right-hand of the welcome page. Four tabs will appear on the left-hand side of the page.
Click the Admin tab to open the portal management application, and then click the Portal Objects tab to display available portals.
Configuration options are available as part of the properties for each configuration level. You can specify the default error handling policy (at the root of the portal object hierarchy) for each portal, or each page, by clicking on the Properties button for each page or portal:

As well, you can specify how dashboards should behave with respect to error handling, by clicking on the Dashboards tab in the portal management application:
The page specified with On error redirect to this resource is used when the Redirect to the specified resource action is selected for an error type, such as When access to the page is denied. After making changes, click the Update button for settings to take effect.
Since JBoss Portal 2.6 it is possible to provide an easy integration of content within the portal. Up to the 2.4 version content integration had to be done by configuring a portlet to show some content from an URI and then place that portlet on a page. The new content integration capabilities allows to directly configure a page window with the content URI by removing the need to configure a portlet for that purpose.

The portal uses portlets to configure content

The portal references directly the content and use portlet to interact with content
The content of a window is defined by
At runtime when the portal needs to render a window it delegates the production of markup to a content provider. The portal comes with a preconfigured set of providers which handles the portlet and the cms content types. The most natural way to plug a content provider in the portal is to use a JSR 286 Portlet. Based on a few carefully chosen conventions it is possible to provide an efficient content integration with the benefit of using standards and without requiring the usage of a proprietary API.
Content providers must be able to allow the user or administrator to chose content from the external resource it integrates in the portal in order to properly configure a portal window. A few interactions between the portal, the content provider and the portal user are necessary to achieve that goal. Here again it is possible to provide content customization using a JSR 286 Portlet. For that purpose two special portlet modes called edit_content and select_content has been introduced. It signals to the portlet that it is selecting or editing the content portion of the state of a portlet. select_content is used to select a new content to put in a window while edit_content is used to modify the previously defined content, often the two modes will display the same thing. The traditional edit mode is not used because the edit mode is more targeted to configure how the portlet shows content to the end user rather than what content it shows.

Portlet components are used to integrate content into the portal. It relies on a few conventions which allow the portal and the portlet to communicate.
At runtime the portal will call the portlet with the view mode when it displays content. It will send information about the content to display using the public render parameter urn:jboss:portal:content uri to the portlet. Therefore the portlet has just to read the render parameters and use them to properly display the content in the portlet. The public render parameters values are the key/value pairs that form the content properties and the resource URI of the content to display.
As explained before, the portal will call the portlet using the edit_content mode. In that mode the portlet and the portal will communicate using either action or render parameters. We have two use cases which are:
Here is the base skeleton of the content portlet. The FSContentDrivenPortlet shows the files which are in the war file in which the portlet is deployed. The arbitrary name filesystem will be the content type interpreted by the portlet.
public class FSContentDrivenPortlet extends GenericPortlet
{
/** The edit_content mode. */
public static final PortletMode EDIT_CONTENT_MODE = new PortletMode("edit_content");
...
}
First the doDispatch(RenderRequest req, RenderResponse resp) is overridden in order to branch the request flow to a method that will take care of displaying the editor.
protected void doDispatch(RenderRequest req, RenderResponse resp)
throws PortletException, PortletSecurityException, IOException
{
if (EDIT_CONTENT_MODE.equals(req.getPortletMode()))
{
doEditContent(req, resp);
}
else
{
super.doDispatch(req, resp);
}
}
The portlet also needs a few utilities methods which take care of converting content URI to a file back and forth. There is also an implementation of a file filter that keep only text files and avoid the WEB-INF directory of the war file for security reasons.
protected File getFile(String contentURI) throws IOException
{
String realPath = getPortletContext().getRealPath(contentURI);
if (realPath == null)
{
throw new IOException("Cannot access war file content");
}
File file = new File(realPath);
if (!file.exists())
{
throw new IOException("File " + contentURI + " does not exist");
}
return file;
}
protected String getContentURI(File file) throws IOException
{
String rootPath = getPortletContext().getRealPath("/");
if (rootPath == null)
{
throw new IOException("Cannot access war file content");
}
// Make it canonical
rootPath = new File(rootPath).getCanonicalPath();
// Get the portion of the path that is significant for us
String filePath = file.getCanonicalPath();
return filePath.length() >=
rootPath.length() ? filePath.substring(rootPath.length()) : null;
}
private final FileFilter filter = new FileFilter()
{
public boolean accept(File file)
{
String name = file.getName();
if (file.isDirectory())
{
return !"WEB-INF".equals(name);
}
else if (file.isFile())
{
return name.endsWith(".txt");
}
else
{
return false;
}
}
};
The editor is probably the longest part of the portlet. It tries to stay simple though and goes directly to the point.

protected void doEditContent(RenderRequest req, RenderResponse resp)
throws PortletException, PortletSecurityException, IOException
{
String uri = req.getParameter("current_uri");
if (uri == null)
{
// Get the uri value optionally provided by the portal
uri = req.getParameter("uri");
}
// Get the working directory directory
File workingDir = null;
String currentFileName = null;
if (uri != null)
{
workingDir = getFile(uri).getParentFile();
currentFileName = getFile(uri).getName();
}
else
{
// Otherwise try to get the current directory we are browsing,
// if no current dir exist we use the root
String currentDir = req.getParameter("current_dir");
if (currentDir == null)
{
currentDir = "/";
}
workingDir = getFile(currentDir);
}
// Get the parent path
String parentPath = getContentURI(workingDir.getParentFile());
// Get the children of the selected file, we use a filter
// to retain only text files and avoid WEB-INF dir
File[] children = workingDir.listFiles(filter);
// Configure the response
resp.setContentType("text/html");
PrintWriter writer = resp.getWriter();
//
writer.print("Directories:<br/>");
writer.print("<ul>");
PortletURL choseDirURL = resp.createRenderURL();
if (parentPath != null)
{
choseDirURL.setParameter("current_dir", parentPath);
writer.print("<li><a href=\"" + choseDirURL + "\">..</a></li>");
}
for (int i = 0;i < children.length;i++)
{
File child = children[i];
if (child.isDirectory())
{
choseDirURL.setParameter("current_dir", getContentURI(child));
writer.print("<li><a href=\"" + choseDirURL + "\">" + child.getName() +
"</a></li>");
}
}
writer.print("</ul><br/>");
//
writer.print("Files:<br/>");
writer.print("<ul>");
PortletURL selectFileURL = resp.createActionURL();
selectFileURL.setParameter("content.action.select", "select");
for (int i = 0;i < children.length;i++)
{
File child = children[i];
if (child.isFile())
{
selectFileURL.setParameter("current_uri", getContentURI(child));
if (child.getName().equals(currentFileName))
{
writer.print("<li><b>" + child.getName() + "</b></li>");
}
else
{
writer.print("<li><a href=\"" + selectFileURL + "\">" + child.getName() + "</a></li>");
}
}
}
writer.print("</ul><br/>");
//
writer.close();
}
Last but not least the portlet needs to implement the doView(RenderRequest req, RenderResponse resp) method in order to display the file that the portal window wants to show.
protected void doView(RenderRequest req, RenderResponse resp)
throws PortletException, PortletSecurityException, IOException
{
// Get the URI provided by the portal
String uri = req.getParameter("uri");
// Configure the response
resp.setContentType("text/html");
PrintWriter writer = resp.getWriter();
//
if (uri == null)
{
writer.print("No selected file");
}
else
{
File file = getFile(uri);
FileInputStream in = null;
try
{
in = new FileInputStream(file);
FileChannel channel = in.getChannel();
byte[] bytes = new byte[(int)channel.size()];
ByteBuffer buffer = ByteBuffer.wrap(bytes);
channel.read(buffer);
writer.write(new String(bytes, 0, bytes.length, "UTF8"));
}
catch (FileNotFoundException e)
{
writer.print("No such file " + uri);
getPortletContext().log("Cannot find file " + uri, e);
}
finally
{
if (in != null)
{
in.close();
}
}
}
//
writer.close();
}

Finally we need to make the portal aware of the fact that the portlet can edit and interpret content. For that we need a few descriptors. The portlet.xml descriptor will define our portlet, the portlet-instances.xml will create a single instance of our portlet. The web.xml descriptor will contain a servlet context listener that will hook the content type in the portal content type registry.
First, we need to define the portlet's particular event and render parameters:
<?xml version="1.0" encoding="UTF-8"?>
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
version="2.0">
<portlet>
<description>File System Content Driven Portlet</description>
<portlet-name>FSContentDrivenPortlet</portlet-name>
<display-name>File System Content Driven Portlet</display-name>
<portlet-class>org.jboss.portal.core.samples.basic.FSContentDrivenPortlet</portlet-class>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
<portlet-mode>EDIT_CONTENT</portlet-mode>
</supports>
<portlet-info>
<title>File Portlet</title>
<keywords>sample,test</keywords>
</portlet-info>
<supported-public-render-parameter>uri</supported-public-render-parameter>
<supported-publishing-event xmlns:x="urn:jboss:portal:content">x:select</supported-publishing-event>
</portlet>
<public-render-parameter>
<identifier>uri</identifier>
<qname xmlns:c="urn:jboss:portal:content">c:uri</qname>
</public-render-parameter>
<event-definition>
<qname xmlns:x="urn:jboss:portal:content">x:select</qname>
<value-type>java.lang.String</value-type>
</event-definition>
</portlet-app>
Note that here we need to use a JSR-286 portlet, this portlet will use the event urn:jboss:portal:content select and have a payload of type java.lang.String. This event will be used to tell the portal the URI selected by the user. This same portlet will also be in charge of rendering the content based on that URI, it will then also need to access the public render parameter qualified with the name: urn:jboss:portal:content uri.
The portlet.xml descriptor
<deployments>
...
<deployment>
<instance>
<instance-id>FSContentDrivenPortletInstance</instance-id>
<portlet-ref>FSContentDrivenPortlet</portlet-ref>
</instance>
</deployment>
...
</deployments
The portlet-instances.xml descriptor
<web-app>
...
<context-param>
<param-name>org.jboss.portal.content_type</param-name>
<param-value>filesystem</param-value>
</context-param>
<context-param>
<param-name>org.jboss.portal.portlet_instance</param-name>
<param-value>FSContentDrivenPortletInstance</param-value>
</context-param>
<listener>
<listener-class>org.jboss.content.ContentTypeRegistration</listener-class>
</listener>
...
</web-app>
The web.xml descriptor
How to create a portlet that will enable configuration of content at runtime has been covered above, however it is also possible to configure content in deployment descriptors. With our previous example it would give the following snippet placed in a *-portal.xml file:
<window> <window-name>MyWindow</window-name> <content> <content-type>filesystem</content-type> <content-uri>/dir1/foo.txt</content-uri> </content> <region>center</region> <height>1</height> </window>

JBoss Portal supports the integration of Google gadgets and Netvibes (UWA compatible) widgets out of the box. This integration allows you to display the content of the widget within a portlet. Both types can be added in the administration interface by editing the 'Page Layout' of a page or in the configuration of the users dashboard when selecting the appropriate 'Content type'.
It is possible to modify certain behavior of caching and fetching widgets by changing the init-param values of the portlet.
Connection timeout used for the directory lookup in milliseconds.
Time in minutes for which a widget should be cached. After this time the cached widget information will be deleted and fetched again when the information are needed.
Times in minutes for which a directory query should be cached. After this time the cached query information will be deleted.
This parameter defines if all widgets from a directory lookup should be fetched at the time of the query or not. The default values is false. This means that widgets are only fetched on demand - when the information is really needed.
The parameter for both widget types can be changed identically in either:
...
<portlet>
...
<init-param>
<name>connectionTimeout</name>
<value>5000</value>
</init-param>
<init-param>
<name>widgetExpiration</name>
<value>360</value>
</init-param>
<init-param>
<name>queryExpiration</name>
<value>60</value>
</init-param>
<init-param>
<name>fetchWidgetsOnDirectoryLookup</name>
<value>false</value>
</init-param>
...
</portlet>
...
For Netvibes widgets it is also possible to define a init-param called defaultHeight to set a specific default height if no height attribute is defined by the widget itself. The default value is 250.
JBoss Portal supports the standard portlet modes defined by the JSR-168 specification which are view, edit and help. In addition of that it also supports the admin portlet mode.
The admin mode defines a mode for the portlet which allows the administration of the portlet. Access to this mode is only granted to users having an appropriate role. In order to grant admin access to a portlet, the user must have a role which grants him the admin action permission on the portlet instance. This can be done in the instance deployment descriptor or using the administation portlet of the portal.
In order to be able to use the admin mode, the portlet must declare it in the portlet deployment descriptor.
<portlet-app>
...
<portlet>
...
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>admin</portlet-mode>
</supports>
...
</portlet>
...
<custom-portlet-mode>
<name>admin</name>
</custom-portlet-mode>
...
</portlet-app>
The following example shows the configuration of a portlet instance that grants the admin action permission to the Admin security role. It also grants the view action permission to all users.
...
<instance>
<instance-id>ModePortletInstance</instance-id>
<portlet-ref>ModePortlet</portlet-ref>
<security-constraint>
<policy-permission>
<action-name>admin</action-name>
<role-name>Admin</role-name>
</policy-permission>
<policy-permission>
<action-name>view</action-name>
<unchecked/>
</policy-permission>
</security-constraint>
</instance>
...
At runtime the security configuration section of the administration portlet can be used to grant or revoke the admin access. It can be done by clicking the security action of the portlet instance and then use the security editor.

Edit the security instance configuration
JBoss Portal provides an Application Programming Interface (API) which allows to write code that interacts with the portal. The life time and validity of the API is tied to the major version which means that no changes should be required when code is written against the API provided by the JBoss Portal 2.x versions and used in a later version of JBoss Portal 2.x.
The Portal API package prefix is org.jboss.portal.api. All of the classes that are part of this API are prefixed with this package name except for the org.jboss.portal.Mode and org.jboss.portal.WindowState classes. These two classes were defined before the official Portal API framework was created and so the names have been maintained for backward compatibility.
The Portlet API defines two classes that represent a portion of the visual state of a Portlet which are javax.portlet.PortletMode and javax.portlet.WindowState. Likewise the Portal API defines similar classes named org.jboss.portal.Mode and org.jboss.portal.WindowState which offer comparable characteristics, the main differences are:
Usage of factory methods to obtain instances.
Classes implements the java.io.Serializable interface.

The Mode class

The WindowState class
In the Portal API, the Mode interface is named like this because it does represent the mode of some visual object. The Portlet API names it PortletMode because it makes the assumption that the underlying object is of type Portlet.
There are times when a portlet needs to signal the portal or share information with it. The portal is the only authority to decide if it will take into account that piece of information or ignore it. In JBoss Portal we use as much as possible the mechanisms offered by the portlet spec to achieve that communication.
If a portlet desires to sign out the user, it can let the portal know by triggering a JSR-286 portlet event. To do so, simply defines the event "signOut" in the namespace "urn:jboss:portal" as a publishing event. In the action phase of the portlet, trigger the event, as a payload you can specify a redirection URL. If the payload is null, it will redirect the user to the default page of the default portal. See the following snippet to use in the action phase, it will ask the portal to sign out the user and redirect him to the JBoss Portal blog:
QName name = new QName("urn:jboss:portal", "signOut");
response.setEvent(name, "http://blog.jboss-portal.org");
The JSR-286 specification introduced a new phase for setting up the HTML headers. It is commonly used to add stylesheets
and javascript to the page. An extension of it for JBoss Portal lets you define the web browser title.
To define the web browser title, a portlet simply needs to define a new header element "title". This could be done by a portlet overriding
the method doHeaders(RenderRequest req, RenderResponse resp) to add such an element.
public void doHeaders(RenderRequest req, RenderResponse resp)
{
Element element = resp.createElement("title");
element.setTextContent("My new web browser title");
resp.addProperty(MimeResponse.MARKUP_HEAD_ELEMENT, element);
}
It several portlets on a page defines a web browser title, only one of them will be displayed. We can consider that the title to be displayed will be randomly chosen.
The Portal API defines the org.jboss.portal.api.PortalURL interface to represent URL managed by the portal.

The PortalURL interface
The setAuthenticated(Boolean wantAuthenticated) methods defines if the URL requires the authentication of the user. If the argument value is true then the user must be authenticated to access the URL, if the argument value is false then the user should not be authenticated. Finally if the argument value is null then it means that the URL authenticated mode should reuse the current mode.
The setSecure(Boolean wantSecure) methods defines the same as above but for the transport guarantee offered by the underlying protocol which means most of the time the secure HTTP protocol (HTTPS).
The setRelative(boolean relative) defines the output format of the URL and whether the created URL will be an URL relative to the same web server or will be the full URL.
The toString() method will create the URL as a string.

The PortalSession interface
It is possible to have access to a portion of the portal session to store objects. The org.jboss.portal.api.session.PortalSession interface defines its API and is similar to the javax.servlet.http.HttpSession except that it does not offer methods to invalidate the session as the session is managed by the portal.

The PortalRuntimeContext interface
The org.jboss.portal.api.PortalRuntimeContext gives access to state or operations associated at runtime with the current user of the portal. The String getUserId() retrieve the user id and can return null if no user is associated with the context. It also gives access to the PortalSession instance associated with the current user. Finally it gives access to the NavigationalStateContext associated with the current user.
The portal structure is a tree formed by nodes. It is possible to programmatically access the portal tree in order to
discover the tree structure of the portal
create URL that will render the different portal nodes
access the properties of a specific node

The PortalNode interface
As usual with tree structures, the main interface to study is the org.jboss.portal.api.node.PortalNode. That interface is intentionally intended for obtaining useful information from the tree. It is not possible to use it to modify the tree shape because it is not intended to be a management interface.
public interface PortalNode
{
int getType();
String getName();
String getDisplayName(Locale locale);
Map getProperties();
PortalNodeURL createURL(PortalRuntimeContext portalRuntimeContext);
...
}
The interface offers methods to retrieve informations for a given node such as the node type, the node name or the properties of the node. The noticeable node types are:
PortalNode.TYPE_PORTAL : the node represents a portal
PortalNode.TYPE_PAGE : the node represents a portal page
PortalNode.TYPE_WINDOW : the node represents a page window
The org.jboss.portal.api.node.PortalNodeURL is an extension of the PortalURL interface which adds additional methods useful for setting parameters on the URL. There are no guarantees that the portal node will use the parameters. So far portal node URL parameters are only useful for nodes of type PortalNode.TYPE_WINDOW and they should be treated as portlet render parameters in the case of the portlet is a local portlet and is not a remote portlet. The method that creates portal node URL requires as parameter an instance of PortalRuntimeContext.
The interface also offers methods to navigate the node hierarchy:
public interface PortalNode
{
...
PortalNode getChild(String name);
Collection getChildren();
PortalNode getRoot();
PortalNode getParent();
...
}
The navigational state is a state managed by the portal that associates to each user the state triggered by its navigation. A well known part of the navigational state are the render parameters provided at runtime during the call of the method void render(RenderRequest req, RenderResponse resp). The portal API offers an interface to query and update the navigational state of the portal. For now the API only exposes mode and window states of portal nodes of type window.

The NavigationalStateContext interface
Portal events are a powerful mechanism to be aware of what is happening in the portal at runtime. The base package for event is org.jboss.portal.api.event and it contains the common event classes and interfaces.

The PortalEvent class
The org.jboss.portal.api.event.PortalEvent abstract class is the base class for all kind of portal events.

The PortalEventContext interface
The org.jboss.portal.api.event.PortalEventContext interface defines the context in which an event is created and propagated. It allows retrieval of the PortalRuntimeContext which can in turn be used to obtain the portal context.

The PortalEventListener interface
The org.jboss.portal.api.event.PortalEventListener interface defines the contract that class can implement in order to receive portal event notifications. It contains the method void onEvent(PortalEvent event) called by the portal framework.
Listeners declaration requires a service to be deployed in JBoss that will instantiate the service implementation and register it with the service registry. We will see how to achieve that in the example section of this chapter.
The event propagation model uses one instance of a listener class to receive all portal events that may be routed to that class when appropriate. Therefore implementors needs to be aware of that model and must provide thread safe implementations.
Portal node events extend the abstract portal event framework in order to provide notifications about user interface events happening at runtime. For instance when the portal renders a page or a window, a corresponding event will be fired.

The portal node event class hierarchy
The org.jboss.portal.api.node.event.PortalNodeEvent class extends the org.jboss.portal.api.node.PortalEvent class and is the base class for all events of portal nodes. It defines a single method PortalNode getNode() which can be used to retrieve the node targetted by the event.
The org.jboss.portal.api.node.event.WindowEvent is an extension for portal nodes of type window. It provides access to the mode and window state of the window. It has 3 subclasses which represent different kind of event that can target windows.
The org.jboss.portal.api.node.event.WindowNavigationEvent is fired when the window navigational state changes. For a portlet it means that the window is targetted by an URL of type render.
The org.jboss.portal.api.node.event.WindowActionEvent is fired when the window is targetted by an action. For a portlet it means that the window is targetted by an URL of type action.
The org.jboss.portal.api.node.event.WindowRenderEvent is fired when the window is going to be rendered by the portal.
The org.jboss.portal.api.node.event.PageEvent is an extension for portal nodes of type page.
The org.jboss.portal.api.node.event.PageRenderEvent is fired when the page is going to be rendered by the portal.
A portal node event is fired when an event of interest happens to a portal node of the portal tree. The notification model is comparable to the bubbling propagation model defined by the DOM specification. When an event is fired, the event is propagated in the hierarchy from the most inner node where the event happens to the root node of the tree.

The portal node event propagation model
The org.jboss.portal.api.node.event.PortalNodeEventListener interface should be used instead of the too generic org.jboss.portal.api.event.PortalEventListener when it comes down of listening portal node events. Actually it does not replace it, the PortalEventListener interface semantic allows only traditional event delivering. The PortalNodeEventListener interface is designed to match the bubbling effect during an event delivery.
The PortalNodeEvent onEvent(PortalNodeEventContext context, PortalNodeEvent event) method declares a PortalNodeEvent as return type. Commonly the method returns null; however, a returned PortalNodeEvent replaces the event in the listeners subsequently called during the event bubbling process.

The PortalNodeEventContext interface
The org.jboss.portal.api.node.event.PortalNodeEventContext interface extends the PortalEventContext interface and plays an important role in the event delivery model explained in the previous section. That interface gives full control over the delivery of the event to ascendant nodes in the hierarchy, even more it gives the possibility to replace the current event being delivered by a new event that will be transformed into the corresponding portal behavior. However there are no guarantees that the portal will turn the returned event into a portal behavior, here the portal provides a best effort policy, indeed sometime it is not possible to achieve the substitution of one event by another.
Here the simplest implementation of a listener that does nothing except than correctly passing the control to a parent event listener if there is one.
public PortalNodeEvent onEvent(PortalNodeEventContext context, PortalNodeEvent event)
{
return context.dispatch();
}
The method PortalNode getNode() returns the current node being selected during the event bubbler dispatching mechanism.
The life cycle of the session of the portal associated with the user can also raise events. This kind of event is not bound to a portal node since it is triggered whenever a portal session is created or destroyed

The PortalSessionEvent class
There are two different types of events:
org.jboss.portal.api.session.event.PortalSessionEvent.SESSION_CREATED, fired when a new portal session is created
org.jboss.portal.api.session.event.PortalSessionEvent.SESSION_DESTROYED, fired when a new portal session is destroyed
The life cycle of the portal user can also raise events such as its authentication. A subclass of the wider scope UserEvent class is provided and triggers events whenever a user signs in or out. The UserEvent object gives access to the user name of the logged-in user through the method String getId().

The UserEvent class and UserAuthenticationEvent sub-classes
The UserAuthenticationEvent triggers two events that can be catched:
org.jboss.portal.api.session.event.UserAuthenticationEvent.SIGN_IN, fired when a portal user signs in
org.jboss.portal.api.session.event.UserAuthenticationEvent.SIGN_OUT, fired when a portal user signs out
Based on the UserEvent class other custom user related events could be added like one that would trigger when a new user is being registered
The events mechanism is quite powerful, in this section of the chapter we will see few simple examples to explain how it works.
In this example, we will create a simple counter of the number of logged-in registered users. In order to do that we just need to keep track of Sign-in and Sign-out events.
First, let's write our listener. It just a class that will implement org.jboss.portal.api.event.PortalEventListener and its unique method void onEvent(PortalEventContext eventContext, PortalEvent event). Here is such an example:
package org.jboss.portal.core.portlet.test.event;
import[...]
public class UserCounterListener implements PortalEventListener
{
/** Thread-safe long */
private final SynchronizedLong counter = new SynchronizedLong(0);
/** Thread-safe long */
private final SynchronizedLong counterEver = new SynchronizedLong(0);
public void onEvent(PortalEventContext eventContext, PortalEvent event)
{
if (event instanceof UserAuthenticationEvent)
{
UserAuthenticationEvent userEvent = (UserAuthenticationEvent)event;
if (userEvent.getType() == UserAuthenticationEvent.SIGN_IN)
{
counter.increment();
counterEver.increment();
}
else if (userEvent.getType() == UserAuthenticationEvent.SIGN_OUT)
{
counter.decrement();
}
System.out.println("Counter : " + counter.get());
System.out.println("Counter ever: " + counterEver.get());
}
}
}
On this method we simply filter down to UserAuthenticationEvent then depending on the type of authentication event we update the counters. counter keeps track of the registered and logged-in users, while counterEver only counts the number of times people logged-in the portal.
Now that the Java class has been written we need to register it so that it can be called when the events are triggered. To do so we need to register it as an MBean. It can be done by editing the sar descriptor file: YourService.sar/META-INF/jboss-service.xml so that it looks like the following:
<?xml version="1.0" encoding="UTF-8"?>
<server>
<mbean
code="org.jboss.portal.core.event.PortalEventListenerServiceImpl"
name="portal:service=ListenerService,type=counter_listener"
xmbean-dd=""
xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
<xmbean/>
<depends
optional-attribute-name="Registry"
proxy-type="attribute">portal:service=ListenerRegistry</depends>
<attribute name="RegistryId">counter_listener</attribute>
<attribute name="ListenerClassName">
org.jboss.portal.core.portlet.test.event.UserCounterListener
</attribute>
</mbean>
</server>
This snippet can be kept as it is, providing you change the values:
name: Must follow the pattern: portal:service=ListenerService,type={{UNIQUENAME}}
RegistryId: Must match the type (here: counter_listener)
ListenerClassName: Full path to the listener (here: org.jboss.portal.core.portlet.test.event.UserCounterListener).
That's it - we now have a user counter that will display it states each time a user logs-in our logs-out.
The first version of the Portlet Specification (JSR 168), regretfully, did not cover interaction between portlets. The side-effect of diverting the issue to the subsequent release of the specification, has forced portal vendors to each craft their own proprietary API to achieve inter portlet communication. Here we will see how we can use the event mechanism to pass parameters from one portlet to the other (and only to the other portlet).
The overall scenario will be that Portlet B will need to be updated based on some parameter set on Portlet A. To achieve that we will use a portal node event.
Portlet A is a simple Generic portlet that has a form that sends a color name:
public class PortletA extends GenericPortlet
{
protected void doView(RenderRequest request, RenderResponse response)
throws PortletException, PortletSecurityException, IOException
{
response.setContentType("text/html");
PrintWriter writer = response.getWriter();
writer.println("<form action=\"" + response.createActionURL() + "\" method=\"post\">");
writer.println("<select name=\"color\">");
writer.println("<option>blue</option>");
writer.println("<option>red</option>");
writer.println("<option>black</option>");
writer.println("</select>");
writer.println("<input type=\"submit\"/>");
writer.println("</form>");
writer.close();
}
}
The other portlet (Portlet B) that will receive parameters from Portlet A is also a simple Generic portlet:
public class PortletB extends GenericPortlet
{
public void processAction(ActionRequest request, ActionResponse response)
throws PortletException, PortletSecurityException, IOException
{
String color = request.getParameter("color");
if (color != null)
{
response.setRenderParameter("color", color);
}
}
protected void doView(RenderRequest request, RenderResponse response)
throws PortletException, PortletSecurityException, IOException
{
String color = request.getParameter("color");
response.setContentType("text/html");
PrintWriter writer = response.getWriter();
writer.println("<div" +
(color == null ? "" : " style=\"color:" + color + ";\"") +
">some text in color</div>");
writer.close();
}
// Inner listener explained after
}
With those two portlets in hands, we just want to pass parameters from Portlet A to Portlet B (the color in as a request parameter in our case). In order to achieve this goal, we will write an inner Listener in Portlet B that will be triggered on any WindowActionEvent of Portlet A. This listener will create a new WindowActionEvent on the window of Portlet B.
public static class Listener implements PortalNodeEventListener
{
public PortalNodeEvent onEvent(PortalNodeEventContext context, PortalNodeEvent event)
{
PortalNode node = event.getNode();
// Get node name
String nodeName = node.getName();
// See if we need to create a new event or not
WindowActionEvent newEvent = null;
if (nodeName.equals("PortletAWindow") && event instanceof WindowActionEvent)
{
// Find window B
WindowActionEvent wae = (WindowActionEvent)event;
PortalNode windowB = node.resolve("../PortletBWindow");
if (windowB != null)
{
// We can redirect
newEvent = new WindowActionEvent(windowB);
newEvent.setParameters(wae.getParameters());
newEvent.setMode(wae.getMode());
newEvent.setWindowState(WindowState.MAXIMIZED);
// Redirect to the new event
return newEvent;
}
}
// Otherwise bubble up
return context.dispatch();
}
}
It is important to note here some of the important items in this listener class. Logic used to determine if the requesting node was Portlet A.:
nodeName.equals("PortletAWindow")
Get the current window object so we can dispatch the event to it:
PortalNode windowB = node.resolve("../PortletBWindow");
Set the original parameter from Portlet A, so Portlet B can access them in its processAction():
newEvent.setParameters(wae.getParameters());
We still need to register our listener as an mbean:
<mbean
code="org.jboss.portal.core.event.PortalEventListenerServiceImpl"
name="portal:service=ListenerService,type=test_listener"
xmbean-dd=""
xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
<xmbean/>
<depends
optional-attribute-name="Registry"
proxy-type="attribute">portal:service=ListenerRegistry</depends>
<attribute name="RegistryId">test_listener</attribute>
<attribute name="ListenerClassName">
org.jboss.portal.core.samples.basic.event.PortletB$Listener
</attribute>
</mbean>
For node events, we also need to declare on which node we want to listen, this is done by modifying
the *-object.xml that defines your portal nodes. In this example we want to trigger
the listener each time the window containing the portlet A is actioned. We can add the listener
tag to specify that out listener with RegistryId=test_listener should be triggered
on events on the embedding object.
...
<window>
<window-name>PortletAWindow</window-name>
<instance-ref>PortletAInstance</instance-ref>
<region>center</region>
<height>0</height>
<listener>test_listener</listener>
</window>
...
Of course we could have added it at the page level instead of the window level. Note that a unique listener can be specified, the event mechanism is primarily done to let the developer change the navigation state of the portal, this example being a nice side-effect of this feature.
The portlet 2.0 specification (JSR 286) will cover Inter Portlet Communication so that portlets using it can work with different portal vendors.
Linking to some other pages or portals is also out of the scope of the portlet specification. As seen previously JBoss Portal offers an API in order to create links to other portal nodes. The JBoss request gives access to the current window node from which we can navigate from.
// Get the ParentNode. Since we are inside a Window, the Parent is the Page
PortalNode thisNode = req.getPortalNode().getParent();
// Get the Node in the Portal hierarchy tree known as "../default"
PortalNode linkToNode = thisNode.resolve("../default");
// Create a RenderURL to the "../default" Page Node
PortalNodeURL pageURL = resp.createRenderURL(linkToNode);
// Output the Node's name and URL for users
html.append("Page: " + linkToNode.getName() + " -> ");
html.append("<a href=\"" + pageURL.toString() + "\">" + linkToNode.getName() + "</a>");
From this, it is easy to create a menu or sitemap, the List getChildren() method will return all the child nodes on which the user has the view right access.
Those examples are available in the core-samples package in the sources of JBoss Portal. There are more examples of events usage in the samples delivered with JBoss Portal. One of them shows the usage of a portal node event to only have one window in normal mode at a time in a region. Anytime another window is being put in normal mode, all the other windows of the same regions are automatically minimized.
This section covers configuring JBoss Portal for a clustered environment.
JBoss Portal leverages various clustered services that are found in JBoss Application Server. This section briefly details how each is leveraged:
JBoss Cache: Used to replicate data among the different hibernate session factories that are deployed in each node of the cluster.
JBoss HA Singleton:
HA-JNDI: Used to replicate a proxy that will talk to the HA CMS on the cluster.
Http Session Replication: Used to replicate the portal and the portlet sessions.
JBoss SSO: Used to replicate the user identity, an authenticated user does not have to login again when failover occurs.
When you want to run JBoss Portal on a cluster there are a few things to keep in mind:
The portal associates with each user a http session in order to keep specific objects such as:
Replicating the portal session ensures that this state will be kept in sync on the cluster, e.g The user will see exactly the same portlet window on every node of the cluster. The activation of the portal session replication is made through the configuration of the web application that is the main entry point of the portal. This setting is available in the file jboss-portal.sar/portal-server.war/WEB-INF/web.xml
<web-app> <description>JBoss Portal</description> <!-- Comment/Uncomment to enable portal session replication --> <distributable/> ... </web-app>
JBoss Portal leverages hibernate for its database access. In order to improve performances it uses the caching features provided by hibernate. On a cluster the cache needs to be replicated in order to avoid state inconsistencies. Hibernate is configured with JBoss Cache which performs that synchronization transparently. Therefore the different hibernate services must be configured to use JBoss Cache. The following hibernate configurations needs to use a replicated JBoss Cache :
The cache configuration should look like :
<!-- | Uncomment in clustered mode : use transactional replicated cache --> <property name="cache.provider_class">org.jboss.portal.core.hibernate.JMXTreeCacheProvider </property> <property name="cache.object_name">portal:service=TreeCacheProvider,type=hibernate </property> <!-- | Comment in clustered mode <property name="cache.provider_configuration_file_resource_path"> conf/hibernate/instance/ehcache.xml</property> <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property> -->
Also we need to ensure that the cache is deployed by having in the file jboss-portal.sar/META-INF/jboss-service.xml the cache service uncommented :
<!-- | Uncomment in clustered mode : replicated cache for hibernate --> <mbean code="org.jboss.cache.TreeCache" name="portal:service=TreeCache,type=hibernate"> <depends>jboss:service=Naming</depends> <depends>jboss:service=TransactionManager</depends> <attribute name="TransactionManagerLookupClass"> org.jboss.cache.JBossTransactionManagerLookup</attribute> <attribute name="IsolationLevel">REPEATABLE_READ</attribute> <attribute name="CacheMode">REPL_SYNC</attribute> <attribute name="ClusterName">portal.hibernate</attribute> </mbean> <mbean code="org.jboss.portal.core.hibernate.JBossTreeCacheProvider" name="portal:service=TreeCacheProvider,type=hibernate"> <depends optional-attribute-name="CacheName">portal:service=TreeCache,type=hibernate </depends> </mbean>
More information can be found here.
JBoss Portal leverages the servlet container authentication for its own authentication mechanism. When
the user is authenticated on one particular node he will have to reauthenticate again if a different
node of the cluster (during a failover for instance) is used. This is valid only for the FORM
based authentication which is the default form of authentication that JBoss Portal uses. Fortunately JBoss
provides transparent reauthentication of the user called JBoss clustered SSO. Its configuration can be found
in $JBOSS_HOME/server/all/deploy/jboss-web.deployer/server.xml and you will need to
uncomment the following valve:
<Valve className="org.jboss.web.tomcat.service.sso.ClusteredSingleSignOn" />
More information can be found here.
The CMS backend storage relies on the Apache Jackrabbit project. Jackrabbit does not support clustering out of the box. So the portal run the Jackrabbit service on one node of the cluster using the HA-Singleton technology. The file jboss-portal.sar/portal-cms.sar/META-INF/jboss-service.xml contains the configuration. We will not reproduce it in this documentation as the changes are quite complex and numerous. Access from all nodes of the cluster is provided by a proxy bound in HA-JNDI. In order to avoid any bottleneck JBoss Cache is leveraged t