JBoss® Portal 2.6.6

Reference Guide

Thomas Heute

Julien Viet

Roy Russo

Release 2.6.6

July 2008


Table of Contents

Please Read: Important Trademark Information
JBoss Portal - Overview
Feature List
Target Audience
Acknowledgments
1. System Requirements
1.1. Minimum System Requirements
1.2. Supported Operating Systems
1.3. JBoss Application Server
1.4. Databases
1.5. Source Building
2. Installation
2.1. The JBoss Portal and JBoss AS Bundle
2.2. Installing the Binary Download
2.2.1. Setting up your Environment
2.2.1.1. Getting the Binary
2.2.1.2. JBoss EAP and JBoss AS Setup
2.2.1.3. Operating System Environment Settings
2.2.1.4. Database Setup
2.2.1.5. Datasource Descriptors
2.2.2. Deploying JBoss Portal
2.3. Installing from the Sources
2.3.1. Getting the Sources
2.3.2. JBoss EAP and JBoss AS Setup
2.3.2.1. JBoss Application Server Setup
2.3.2.2. Operating System Environment Settings
2.3.3. Building and Deploying from the Sources
2.3.4. Database Setup
2.3.5. Datasource Configuration
2.4. Deploying JBoss Portal
3. Customizing your Installation
3.1. Changing the Port
3.2. Changing the Context Path
3.3. Forcing the Database Dialect
3.3.1. Database Dialect Settings for JBoss Portal
3.3.2. DB Dialect Settings for the CMS Component
3.4. Configuring the Email Service
3.5. Configuring proxy settings
3.6. Disabling Dynamic Proxy Un-wrapping
4. Upgrading JBoss Portal 2.4 to 2.6
4.1. Manual Upgrade
4.1.1. Themes
4.1.2. Updating the Database
4.1.3. Portlet Names
4.1.4. CMS
5. Portlet Primer
5.1. JSR-168 Overview
5.1.1. Portal Pages
5.1.2. Rendering Modes
5.1.3. Window States
5.1.4. Section Status
5.2. Tutorials
5.2.1. Deploying your first Portlet
5.2.1.1. Introduction
5.2.1.2. Package Structure
5.2.1.3. Portlet Classes
5.2.1.4. Application Descriptors
5.2.1.5. Building your Portlet
5.2.1.6. Deploying your Portlet
5.2.2. An example JavaServer Pages (JSP) portlet
5.2.2.1. Introduction
5.2.2.2. Package Structure
5.2.2.3. Portlet Classes
5.2.2.4. JSP files and the Portlet Tag Library
5.2.2.5. Building your JSP portlet
5.2.2.6. Deploying your JSP portlet
5.2.3. An example Sun JSF Reference Implementation (RI) portlet
5.2.3.1. Introduction
5.2.3.2. Package Structure
5.2.3.3. Application Descriptors
5.2.3.4. Building your JSF portlet
5.2.3.5. Deploying your JSF portlet
5.2.4. An example Apache MyFaces JSF portlet
5.2.4.1. Introduction
5.2.4.2. Package Structure
5.2.4.3. Application Descriptors
5.2.4.4. Building your Apache MyFaces JSF portlet
5.2.4.5. Deploying your Apache MyFaces JSF portlet
6. XML Descriptors
6.1. Changes from previous Releases
6.1.1. The JBoss Portlet DTD
6.1.2. The JBoss Portlet Instance DTD
6.1.3. The JBoss Portal Object DTD
6.1.4. The JBoss Portal App DTD
6.2. Portlet Descriptors
6.2.1. *-object.xml Descriptors
6.2.2. The portlet-instances.xml Descriptor
6.2.3. The jboss-portlet.xml Descriptor
6.2.3.1. Injecting Header Content
6.2.3.2. Injecting Services in the portlet Context
6.2.3.3. Defining extra portlet Information
6.2.3.4. Portlet Session Replication in a Clustered Environment
6.2.4. The portlet.xml Descriptor
6.3. JBoss Portal Descriptors
6.3.1. Datasource Descriptors (portal-*-ds.xml)
6.3.1.1. Datasource Descriptors included in Binary releases
6.3.1.2. Building Datasource Descriptors from Source
6.3.2. Portlet Debugging (jboss-portal.sar/conf/config.xml)
6.3.3. Log in to Dashboard
6.4. Descriptor Examples
6.4.1. Defining a new Portal Page
6.4.2. Defining a new Portal Instance
7. Portal URLs
7.1. Introduction to Portals
7.2. Accessing a Portal
7.3. Accessing a Page
7.4. Accessing CMS Content
8. Error Handling Configuration
8.1. Error Types
8.2. Control Policies
8.2.1. Policy Delegation and Cascading
8.2.2. Default Policy
8.2.3. Portal Policy
8.2.4. Page Policy
8.3. Configuration using XML Descriptors
8.3.1. Portal Policy Properties
8.3.2. Page Policy Properties
8.4. Using JSP to Handle Errors
8.5. Configuration using the Portal Management Application
9. Content Integration
9.1. Window content
9.2. Content customization
9.3. Content Driven Portlet
9.3.1. Displaying content
9.3.2. Configuring content
9.3.3. Step by step example of a content driven portlet
9.3.3.1. The Portlet skeleton
9.3.3.2. Overriding the dispatch method
9.3.3.3. Utilities methods
9.3.3.4. The editor
9.3.3.5. Viewing content at runtime
9.3.3.6. Hooking the portlet into the portal
9.4. Configuring window content in deployment descriptor
10. Widget Integration
10.1. Introduction
10.2. Widget portlet configuration
11. Portlet Modes
11.1. Admin Portlet Mode
11.1.1. Portlet configuration
11.1.2. Declarative instance security configuration
11.1.3. Instance security configuration with the administration portlet
12. Portal API
12.1. Introduction
12.2. Portal URL
12.3. Portal session
12.4. Portal runtime context
12.5. Portal nodes
12.6. Portal navigational state
12.7. Portal events
12.7.1. Portal node events
12.7.1.1. Portal node event propagation model
12.7.1.2. Portal node event listener
12.7.1.3. Portal node event context
12.7.2. Portal session events
12.7.3. Portal user events
12.8. Examples
12.8.1. UserAuthenticationEvent example
12.8.2. Achieving Inter Portlet Communication with the events mechanism
12.8.3. Link to other pages
13. Clustering Configuration
13.1. Introduction
13.2. Considerations
13.3. JBoss Portal Clustered Services
13.3.1. Portal Session Replication
13.3.2. Hibernate clustering
13.3.3. Identity clustering
13.3.4. CMS clustering
13.4. Setup
13.5. Portlet Session Replication
13.5.1. JBoss Portal configuration
13.5.2. Portlet configuration
13.5.3. Limitations
14. Web Services for Remote Portlets (WSRP)
14.1. Introduction
14.2. Level of support in JBoss Portal
14.3. Deploying JBoss Portal's WSRP services
14.3.1. Considerations to use WSRP when running Portal on a non-default port or hostname
14.3.2. Considerations to use WSRP with SSL
14.4. Making a portlet remotable
14.5. Consuming JBoss Portal's WSRP portlets from a remote Consumer
14.6. Consuming remote WSRP portlets in JBoss Portal
14.6.1. Overview
14.6.2. Configuring a remote producer walk-through
14.6.2.1. Using the configuration portlet
14.6.2.2. Using a WSRP Producer XML descriptor
14.6.2.3. Configuring access to a remote portlet
14.6.3. WSRP Producer descriptors
14.6.3.1. Required configuration information
14.6.3.2. Optional configuration
14.6.4. Examples
14.7. Consumers maintenance
14.7.1. Modifying a currently held registration
14.7.1.1. Registration modification for service upgrade
14.7.1.2. Registration modification on producer error
14.7.2. Consumer operations
14.7.3. Erasing local registration data
14.8. Configuring JBoss Portal's WSRP Producer
14.8.1. Overview
14.8.2. Default configuration
14.8.3. Registration configuration
14.8.3.1. Customization of Registration handling behavior
14.8.4. WSRP validation mode
15. Security
15.1. Securing Portal Objects
15.2. Securing the Content Management System
15.2.1. CMS Security Configuration
15.2.1.1. CMS Super User
15.2.1.2. CMS Security Console
15.3. Authentication with JBoss Portal
15.3.1. Authentication configuration
15.3.2. The portal servlet
15.4. Authorization with JBoss Portal
15.4.1. The portal permission
15.4.2. The authorization provider
15.4.3. Making a programmatic security check
15.4.4. Configuring an authorization domain
16. JBoss Portal Identity Management
16.1. Identity management API
16.1.1. How to obtain identity modules services ?
16.1.2. API changes since 2.4
16.2. Identity configuration
16.2.1. Main configuration file architecture (identity-config.xml)
16.2.1.1. Datasources
16.2.1.2. Modules
16.2.1.3. Options
16.3. User profile configuration
16.4. Identity modules implementations
16.4.1. Database modules
16.4.2. Delegating UserProfile module
16.4.3. Database UserProfile module implementation
17. JBoss Portal Identity Portlets
17.1. Introduction
17.1.1. Features
17.2. Configuration
17.2.1. Captcha support
17.2.2. Lost password
17.2.3. Reset password
17.2.4. jBPM based user registration
17.2.5. The configuration file
17.2.6. Customize e-mail templates
17.3. User interface customization
17.3.1. Example 1: required fields
17.3.2. Example 2: dynamic values (dropdown menu with predefined values)
17.3.3. Example 3: adding new properties
17.3.4. Illustration
17.3.5. Customizing the View Profile page
17.4. Customizing the workflow
17.4.1. Duration of process validity
17.5. Disabling the Identity Portlets
17.5.1. Enabling the Identity Portlets
18. Authentication and Authorization
18.1. Authentication in JBoss Portal
18.1.1. Configuration
18.2. JAAS Login Modules
18.2.1. org.jboss.portal.identity.auth.IdentityLoginModule
18.2.2. org.jboss.portal.identity.auth.DBIdentityLoginModule
18.2.3. org.jboss.portal.identity.auth.SynchronizingLdapLoginModule
18.2.4. org.jboss.portal.identity.auth.SynchronizingLdapExtLoginModule
18.2.5. org.jboss.portal.identity.auth.SynchronizingLoginModule
19. LDAP
19.1. How to enable LDAP usage in JBoss Portal
19.2. Configuration of LDAP connection
19.2.1. Connection Pooling
19.2.2. SSL
19.2.3. ExternalContext
19.3. LDAP Identity Modules
19.3.1. Common settings
19.3.2. UserModule
19.3.2.1. LDAPUserModuleImpl
19.3.2.2. LDAPExtUserModuleImpl
19.3.3. RoleModule
19.3.3.1. LDAPRoleModuleImpl
19.3.3.2. LDAPExtRoleModuleImpl
19.3.4. MembershipModule
19.3.4.1. LDAPStaticGroupMembershipModuleImpl
19.3.4.2. LDAPStaticRoleMembershipModuleImpl
19.3.5. UserProfileModule
19.3.5.1. LDAPUserProfileModuleImpl
19.4. LDAP server tree shapes
19.4.1. Keeping users membership in role entries
19.4.1.1. Example LDIF
19.4.1.2. Example identity configuration
19.4.2. Keeping users membership in user entries
19.4.2.1. Example LDIF
19.4.2.2. Example identity configuration
19.5. Synchronizing LDAP configuration
19.6. Supported LDAP servers
20. Single Sign On
20.1. Overview of SSO in portal
20.2. Using an Apache Tomcat Valve
20.2.1. Enabling the Apache Tomcat SSO Valve
20.2.2. Example of usage
20.3. CAS - Central Authentication Service
20.3.1. Integration steps
20.4. Java Open Single Sign-On (JOSSO)
20.4.1. Integration steps
21. CMS Portlet
21.1. Introduction
21.2. Features
21.3. CMS content
21.3.1. Configuring a window to display CMS content
21.4. CMS Configuration
21.4.1. Display CMS content
21.4.2. Service Configuration
21.4.2.1. Tuning Apache Jackrabbit
21.4.2.2. Changing the url under which the content should be accessible
21.4.3. Configuring the Content Store Location
21.4.3.1. 100% Filesystem Storage
21.4.3.2. 100% Database Storage
21.4.3.3. Mixed Storage
21.5. Localization Support
21.6. CMS Service
21.6.1. CMS Interceptors
22. Portal Workflow
22.1. jBPM Workflow Engine Integration
22.2. CMS Publish/Approve Workflow Service
23. Navigation Tabs
23.1. Explicit ordering of tabs
23.2. Translating tab labels
23.2.1. Method one: Multiple display-name
23.2.2. Defining a resource bundle and supported locales
24. Layouts and Themes
24.1. Overview
24.2. Header
24.2.1. Overview
24.2.1.1. Writing his own JSP pages
24.3. Layouts
24.3.1. How to define a Layout
24.3.2. How to use a Layout
24.3.2.1. Declarative use
24.3.2.2. Programmatic use
24.3.3. Where to place the Descriptor files
24.3.4. Layout JSP tags
24.4. RenderSets
24.4.1. What is a RenderSet
24.4.2. How is a RenderSet defined
24.4.3. How to specify what RenderSet to use
24.5. Themes
24.5.1. What is a Theme
24.5.2. How to define a Theme
24.5.3. How to use a Theme
24.5.4. How to write your own Theme
24.6. Other Theme Functionalities and Features
24.6.1. Content Rewriting and Header Content Injection
24.6.2. Declarative CSS Style injection
24.6.3. Disabling Portlet Decoration
24.7. Theme Style Guide (based on the Industrial theme)
24.7.1. Overview
24.7.2. Main Screen Shot
24.7.3. List of CSS Selectors
24.8. Additional Ajax selectors
25. Ajax
25.1. Introduction
25.2. Ajaxified markup
25.2.1. Ajaxified layouts
25.2.2. Ajaxified renderers
25.3. Ajaxified pages
25.3.1. Drag and Drop
25.3.2. Partial refresh
25.3.2.1. Portal objects configuration
25.3.2.2. Portlet configuration
25.3.2.3. Limitations
26. Troubleshooting and FAQ
26.1. Troubleshooting and FAQ
A. *-object.xml DTD
B. portlet-instances.xml DTD
C. jboss-portlet.xml DTD

Please Read: Important Trademark Information

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.

JBoss Portal - Overview

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, 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 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.

Feature List

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).
  • Content Repository for Java™ technology API (JSR-170).
  • JavaServer™ Faces 1.2 (JSR-252).
  • 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.

Target Audience

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 .

Acknowledgments

We would like to thank the developers that participate in the JBoss Portal project.

Specifically:

  • Luca Stancapiano and Luc Boudreau for their localization contributions.
  • Antoine Herzog for his feedback, writing Wikis, and 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, Noel Rocher for his contributions and early feedback on JBoss Portal 2.6, and James Cobb for the renaissance theme.
  • 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 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.

Chapter 1. System Requirements

Thomas Heute

Roy Russo

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.

1.1. Minimum System Requirements

  • JDK™ 5 (JDK 6 is not part of the test platform)
  • 512 MB RAM
  • 100 MB hard disk space
  • 400 MHz CPU

1.2. Supported Operating Systems

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.

1.3. JBoss Application Server

JBoss Portal 2.6.6 is tested with JBoss Application Server (AS) 4.2.3, and Boss Enterprise Application Platform (EAP) 4.3. It is highly recommended that customers who have access to the JBoss Customer Support Portal (CSP) use JBoss EAP 4.3 (It is mandatory to get access to professional support). Customers who do not have access to the JBoss CSP should use JBoss AS.

Warning

JBoss AS versions 4.0.x are not supported.

1.4. Databases

JBoss Portal is database-agnostic. The following list outlines known-to-be-working database vendor and version combinations:

Note

JBoss 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.

1.5. Source Building

The source building mechanism works on Linux, Windows, Mac OS X, and UNIX operating systems.

Chapter 2. Installation

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.

2.1. The JBoss Portal and JBoss AS Bundle

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:

  1. Get the bundle: the bundle is available from the JBoss Portal Downloads page. Bundles use the JBoss Portal + JBoss AS naming convention.

  2. 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.

  3. 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.

  4. 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.

SQL Errors

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
				

2.2. Installing the Binary Download

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.

2.2.1. Setting up your Environment

2.2.1.1. Getting the Binary

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.

2.2.1.2. JBoss EAP and JBoss AS Setup

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.

Use the JBoss EAP and JBoss AS ZIP file

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.

2.2.1.3. Operating System Environment Settings

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:

  1. 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/
    

  2. Run the following command to enable the JBOSS_HOME environment variable:

    source ~/.bashrc
    

JBoss EAP JBOSS_HOME Environment Variable

If you are running JBoss EAP, configure the JBOSS_HOME environment variable to point to the /path/to/jboss-eap-version/jboss-as/ directory.

2.2.1.4. Database Setup

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:

  1. Create a new database: this guide assumes that the new database is called jbossportal.

  2. 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.

  3. 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.

2.2.1.5. Datasource Descriptors

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/configuration/deploy/ directory, where 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.

2.2.2. Deploying JBoss Portal

To start JBoss EAP or JBoss AS and deploy JBoss Portal:

  1. 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/configuration/deploy/ directory.

  2. 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.

  3. 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:

SQL Errors

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

2.3. Installing from the Sources

2.3.1. Getting the Sources

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.6.x versions are located at http://anonsvn.jboss.org/repos/portal/branches/JBoss_Portal_Branch_2_6.

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.6.6, and the locations of their source code:

  • JBoss Portal Common 1.1.2: http://anonsvn.jboss.org/repos/portal/modules/common/tags/JBP_COMMON_1_1_2

  • JBoss Portal Web 1.1.0: http://anonsvn.jboss.org/repos/portal/modules/web/tags/JBP_WEB_1_1_0

  • JBoss Portal Test 1.0.1.SP1: http://anonsvn.jboss.org/repos/portal/modules/test/tags/JBP_TEST_1_0_1_SP1

  • JBoss Portal Portlet 1.0.3: http://anonsvn.jboss.org/repos/portal/modules/portlet/tags/JBP_PORTLET_1_0_3

  • JBoss Portal Identity 1.0.4: http://anonsvn.jboss.org/repos/portal/modules/identity/tags/JBP_IDENTITY_1_0_4

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.

2.3.2. JBoss EAP and JBoss AS Setup

2.3.2.1. JBoss Application Server Setup

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.

Use the JBoss EAP and JBoss AS ZIP file

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.

2.3.2.2. Operating System Environment Settings

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:

  1. 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/
    

  2. Run the following command to enable the JBOSS_HOME environment variable:

    source ~/.bashrc
    

JBoss EAP JBOSS_HOME Environment Variable

If you are running JBoss EAP, configure the JBOSS_HOME environment variable to point to the /path/to/jboss-eap-version/jboss-as/ directory.

2.3.3. Building and Deploying from the Sources

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:

Portal Modules

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:

  1. Change into the JBOSS_PORTAL_SOURCE_DIRECTORY/build/ directory, and run the following command:

    sh build.sh main
    

  2. 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.

2.3.4. Database Setup

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:

  1. Create a new database: this guide assumes that the new database is called jbossportal.

  2. 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.

  3. 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.

2.3.5. Datasource Configuration

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/configuration/deploy/ directory, where 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.

2.4. Deploying JBoss Portal

To start JBoss EAP or JBoss AS and deploy JBoss Portal:

  1. 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/configuration/deploy/ directory.

  2. 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.

  3. 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:

SQL Errors

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

Chapter 3. Customizing your Installation

Thomas Heute

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 26, Troubleshooting and FAQ.

3.1. Changing the Port

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 14.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.

Root User Privileges

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.

3.2. Changing the Context Path

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:

  1. 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>

  2. 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:

  1. 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.

  2. 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.

  3. To clean the project, make sure you are connected to the Internet, and change into the build/ directory. Run the ant clean command.

  4. Rebuild and redeploy JBoss Portal. Refer to Section 2.3, “Installing from the Sources” for build instructions.

Changing the context-root

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>

3.3. Forcing the Database Dialect

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.

3.3.1. Database Dialect Settings for JBoss Portal

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/module/conf/hibernate/directory/ directory, where 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.

3.3.2. DB Dialect Settings for the CMS Component

To modify the DB dialect setting for the JBoss Portal CMS component:

  1. Open the jboss-portal.sar/portal-cms.sar/conf/hibernate/cms/hibernate.cfg.xml file.

  2. 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.

3.4. Configuring the Email Service

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.

3.5. Configuring proxy settings

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.

3.6. Disabling Dynamic Proxy Un-wrapping

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

Chapter 4. Upgrading JBoss Portal 2.4 to 2.6

Warning

Before performing any instructions or operations in this chapter, back up your database and the entire JBoss EAP or JBoss AS directory!

4.1. Manual Upgrade

The database schema has not changed since JBoss Portal 2.4; however, there are several differences when using a database created by JBoss Portal 2.4, that prevent simply deploying the latest version of JBoss Portal. For example, some portlets are no longer present in JBoss Portal 2.6, and certain existing portlets are now packaged differently. This chapter describes updating a MySQL database created by JBoss Portal 2.4, for use with JBoss Portal 2.6.

Users, roles, and pages created in JBoss Portal 2.4 should be accessible in JBoss Portal 2.6 deployments.

The upgrade procedure can be straightforward:

  1. If you are using the JBoss Portal binary, remove the $JBOSS_HOME/server/default/deploy/jboss-portal.sar/ directory. If JBoss Portal was built from source, remove the $JBOSS_HOME/server/default/deploy/jboss-portal.sar file.

  2. Update the data in the JBoss Portal database, as described in Section 4.1.2, “Updating the Database”.

  3. Deploy JBoss Portal 2.6.

4.1.1. Themes

In JBoss Portal 2.6, portal pages contain additional areas, such as the Login, Admin, and Dashboard links, on the top right-hand corner of portal pages:

Since portal pages now contain additional areas, certain themes have changed. If a default theme that exists in JBoss Portal 2.6 is used, such as renaissance, no configuration should be necessary. Using old themes from JBoss Portal 2.4 may make JBoss Portal 2.6 unusable, for example, not being able to log in. To update custom themes, refer to the bundled JBoss Portal 2.6 themes as an example.

4.1.2. Updating the Database

The following tables contain all references to portlets:

  • JBP_INSTANCE

  • JBP_WINDOW

  • JBP_OBJECT_NODE

All procedures described in the following sections can performed using the JBoss Portal 2.4 Admin portlet. Treat these directions as guidelines when migrating a large JBoss Portal deployment. Database data can be updated manually using the correct tools for your RDBMS. For example, if you are using a MySQL database, you can use the MySQL Query Browser.

During the upgrade process, legacy references have to be cleaned up, to either remove them, or to allow JBoss Portal 2.6 to recreate them correctly. Remove all references (instances and windows) to the portlets listed below, as they are not present in JBoss Portal 2.6. This can be done using the JBoss Portal 2.4 Admin portlet:

  • HeaderContentPortlet

  • URLPortlet

  • TestPortlet

  • PortletA

  • PortletB

  • SecuredTestPortlet

  • CharsetPortlet

  • CounterPortlet

  • CachedCounterPortlet

  • ExceptionPortlet

  • PortletSessionPortlet

  • EncodingPortlet

The following instructions refer to a standard JBoss Portal 2.4 deployment. If core portlets, portlet instances, or portlet windows were renamed, make the appropriate modifications. The following is an example of the MySQL Query Browser:

Requested Resource Error

When running JBoss Portal 2.6 with a database created by JBoss Portal 2.4, a non-existing portlet will try to be displayed, resulting in a 404, The requested resource() is not available error.

4.1.3. Portlet Names

Names of certain core bundled-portlets have changed. Destroy the following instances and use the Admin portlet to recreate them, or edit the JBP_INSTANCE table as follows:

  • Change local.samples.JSPPortlet in the PORTLET_REF column to local./portal-jsp-samples.JSPPortlet.

  • Change local.portal.CMSPortlet in the PORTLET_REF column to local./portal-cms.CMSPortlet.

  • Change local.portal.CMSAdminPortlet in the PORTLET_REF column to local./portal-cms.CMSAdminPortlet.

  • Change local.portal.ManagementPortlet in the PORTLET_REF column to local./portal-admin.AdminPortlet.

Some portlets are no longer present in JBoss Portal 2.6, and certain existing portlets are now packaged differently. Remove the following entries in the JBP_INSTANCE table, so that JBoss Portal 2.6 can recreate them:

  • rows containing NewsPortletInstance2 in the ID column.

  • rows containing local.portal.NavigationPortlet in the PORTLET_REF column.

  • rows containing local.samples.HeaderContentPortlet in the PORTLET_REF column.

  • rows containing local.samples.WeatherPortlet in the PORTLET_REF column.

  • rows containing local.samples.NewsPortlet in the PORTLET_REF column.

  • rows containing local.samples.URLPortlet in the PORTLET_REF column.

  • rows containing local.samples.TestPortlet in the PORTLET_REF column.

  • rows containing local.samples.PortletA in the PORTLET_REF column.

  • rows containing local.samples.PortletB in the PORTLET_REF column.

  • rows containing local.samples.SecuredTestPortlet in the PORTLET_REF column.

  • rows containing local.samples.CharsetPortlet in the PORTLET_REF column.

  • rows containing local.samples.CounterPortlet in the PORTLET_REF column.

  • rows containing local.samples.CachedCounterPortlet in the PORTLET_REF column.

  • rows containing local.samples.ExceptionPortlet in the PORTLET_REF column.

  • rows containing local.samples.PortletSessionPortlet in the PORTLET_REF column.

  • rows containing local.samples.EncodingPortlet in the PORTLET_REF column.

Remove the following entries in the JBP_WINDOW table, so that JBoss Portal 2.6 can recreate them:

  • rows containing NavigationPortletInstance in the INSTANCE_REF column.

  • rows containing URLPortletInstance in the INSTANCE_REF column.

  • rows containing PortletAInstance in the INSTANCE_REF column.

  • rows containing PortletBInstance in the INSTANCE_REF column.

  • rows containing EncodingPortletInstance in the INSTANCE_REF column.

  • rows containing PortletSessionPortletInstance in the INSTANCE_REF column.

  • rows containing CachedCounterPortletInstance in the INSTANCE_REF column.

  • rows containing CounterPortletInstance in the INSTANCE_REF column.

  • rows containing CharsetPortletInstance in the INSTANCE_REF column.

  • rows containing SecuredTestPortletInstance in the INSTANCE_REF column.

  • rows containing SecuredTestPortletInstance in the INSTANCE_REF column.

  • rows containing ExceptionPortletInstance in the INSTANCE_REF column.

  • rows containing HeaderContentPortletInstance in the INSTANCE_REF column.

  • rows containing TestPortletInstance in the INSTANCE_REF column.

  • rows containing MissingPortletInstance in the INSTANCE_REF column.

Remove the following entries in the JBP_OBJECT_NODE table, so that JBoss Portal 2.6 can recreate them:

  • rows containing NavigationPortletWindow in the NAME column.

  • rows containing URLPortletWindow in the NAME column.

  • rows containing PortletAWindow in the NAME column.

  • rows containing PortletBWindow in the NAME column.

  • rows containing MissingInstanceWindow in the NAME column.

  • rows containing EncodingPortletWindow in the NAME column.

  • rows containing PortletSessionPortletWindow in the NAME column.

  • rows containing CachedCounterPortletWindow in the NAME column.

  • rows containing CounterPortletWindow in the NAME column.

  • rows containing CharsetPortletWindow in the NAME column.

  • rows containing SecuredTestPortletWindow in the NAME column.

  • rows containing ExceptionPortletWindow in the NAME column.

  • rows containing MissingPortletWindow in the NAME column.

  • rows containing HeaderContentPortletWindow in the NAME column.

  • rows containing TestPortletWindow in the NAME column.

4.1.4. CMS

In JBoss Portal 2.6 versions, the way the CMS content is displayed changed significantly. For further information, refer to Chapter 9, Content Integration and Chapter 21, CMS Portlet. Currently there is no need to have more than one instance of the CMSPortlet. The portlet window displays CMS content, not by referring to that portlet instance, but by having the proper content-type defined. The following configuration is in the jboss-portal.sar/conf/data/default-object.xml file:

<window>
	<window-name>CMSWindow</window-name>
	<content>
		<content-type>cms</content-type>
		<content-uri>/default/index.html</content-uri>
	</content>
	<region>center</region>
	<height>1</height>
</window>

The following example uses the MySQL Query Browser. Open the JBP_OBJECT_NODE table in your database schema. Look at the PATH column to identify any occurrences of CMS in your JBoss Portal deployment. Identify any row referring to CMSPortletWindow, and remember the number in the PK column. The PK number is needed in the following steps:

Go to the JBP_WINDOW table and find a row with the same PK value from the JBP_OBJECT_NODE table. In such a row, replace CMSPortletInstance with a path to your CMS resource. For example, by default, JBoss Portal displays /default/index.html.

Add a row containing the following to the JBP_PORTAL_OBJECT_PROPS table:

  • The PK number remembered from the OBJECT_KEY column.

  • portal.windowContentType in the NAME column.

  • cms in the jbp_VALUE column.

As well, the CMS can be migrated by backing up the jbp_cms_* tables, and recreating them in a JBoss Portal 2.6 database. There were no schema changes for the CMS between JBoss Portal 2.4 and JBoss Portal 2.6.

Portlet Content-type and the path to the CMS Resource

The Admin portlet can be used to change the portlet window content-type, and configure the path to the CMS resource.

Chapter 5. Portlet Primer

Roy Russo

5.1. JSR-168 Overview

The JSR-168 Portlet Specification aims at defining portlets that can be used by any JSR-168 portlet container, also known as a portal. There are different portals with commercial and non-commercial licenses. This chapter gives a brief overview of the JSR-168 Portlet Specification. Portlet developers are strongly encouraged to read the JSR-168 Portlet Specification.

JBoss Portal is fully JSR-168 compliant, which means any JSR-168 portlet behaves as it should inside the portal.

5.1.1. Portal Pages

A portal can be seen as pages with different areas, and inside areas, different windows, and each window having one portlet:

5.1.2. Rendering Modes

A portlet can have different view modes. Three modes are defined by the JSR-168 specification, but a portal can extend those modes. The three modes are:

  • 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.

5.1.3. Window States

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.

5.1.4. Section Status

This overview of the JSR-168 Portlet Specification is a work in progress. Check back for more in-depth analsis of the specification. The sections following here after contain real-world cases for how to leverage the specification.

5.2. Tutorials

The tutorials contained in this chapter are targetted toward portlet developers. Although they are a good starting and reference point, it is highly recommend that portlet developers read and understand the JSR-168 Portlet Specification. Use the JBoss Portal User Forums for user-to-user help.

5.2.1. Deploying your first Portlet

5.2.1.1. Introduction

This section describes how to deploy a portlet in JBoss Portal. Before proceeding, download the HelloWorldPortlet from JBoss PortletSwap.

5.2.1.2. Package Structure

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:

5.2.1.3. Portlet Classes

The following is the HelloWorldPortlet/src/main/org/jboss/portlet/hello/HelloWorldPortlet.java Java source file, which comes bundled with the HelloWorldPortlet:


package org.jboss.portlet.hello;

import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.UnavailableException;
import java.io.IOException;
import java.io.PrintWriter;

public class HelloWorldPortlet extends GenericPortlet

{
	protected void doView(RenderRequest rRequest, RenderResponse rResponse) 
	throws PortletException, IOException, UnavailableException

	{
		rResponse.setContentType("text/html");
		PrintWriter writer = rResponse.getWriter();
		writer.write("Hello World!");
		writer.close();
	}

} 

public class HelloWorldPortlet extends GenericPortlet

All portlets must implement the javax.portlet.Portlet interface. The portlet API provides a convenient implementation of this interface, in the form of the javax.portlet.GenericPortlet class, which among other things, implements the Portlet render method to dispatch to abstract mode-specific methods to make it easier to support the standard portlet modes. As well, it provides a default implementation for the processAction, init and destroy methods. It is recommended to extend GenericPortlet for most cases.

protected void doView(RenderRequest rRequest, RenderResponse rResponse) 
throws PortletException, IOException, UnavailableException

As we extend from GenericPortlet, and are only interested in supporting the view mode, only the doView method needs to be implemented, and the GenericPortlet render implemention calls our implementation when the view mode is requested.

rResponse.setContentType("text/html");

As in the servlet world, you must declare what content-type the portlet will be responding in. Do this before starting to write content, or the portlet will throw an exception.

PrintWriter writer = rResponse.getWriter(); 
writer.write("Hello World!"); 
writer.close();

This produces the Hello World! text in our portlet window.

Markup Fragments

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.

5.2.1.4. Application Descriptors

JBoss Portal requires certain descriptors to be included in a portlet WAR file. Some of these descriptors are defined by the JSR-168 Portlet Specification, and others are specific to JBoss Portal. The following is an example of the directory structure of the HelloWorldPortlet portlet:

To create the WEB-INF/ and META-INF/ directories, extract the helloworldportlet.war file.

The following is an example of the HelloWorldPortlet/WEB-INF/portlet.xml file. This file must adhere to its definition in the JSR-168 Portlet Specification. You may define more than one portlet application in this file:

<?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>
      <portlet-name>HelloWorldPortlet</portlet-name>
      <portlet-class>org.jboss.portlet.hello.HelloWorldPortlet</portlet-class>
      <supports>
         <mime-type>text/html</mime-type>
         <portlet-mode>view</portlet-mode>
      </supports>
      <portlet-info>
         <title>HelloWorld Portlet</title>
      </portlet-info>
   </portlet>
</portlet-app>

<portlet-name>HelloWorldPortlet</portlet-name>

Define the portlet name. It does not have to be the class name.

<portlet-class>org.jboss.portlet.hello.HelloWorldPortlet</portlet-class>

The Fully Qualified Name (FQN) of your portlet class must be declared here.

<supports>
    <mime-type>text/html</mime-type>
    <portlet-mode>view</portlet-mode>
</supports>

The <supports> element declares all of the markup types that a portlet supports in the render method. This is accomplished via the <mime-type> element, which is required for every portlet. The declared MIME types must match the capability of the portlet. As well, it allows you to pair which modes and window states are supported for each markup type. All portlets must support the view portlet mode, so this does not have to be declared. Use the <mime-type> element to define which markup type your portlet supports, which in this example, is text/html. This section tells the portal that it only outputs text and HTML, and that it only supports the view mode.

<portlet-info>
    <title>HelloWorld Portlet</title>
</portlet-info>

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 HelloWorld Portlet.

The HelloWorldPortlet/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 HelloWorldPortlet/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 HelloWorldPortlet/WEB-INF/helloworld-object.xml file.

The following is an example of the HelloWorldPortlet/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/portal/dtd/portlet-instances_2_6.dtd">
<deployments>
   <deployment>
      <instance>
         <instance-id>HelloWorldPortletInstance</instance-id>
         <portlet-ref>HelloWorldPortlet</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 HelloWorldPortletInstance portlet instance.

  • the window is assigned to the default.default page.

  • the <region> element specifies where the window appears on the page.

The following is an example HelloWorldPortlet/WEB-INF/helloworld-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.default</parent-ref>
      <if-exists>overwrite</if-exists>
      <window>
         <window-name>HelloWorldPortletWindow</window-name>
         <instance-ref>HelloWorldPortletInstance</instance-ref>
         <region>center</region>
         <height>1</height>
      </window>
   </deployment>
</deployments>

<parent-ref>default.default</parent-ref>

Tells the portal where this portlet appears. In this case, default.default specifies that the portlet appears in the portal instance named default, and on the page named default.

<if-exists>overwrite</if-exists>

Instructs the portal to overwrite or keep this object if it 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.

<window-name>HelloWorldPortletWindow</window-name>

A unique name given to the portlet window. This can be named anything.

<instance-ref>HelloWorldPortletInstance</instance-ref>

The value of <instance-ref> must match the value of one of the <instance-id> elements found in the HelloWorldPortlet/WEB-INF/portlet-instances.xml file.

<region>center</region>
<height>1</height>

Specifies where the window appears within the page layout.

The following diagram illustrates the relationship between the portlet.xml, portlet-instances.xml, and helloworld-object.xml descriptors:

JBoss Portal 2.6 introduces 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, HelloWorldPortlet/WEB-INF/helloworld-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>HelloWorldPortletWindow</window-name>
         <content>
            <content-type>portlet</content-type>
            <content-uri>HelloWorldPortletInstance</content-uri>
         </content>
         <region>center</region>
         <height>1</height>
      </window>
   </deployment>
</deployments>

This declaration is equivalent to the previous HelloWorldPortlet/WEB-INF/helloworld-object.xml example. Use <content-type> to specify the content to display. In this example, the content being displayed by the HelloWorldPortletWindow is a portlet. The <content-uri> element specifies which content to display, which in this example, is the HelloWorldPortletInstance:

<content>
   <content-type>portlet</content-type>
   <content-uri>HelloWorldPortletInstance</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.

5.2.1.5. Building your Portlet

The HelloWorldPortlet.zip file contains a pre-compiled helloworldportlet.war file; however, to manually build the helloworldportlet.war file:

  1. Change into the HelloWorldPortlet/ directory, and remove the existing helloworldportlet.war file.

  2. If required, edit the HelloWorldPortlet/src/main/org/jboss/portlet/hello/HelloWorldPortlet.java file, and the application descriptors in the HelloWorldPortlet/src/resources/helloworldportlet-war/WEB-INF/ directory.

  3. Change into HelloWorldPortlet/ directory, and run the ant deploy command. On Windows, the output will be similar to the following:

Note: the directory names will be different for your system.

Expanding the helloworldportlet.war file allows you to deploy the portlet as an expanded directory, which makes development easier. As well, it gives you access to the application descriptors, resource files, JSF, and JSP pages. To expand the helloworldportlet.war file:

  1. If you do not have the HelloWorldPortlet/helloworldportlet.war file, change into the HelloWorldPortlet/ directory, and run the ant deploy command. This creates the helloworldportlet.war file.

  2. To expand the WAR file, change into the HelloWorldPortlet/ directory, and run the ant explode command. On Windows, the output will be similar to the following:

Note: the directory names will be different for your system.

The ant explode command creates a directory structure such as the following:

The expanded WAR file and the application descriptors are located in the HelloWorldPortlet/output/lib/exploded/helloworldportlet.war/WEB-INF/ directory.

5.2.1.6. Deploying your Portlet

If you did not expand the helloworldportlet.war file, copy the HelloWorldPortlet/helloworldportlet.war file into the correct JBoss AS or JBoss EAP deploy/ directory. If you expanded the helloworldportlet.war file, copy the HelloWorldPortlet/output/lib/exploded/helloworldportlet.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.

Performing this step on a running instance of JBoss AS or JBoss EAP, and JBoss Portal, triggers a hot-deploy of the portlet:

INFO  [TomcatDeployer] deploy, ctxPath=/helloworldportlet, 
warUrl=.../tmp/deploy/tmp35219helloworldportlet-exp.war/

To see the HelloWorldPortlet, navigate to http://localhost:8080/portal/, or, if the default JBoss Portal page is already open, refresh the page. The HelloWorldPortlet is added to the bottom of the default JBoss Portal page:

To re-deploy the portlet, for example, if you have made changes to any of the application descriptors, touch the $JBOSS_HOME/server/configuration/deploy/helloworldportlet.war/WEB-INF/web.xml file. This only works if you copied the HelloWorldPortlet/output/lib/exploded/helloworldportlet.war/ directory into the JBoss AS or JBoss EAP deploy/ directory. On Linux, run the touch $JBOSS_HOME/server/configuration/deploy/helloworldportlet.war/WEB-INF/web.xml command to re-deploy the HelloWorldPortlet.

Re-deploying the HelloWorldPortlet produces output to the JBoss AS or JBoss EAP console, similar to the following:

INFO  [TomcatDeployer] undeploy, ctxPath=/helloworldportlet, 
warUrl=.../deploy/helloworldportlet.war/
INFO  [TomcatDeployer] deploy, ctxPath=/helloworldportlet, 
warUrl=.../deploy/helloworldportlet.war/

5.2.2. An example JavaServer™ Pages (JSP™) portlet

5.2.2.1. Introduction

This section describes how to deploy a JSP™ portlet in JBoss Portal. Before proceeding, download the HelloWorldJSPPortlet from JBoss PortletSwap. The HelloWorldJSPPortlet demonstrates how to use JSP pages for view rendering, and the portlet tag library (taglib) for generating links.

5.2.2.2. Package Structure

The application descriptors for the HelloWorldJSPPortlet portlet are similar to those from the HelloWorldPortlet (Section 5.2.1.4, “Application Descriptors”). Refer to Section 6.2, “Portlet Descriptors” for further information about application descriptors.

The HelloWorldJSPPortlet portlet contains the traditional portlet and JBoss Portal specific application descriptors. The following is an example of the directory structure of the HelloWorldJSPPortlet portlet:

To create the WEB-INF/ and META-INF/ directories, extract the helloworldjspportlet.war file.

5.2.2.3. Portlet Classes

The HelloWorldJSPPortlet contains the HelloWorldJSPPortlet/src/main/org/jboss/portlet/hello/HelloWorldJSPPortlet.java file:

package org.jboss.portlet.hello;

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;
import java.io.IOException;

public class HelloWorldJSPPortlet extends GenericPortlet
{
   protected void doView(RenderRequest rRequest, RenderResponse rResponse)
                     throws PortletException, IOException, UnavailableException
   {
      rResponse.setContentType("text/html");

      String sYourName = (String) rRequest.getParameter("yourname");

      if(sYourName != null)
      {
         rRequest.setAttribute("yourname", sYourName);
         PortletRequestDispatcher prd = getPortletContext()
            .getRequestDispatcher("/WEB-INF/jsp/view2.jsp");
         prd.include(rRequest, rResponse);
      }
      else
      {
         PortletRequestDispatcher prd = getPortletContext()
            .getRequestDispatcher("/WEB-INF/jsp/view.jsp");
         prd.include(rRequest, rResponse);
      }
   }

   public void processAction(ActionRequest aRequest, ActionResponse aResponse)
                  throws PortletException, IOException, UnavailableException
   {
      String sYourname = (String) aRequest.getParameter("yourname");

      // do something

      aResponse.setRenderParameter("yourname", sYourname);
   }

   protected void doHelp(RenderRequest rRequest, RenderResponse rResponse)
                     throws PortletException, IOException, UnavailableException
   {
      rResponse.setContentType("text/html");
      PortletRequestDispatcher prd = getPortletContext()
         .getRequestDispatcher("/WEB-INF/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("/WEB-INF/jsp/edit.jsp");
      prd.include(rRequest, rResponse);
   }
}

protected void doHelp(RenderRequest rRequest, RenderResponse rResponse)
                   throws PortletException, IOException, UnavailableException
protected void doEdit(RenderRequest rRequest, RenderResponse rResponse)
                  throws PortletException, IOException, UnavailableException

Support for these modes must be declared in the HelloWorldJSPPortlet/WEB-INF/portlet.xml file. They are triggered when a user clicks on the respective icons in the portlet window titlebar, or through generated links within the portlet.

public void processAction(ActionRequest aRequest, ActionResponse aResponse)
               throws PortletException, IOException, UnavailableException
{
   String sYourname = (String) aRequest.getParameter("yourname");

   // do something

   aResponse.setRenderParameter("yourname", sYourname);
}

This method is triggered when a user clicks on an actionURL, which is defined in the HelloWorldJSPPortlet/WEB-INF/jsp/view.jsp file. This retrieves yourname from the HTML form, and passes it as a aResponse.setRenderParameter to the doView() method.

rResponse.setContentType("text/html");

As in the servlet world, you must declare what content-type the portlet will be responding in. Do this before starting to write content, or the portlet throws an exception.

protected void doView(RenderRequest rRequest, RenderResponse rResponse)
                  throws PortletException, IOException, UnavailableException

The doView implementation is responsible for dispatching to the appropriate JSP, HelloWorldJSPPortlet/WEB-INF/jsp/view.jsp or HelloWorldJSPPortlet/WEB-INF/jsp/view2.jsp, depending on the existence of the yourname parameter passed in from processAction.

5.2.2.4. JSP™ files and the Portlet Tag Library

The HelloWorldJSPPortlet/WEB-INF/jsp/view.jsp and HelloWorldJSPPortlet/WEB-INF/jsp/view2.jsp JSP™ files are included in the HelloWorldJSPPortlet portlet. The view.jsp file allows a user to input their name. This is then posted to the processAction method in the portlet class, which is set as a aResponse.setRenderParameter. The doView render method is invoked, which dispatches to the view2.jsp JSP:

The following is an example of the HelloWorldJSPPortlet/WEB-INF/jsp/view.jsp file:

<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %>

<portlet:defineObjects/>

<div align="center">
   This is a simple HelloWorld JSP Portlet. Type in a name and it will dispatch
   to the view2.jsp to print out your name.
   <br/>

   <form action="<portlet:actionURL><portlet:param name="page" value="mainview"/>
         </portlet:actionURL>" method="POST">
      Name:<br/>
      <input type="text" name="yourname"/>
   </form>
   <br/>
   You can also link to other pages, using a renderURL, like <a
      href="<portlet:renderURL><portlet:param name="yourname" value="Roy Russo">
            </portlet:param></portlet:renderURL>">this</a>.
</div>

<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %>

Define the portlet taglib. You do not need to bundle the portlet taglib - JBoss Portal handles this for you.

<portlet:defineObjects/>

Calling defineObjects makes available implicit objects in the JSP, such as renderRequest, actionRequest, and portletConfig.

<form action="<portlet:actionURL><portlet:param name="page" value="mainview"/>
      </portlet:actionURL>" method="POST">

A HTML form is created. This form posts to the URL defined by the portlet taglib. In this example, an actionURL is created, that activates the processAction method, which passes the input parameters from the form.

<a href="<portlet:renderURL><portlet:param name="yourname" value="Roy Russo">
</portlet:param></portlet:renderURL>">

You can create a link to the doView method by creating a renderURL, which passes the yourname parameter.

5.2.2.5. Building your JSP™ portlet

The HelloWorldJSPPortlet.zip file contains a pre-compiled helloworldjspportlet.war file; however, to manually build the helloworldjspportlet.war file:

  1. Change into the HelloWorldJSPPortlet/ directory, and remove the existing helloworldjspportlet.war file.

  2. If required, edit the HelloWorldJSPPortlet/src/main/org/jboss/portlet/hello/HelloWorldJSPPortlet.java file, and the application descriptors in the HelloWorldJSPPortlet/src/resources/helloworldjspportlet-war/WEB-INF/ directory.

  3. Change into HelloWorldJSPPortlet/ directory, and run the ant deploy command. On Linux, the output will be similar to the following:

Note: the directory names will be different for your system.

Expanding the helloworldjspportlet.war file allows you to deploy the portlet as an expanded directory, which makes development easier. As well, it gives you access to the application descriptors, resource files, JSF, and JSP™ pages. To expand the helloworldjspportlet.war file:

  1. If you do not have the HelloWorldJSPPortlet/helloworldjspportlet.war file, change into the HelloWorldJSPPortlet/ directory, and run the ant deploy command. This creates the helloworldjspportlet.war file.

  2. To expand the WAR file, change into the HelloWorldJSPPortlet/ directory, and run the ant explode command. On Linux, the output will be similar to the following:

Note: the directory names will be different for your system.

The ant explode command creates a directory structure such as the following:

The expanded WAR file and the application descriptors are located in the HelloWorldJSPPortlet/output/lib/exploded/helloworldjspportlet.war/WEB-INF/ directory.

5.2.2.6. Deploying your JSP™ portlet

If you did not expand the helloworldjspportlet.war file, copy the HelloWorldJSPPortlet/helloworldjspportlet.war file into the correct JBoss AS or JBoss EAP deploy/ directory. If you expanded the helloworldjspportlet.war file, copy the HelloWorldJSPPortlet/output/lib/exploded/helloworldjspportlet.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.

Performing this step on a running instance of JBoss AS or JBoss EAP, and JBoss Portal, triggers a hot-deploy of the portlet:

INFO  [TomcatDeployer] deploy, ctxPath=/helloworldjspportlet, 
warUrl=.../deploy/helloworldjspportlet.war/

To see the HelloWorldJSPPortlet, navigate to http://localhost:8080/portal/, or, if the default JBoss Portal page is already open, refresh the page. The HelloWorldJSPPortlet is added to the bottom of the default JBoss Portal page:

To re-deploy the portlet, for example, if you have made changes to any of the application descriptors, touch the $JBOSS_HOME/server/configuration/deploy/helloworldjspportlet.war/WEB-INF/web.xml file. This only works if you copied the HelloWorldJSPPortlet/output/lib/exploded/helloworldjspportlet.war/ directory into the JBoss AS or JBoss EAP deploy/ directory. On Linux, run the touch $JBOSS_HOME/server/configuration/deploy/helloworldjspportlet.war/WEB-INF/web.xml command to re-deploy the HelloWorldJSPPortlet.

Re-deploying the HelloWorldJSPPortlet produces output to the JBoss AS or JBoss EAP console, similar to the following:

INFO  [TomcatDeployer] undeploy, ctxPath=/helloworldjspportlet, 
warUrl=.../deploy/helloworldjspportlet.war/
INFO  [TomcatDeployer] deploy, ctxPath=/helloworldjspportlet, 
warUrl=.../deploy/helloworldjspportlet.war/

5.2.3. An example Sun™ JSF Reference Implementation (RI) portlet

5.2.3.1. Introduction

This section describes how to deploy a JSF portlet in JBoss Portal, using the Apache MyFaces JSF implementation in JBoss AS and JBoss EAP. Before proceeding, download the HelloWorldJSFSunRIPortlet from JBoss PortletSwap.

5.2.3.2. Package Structure

JBoss Portal requires certain descriptors to be included in a portlet WAR file. Some of these descriptors are defined by the JSR-168 Portlet Specification, and others are specific to JBoss Portal. Like a typical JSF application, the HelloWorldJSFSunRIPortlet package contains a faces-config.xml file that defines managed-beans, converters, validators, navigation rules, and so on. The following is an example of the directory structure of the HelloWorldJSFSunRIPortlet portlet:

To create the WEB-INF/ and META-INF/ directories, extract the helloworldjsfsunriportlet.war file.

Bundled Sun JSF RI

JBoss AS version 4.2.x and JBoss EAP bundle the Sun™ JSF RI libraries in the $JBOSS_HOME/server/default/deploy/jboss-web.deployer/jsf-libs/ directory. Therefore, you do not need to package the Sun JSF RI libraries with your portlet application.

5.2.3.3. Application Descriptors

Only the portlet.xml, faces-config.xml, and web.xml descriptors are described here. For more information about application descriptors, refer to Section 5.2.1.4, “Application Descriptors” and Section 6.2, “Portlet Descriptors”.

The following is an example of the HelloWorldJSFSunRIPortlet/WEB-INF/portlet.xml file. This file must adhere to its definition in the JSR-168 Portlet Specification. You may define more than one portlet application in this file:

<?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>
      <portlet-name>HelloWorldJSFPortlet</portlet-name>
      <portlet-class>com.sun.faces.portlet.FacesPortlet</portlet-class>
      <init-param>
         <name>com.sun.faces.portlet.INIT_VIEW</name>
         <value>/WEB-INF/jsp/index.jsp</value>
      </init-param>
      <supports>
         <mime-type>text/html</mime-type>
         <portlet-mode>view</portlet-mode>
      </supports>
      <portlet-info>
         <title>HelloWorld JSF Portlet</title>
      </portlet-info>
   </portlet>
</portlet-app>

<portlet-class>com.sun.faces.portlet.FacesPortlet</portlet-class>

This specifies that the com.sun.faces.portlet.FacesPortlet handles all requests and responses from the users. This class is part of the HelloWorldJSFSunRIPortlet/WEB-INF/lib/jsf-portlet.jar file.

<init-param>
   <name>com.sun.faces.portlet.INIT_VIEW</name>
   <value>/WEB-INF/jsp/index.jsp</value>
</init-param>

You must initialize the portlet with a default page to render, similar to a welcome page.

<supports>
    <mime-type>text/html</mime-type>
    <portlet-mode>view</portlet-mode>
</supports>

The <supports> element allows you to declare all of the markup types that a portlet supports in the render method. This is accomplished via the <mime-type> element, which is required for every portlet. The declared MIME types must match the capability of the portlet. As well, it allows you to pair which modes and window states are supported for each markup type. All portlets must support the view portlet mode, so this does not have to be declared. Use the <mime-type> element to define which markup type your portlet supports, which in this example, is text/html. This section tells the portal that it only outputs text and HTML, and that it only supports the view mode.

The following is an example HelloWorldJSFSunRIPortlet/WEB-INF/faces-config.xml file:

<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
   "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
   "http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
<faces-config>
   <managed-bean>
      <description>Basic UserBean</description>
      <managed-bean-name>user</managed-bean-name>
      <managed-bean-class>org.jboss.portlet.hello.bean.User</managed-bean-class>
      <managed-bean-scope>session</managed-bean-scope>
   </managed-bean>
   
   <navigation-rule>
      <navigation-case>
         <from-outcome>done</from-outcome>
         <to-view-id>/WEB-INF/jsp/result.jsp</to-view-id>
      </navigation-case>
   </navigation-rule>
</faces-config>

Without the faces-config.xml file, the application would work the same outside of the portlet as it would inside a portlet container. In this example, a basic user bean, <managed-bean-name>user</managed-bean-name>, and a navigation rule are defined, which handle the submission of the original form in the HelloWorldJSFSunRIPortlet/WEB-INF/jsp/index.jsp file.

The following is an example of the Faces Servlet and Faces Servlet Mapping sections from the HelloWorldJSFSunRIPortlet/WEB-INF/web.xml file:

<?xml version="1.0"?>
<!DOCTYPE web-app PUBLIC
   "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
   "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

    <!-- Faces Servlet -->
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>


    <!-- Faces Servlet Mapping -->
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
    </servlet-mapping>

</web-app>

For Sun JSF RI portlets, the Faces Servlet and Faces Servlet Mapping sections are required to associate files with the .jsf extension to the Apache MyFaces servlet.

Classes for the JSF-Portlet bridge are not included

Unlike Apache MyFaces, the classes for the JSF-Portlet bridge are not included in the JSF implementation, JBoss AS, or JBoss EAP. This library must be available in your application package. Navigate to the JSF-Portlet bridge webpage to download the JSF-Portlet bridge library.

5.2.3.4. Building your JSF portlet

The HelloWorldJSFSunRIPortlet.zip file contains a pre-compiled helloworldjsfsunriportlet.war file; however, to manually build the helloworldjsfsunriportlet.war file:

  1. Change into the HelloWorldJSFSunRIPortlet/ directory, and remove the existing helloworldjsfsunriportlet.war file.

  2. If required, edit the HelloWorldJSFSunRIPortlet/src/main/org/jboss/portlet/hello/bean/User.java file, and the application descriptors in the HelloWorldJSFSunRIPortlet/src/resources/helloworldjsfsunriportlet-war/WEB-INF/ directory.

  3. Change into HelloWorldJSFSunRIPortlet/ directory, and run the ant deploy command. On Linux, the output will be similar to the following:

Note: the directory names will be different for your system.

Expanding the helloworldjsfsunriportlet.war file allows you to deploy the portlet as an expanded directory, which makes development easier. As well, it gives you access to the application descriptors, resource files, JSF, and JSP pages. To expand the helloworldjsfsunriportlet.war file:

  1. If you do not have the HelloWorldJSFSunRIPortlet/helloworldjsfsunriportlet.war file, change into the HelloWorldJSFSunRIPortlet/ directory, and run the ant deploy command. This creates the helloworldjsfsunriportlet.war file.

  2. To expand the WAR file, change into the HelloWorldJSFSunRIPortlet/ directory, and run the ant explode command. On Linux, the output will be similar to the following:

Note: the directory names will be different for your system.

The expanded WAR file and the application descriptors are located in the HelloWorldJSFSunRIPortlet/output/lib/exploded/helloworldjsfsunriportlet.war/WEB-INF/ directory.

5.2.3.5. Deploying your JSF portlet

If you did not expand the helloworldjsfsunriportlet.war file, copy the HelloWorldJSFSunRIPortlet/helloworldjsfsunriportlet.war file into the correct JBoss AS or JBoss EAP deploy/ directory. If you expanded the helloworldjsfsunriportlet.war file, copy the HelloWorldJSFSunRIPortlet/output/lib/exploded/helloworldjsfsunriportlet.war/ directory into the correct JBoss AS or JBoss EAP deploy/ directory. For example, if you are using default JBoss AS profile, copy the WAR file or the expanded directory into the $JBOSS_HOME/server/default/deploy/ directory.

Performing this step on a running instance of JBoss AS or JBoss EAP, and JBoss Portal, triggers a hot-deploy of the portlet:

INFO  [TomcatDeployer] deploy, ctxPath=/helloworldjsfsunriportlet,
warUrl=.../tmp/deploy/tmp9138helloworldjsfsunriportlet-exp.war/

To see the HelloWorldJSFSunRIPortlet, navigate to http://localhost:8080/portal/, or, if the default JBoss Portal page is already open, refresh the page. The HelloWorldJSFSunRIPortlet is added to the bottom of the default JBoss Portal page:

To re-deploy the portlet, for example, if you have made changes to any of the application descriptors, touch the $JBOSS_HOME/server/configuration/deploy/helloworldjsfsunriportlet.war/WEB-INF/web.xml file. This only works if you copied the HelloWorldJSFSunRIPortlet/output/lib/exploded/helloworldjsfsunriportlet.war/ directory into the JBoss AS or JBoss EAP deploy/ directory. On Linux, run the touch $JBOSS_HOME/server/configuration/deploy/helloworldjsfsunriportlet.war/WEB-INF/web.xml command to re-deploy the HelloWorldJSFSunRIPortlet.

Re-deploying the HelloWorldJSFSunRIPortlet produces output to the JBoss AS or JBoss EAP console, similar to the following:

INFO  [TomcatDeployer] undeploy, ctxPath=/helloworldjsfsunriportlet, 
warUrl=.../deploy/helloworldjsfsunriportlet.war/
INFO  [TomcatDeployer] deploy, ctxPath=/helloworldjsfsunriportlet, 
warUrl=.../deploy/helloworldjsfsunriportlet.war/

5.2.4. An example Apache MyFaces JSF portlet

5.2.4.1. Introduction

This section describes how to deploy a JSF portlet in JBoss Portal, using the Apache MyFaces JSF implementation in JBoss AS and JBoss EAP. Before proceeding, download the HelloWorldJSFMyFaces42Portlet from JBoss PortletSwap.

Apache MyFaces can be used globally for the entire server, replacing the Sun JSF RI libraries, but the HelloWorldJSFMyFaces42Portlet uses its own libraries, but does not affect the application server.

5.2.4.2. Package Structure

JBoss Portal requires certain descriptors to be included in a portlet WAR file. Some of these descriptors are defined by the JSR-168 Portlet Specification, and others are specific to JBoss Portal. Like a typical JSF application, the HelloWorldJSFMyFaces42Portlet package contains a faces-config.xml file that defines managed-beans, converters, validators, navigation rules, and so on. The following is an example of the directory structure of the HelloWorldJSFMyFaces42Portlet portlet:

To create the WEB-INF/ and META-INF/ directories, extract the helloworldjsfmyfacesportlet.war file. The WEB-INF/lib/ directory must contain the Apache MyFaces libraries, along with the dependent libraries.

5.2.4.3. Application Descriptors

Only the portlet.xml, faces-config.xml, and web.xml descriptors are described here. For more information about application descriptors, refer to Section 5.2.1.4, “Application Descriptors” and Section 6.2, “Portlet Descriptors”.

The following is an example of the HelloWorldJSFMyFaces42Portlet/WEB-INF/portlet.xml file. This file must adhere to its definition in the JSR-168 Portlet Specification. You may define more than one portlet application in this file:

<?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>
      <portlet-name>HelloWorldJSFPortlet</portlet-name>
      <portlet-class>org.apache.myfaces.portlet.MyFacesGenericPortlet</portlet-class>
      <init-param>
         <name>default-view</name>
         <value>/WEB-INF/jsp/index.jsp</value>
      </init-param>
      <supports>
         <mime-type>text/html</mime-type>
         <portlet-mode>view</portlet-mode>
      </supports>
      <portlet-info>
         <title>HelloWorld JSF Portlet</title>
      </portlet-info>
   </portlet>
</portlet-app>

<portlet-class>org.apache.myfaces.portlet.MyFacesGenericPortlet</portlet-class>

This specifies that the org.apache.myfaces.portlet.MyFacesGenericPortlet handles all requests and responses from the users. Therefore, there is no need to develop a specific portlet class, as Apache MyFaces provides a generic implementation which bridges the JSF and portlet worlds.

<init-param>
   <name>default-view</name>
   <value>/WEB-INF/jsp/index.jsp</value>
</init-param>

You must initialize the portlet with a default page to render, similar to a welcome page.

<supports>
    <mime-type>text/html</mime-type>
    <portlet-mode>view</portlet-mode>
</supports>

The <supports> element allows you to declare all of the markup types that a portlet supports in the render method. This is accomplished via the <mime-type> element, which is required for every portlet. The declared MIME types must match the capability of the portlet. As well, it allows you to pair which modes and window states are supported for each markup type. All portlets must support the view portlet mode, so this does not have to be declared. Use the <mime-type> element to define which markup type your portlet supports, which in this example, is text/html. This section tells the portal that it only outputs text and HTML, and that it only supports the view mode.

Adding Functionality to an Apache MyFaces JSF portlet

To add functionality to an Apache MyFaces JSF portlet, sub-class it and create your own class.

The following is an example HelloWorldJSFMyFaces42Portlet/WEB-INF/faces-config.xml file:

<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
  "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
  "http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
<faces-config>
   <managed-bean>
      <description>Basic UserBean</description>
      <managed-bean-name>user</managed-bean-name>
      <managed-bean-class>org.jboss.portlet.hello.bean.User</managed-bean-class>
      <managed-bean-scope>session</managed-bean-scope>
   </managed-bean>
   
   <navigation-rule>
      <navigation-case>
      <from-outcome>done</from-outcome>
      <to-view-id>/WEB-INF/jsp/result.jsp</to-view-id>
      </navigation-case>
   </navigation-rule>
</faces-config>

Without the faces-config.xml file, the application would work the same outside of the portlet as it would inside a portlet container. In this example, a basic user bean, <managed-bean-name>user</managed-bean-name>, and a navigation rule are defined, which handle the submission of the original form in the HelloWorldJSFMyFaces42Portlet/WEB-INF/jsp/index.jsp file.

The following is an example of the <context-parm> element from the HelloWorldJSFMyFaces42Portlet/WEB-INF/web.xml file:

<context-param>
   <param-name>org.jboss.jbossfaces.WAR_BUNDLES_JSF_IMPL</param-name>
   <param-value>true</param-value>
</context-param>

These extra parameters let the application server know that the portlet embeds its own libraries. This avoids collision with the Sun JSF RI libraries bundled with JBoss AS and JBoss EAP. For more information, refer to the JBossFaces page on the JBoss Wiki.

5.2.4.4. Building your Apache MyFaces JSF portlet

The HelloWorldJSFMyFaces42Portlet.zip file contains a pre-compiled helloworldjsfmyfacesportlet.war file; however, to manually build the helloworldjsfmyfacesportlet.war file:

  1. Change into the HelloWorldJSFMyFaces42Portlet/ directory, and remove the existing helloworldjsfmyfacesportlet.war file.

  2. If required, edit the HelloWorldJSFMyFaces42Portlet/src/main/org/jboss/portlet/hello/bean/User.java file, and the application descriptors in the HelloWorldJSFMyFaces42Portlet/src/resources/helloworldjsfmyfacesportlet-war/WEB-INF/ directory.

  3. Change into HelloWorldJSFMyFaces42Portlet/ directory, and run the ant deploy command. On Linux, the output will be similar to the following:

Note: the directory names will be different for your system.

Expanding the helloworldjsfmyfacesportlet.war file allows you to deploy the portlet as an expanded directory, which makes development easier. As well, it gives you access to the application descriptors, resource files, JSF, and JSP pages. To expand the helloworldjsfmyfacesportlet.war file:

  1. If you do not have the HelloWorldJSFMyFaces42Portlet/helloworldjsfmyfacesportlet.war file, change into the HelloWorldJSFMyFaces42Portlet/ directory, and run the ant deploy command. This creates the helloworldjsfmyfacesportlet.war file.

  2. To expand the WAR file, change into the HelloWorldJSFMyFaces42Portlet/ directory, and run the ant explode command. On Linux, the output will be similar to the following:

Note: the directory names will be different for your system.

The expanded WAR file and the application descriptors are located in the HelloWorldJSFMyFaces42Portlet/output/lib/exploded/helloworldjsfmyfacesportlet.war/WEB-INF/ directory.

5.2.4.5. Deploying your Apache MyFaces JSF portlet

If you did not expand the helloworldjsfmyfacesportlet.war file, copy the HelloWorldJSFMyFaces42Portlet/helloworldjsfmyfacesportlet.war file into the correct JBoss AS or JBoss EAP deploy/ directory. If you expanded the helloworldjsfmyfacesportlet.war file, copy the HelloWorldJSFMyFaces42Portlet/output/lib/exploded/helloworldjsfmyfacesportlet.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.

Performing this step on a running instance of JBoss AS or JBoss EAP, and JBoss Portal, triggers a hot-deploy of the portlet.

To see the HelloWorldJSFMyFaces42Portlet, navigate to http://localhost:8080/portal/, or, if the default JBoss Portal page is already open, refresh the page. The HelloWorldJSFMyFaces42Portlet is added to the bottom of the default JBoss Portal page:

To re-deploy the portlet, for example, if you have made changes to any of the application descriptors, touch the $JBOSS_HOME/server/configuration/deploy/helloworldjsfmyfacesportlet.war/WEB-INF/web.xml file. This only works if you copied the HelloWorldJSFMyFaces42Portlet/output/lib/exploded/helloworldjsfmyfacesportlet.war/ directory into the JBoss AS or JBoss EAP deploy/ directory. On Linux, run the following command to re-deploy the HelloWorldJSFMyFaces42Portlet:

touch $JBOSS_HOME/server/configuration/deploy/helloworldjsfmyfacesportlet.war/WEB-INF/web.xml

Chapter 6. XML Descriptors

Roy Russo

6.1. Changes from previous Releases

The previous releases of JBoss Portal did not have an external schema to validate XML descriptors; however, they were internally validated by the portal. Since JBoss Portal 2.6, a Document Type Definition (DTD) has been provided to validate descriptors.

To use the 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/configuration/deploy/jboss-portal.sar/dtd/ directory.

6.1.1. The JBoss Portlet 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.

6.1.2. The JBoss Portlet Instance DTD

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>

6.1.3. The JBoss Portal Object DTD

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 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.

<!ELEMENT property (name,value)>

A generic string property.

<!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>

6.1.4. The JBoss Portal App DTD

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 <![CDATA[<!ELEMENT jboss-app (app-name?)>

<!DOCTYPE jboss-app PUBLIC
   "-//JBoss Portal//DTD JBoss Web Application 2.6//EN"
   "http://www.jboss.org/portal/dtd/jboss-app_2_6.dtd">

<!ELEMENT app-name (#PCDATA)>

When a web application is deployed, the context path under which it is deployed is taken as the application name. The application name value in the <app-name> element overrides it. When a component references a portlet, it needs to reference the application too, and if the portlet application WAR file is renamed, the reference is no longer valid; therefore, the <app-name> element is used to have an application name that does not depend upon the context path, under which the application is deployed.

6.2. Portlet Descriptors

The following sections describe the descriptors that define portal objects, such as portals, pages, portlet instances, windows, and portlets. Refer to Section 5.2, “Tutorials” and Section 6.4, “Descriptor Examples” for examples on using these descriptors within a portlet application.

6.2.1. *-object.xml Descriptors

The *-object.xml descriptors define portal instances, pages, windows, and the window layout. As well, themes and layouts for specific portal instances, pages, and windows, can be defined. The following example defines a portlet window being added to the default page, in the default portal. For advanced functionality using these descriptors, refer to Section 6.4, “Descriptor Examples”:

<?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>HelloWorldJSPPortletWindow</window-name>
         <instance-ref>HelloWorldJSPPortletInstance</instance-ref>
         <region>center</region>
         <height>1</height>
      </window>
   </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>...</deployment>

    The <deployment> element specifies object deployments, such as portals, pages, windows, and so on.

  • <if-exists>...</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 maintains the existing object deployment, or creates a new one if it does not exist.

  • <parent-ref>...</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.

    In the example above, a window is defined, and assigned to default.default. This means the window appears on the default page, in the default portal.

  • <window>...</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>...</window-name>

    The <window-name> element defines the unique name given to a portlet window. This can be named anything.

  • <instance-ref>...</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.

The previous *-object.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:

Are *-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.

6.2.2. The portlet-instances.xml Descriptor

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:

Is the 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.

6.2.3. The jboss-portlet.xml Descriptor

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.

6.2.3.1. Injecting Header Content

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.

6.2.3.2. Injecting Services in the portlet Context

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);

6.2.3.3. Defining extra portlet Information

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.

6.2.3.4. Portlet Session Replication in a Clustered Environment

For information about portlet session replication in clustered environments, refer to Section 13.5, “Portlet Session Replication”.

Is the 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.

6.2.4. The portlet.xml Descriptor

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.

The portlet.xml Example

This portlet.xml example is not a replacement for what is covered in the JSR-168 Portlet Specification.

6.3. JBoss Portal Descriptors

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.

6.3.1. Datasource Descriptors (portal-*-ds.xml)

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.

6.3.1.1. Datasource Descriptors included in Binary releases

Several template Datasource descriptors are included in the binary and bundled distributions of JBoss Portal. They are commonly located in the jboss-portal-version/setup/ directory:

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

6.3.1.2. Building Datasource Descriptors from Source

To build the Datasource descriptors from source:

  1. Obtain the JBoss Portal source code: Section 2.3, “Installing from the Sources”.

  2. Configure the JBOSS_HOME environment variable: Section 2.3.2.2, “Operating System Environment Settings”.

  3. 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”.

  4. 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.

6.3.2. Portlet Debugging (jboss-portal.sar/conf/config.xml)

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.

6.3.3. Log in to Dashboard

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>

6.4. Descriptor Examples

6.4.1. Defining a new Portal Page

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:

  1. Download the HelloWorldPortalPage portlet.

  2. Unzip the HelloWorldPortalPage ZIP file.

  3. To expand the WAR file, which gives you access to the XML descriptors, change into the HelloWorldPortalPage/ directory, and run the ant explode command.

  4. 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>

6.4.2. Defining a new Portal Instance

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:

  1. Download the HelloWorldPortal portlet.

  2. Unzip the HelloWorldPortal ZIP file.

  3. To expand the WAR file, which gives you access to the XML descriptors, change into the HelloWorldPortal/ directory, and run the ant explode command.

  4. 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.

Portal Instance default Page

For a portal instance to be accessible via a Web browser, you must define a page named default.

Chapter 7. Portal URLs

Julien Viet

Thomas Heute

Roy Russo

7.1. Introduction to Portals

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.

7.2. Accessing a Portal

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/portal-name/ points to the default page of the portal-name portal.

7.3. Accessing a Page

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/page-name renders the page-name page.

7.4. Accessing CMS Content

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.

Chapter 8. Error Handling Configuration

The JBoss Portal request pipeline allows fine-grained, dynamic configuration of how JBoss Portal behaves when errors occur during runtime.

8.1. Error Types

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.

8.2. Control Policies

If an error occurs, the request control-flow changes according to the configuration. This configuration is known as the control policy.

8.2.1. Policy Delegation and Cascading

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.

8.2.2. Default Policy

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

8.2.3. Portal Policy

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.

8.2.4. Page Policy

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.

8.3. Configuration using XML Descriptors

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.

8.3.1. Portal Policy Properties

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 8.1. 

Property NameDescriptionPossible Values
control.portal.access_deniedwhen access is deniedignore and jsp
control.portal.unavailablewhen a resource is unavailableignore and jsp
control.portal.not_foundwhen a resource is not foundignore and jsp
control.portal.internal_errorwhen an unexpected error occursignore and jsp
control.portal.errorwhen an expected error occursignore and jsp
control.portal.resource_urithe path to the JSP used for redirectionsa 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>

8.3.2. Page Policy Properties

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 8.2. 

Property nameDescriptionPossible values
control.page.access_deniedwhen access is deniedignore, jsp and hide
control.page.unavailablewhen a resource is unavailableignore, jsp and hide
control.page.not_foundwhen a resource is not foundignore, jsp and hide
control.page.internal_errorwhen an unexpected error occursignore, jsp and hide
control.page.errorwhen an expected error occursignore, jsp and hide
control.page.resource_urithe path to the JSP used for redirectionsignore, 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>

Page Property Inheritance for Objects

When page properties are configured for objects that use the portal type, the properties are inherited by pages in that portal.

8.4. Using JSP™ to Handle Errors

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 8.3. 

Attribute NameAttribute DescriptionAttribute Value
org.jboss.portal.control.ERROR_TYPEthe error typepossible values are ACCESS_DENIED, UNAVAILABLE, ERROR, INTERNAL_ERROR, and NOT_FOUND
org.jboss.portal.control.CAUSEa cause which is thrown, that can be nullthe object is a subclass of java.lang.Throwable
org.jboss.portal.control.MESSAGEan error message that can be nulltext

JSP Location

The JavaServer Pages must be located in the jboss-portal.sar/portal-core.war/ web application.

8.5. Configuration using the Portal Management Application

The error handling policy can be configured via the portal management application. To access the portal management application:

  1. Use a Web browser to navigate to http://localhost:8080/portal.

  2. Click the Login button on the top right-hand of the welcome page, and log in as the admin user.

  3. 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.

  4. 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.

Chapter 9. Content Integration

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.

Note

We do not advocate to avoid the usage portlet preferences, we rather advocate that content configuration managed at the portal level simplifies the configuration: it helps to make content a first class citizen of the portal instead of having an intermediary portlet that holds the content for the portal. The portlet preferences can still be used to configure how content is displayed to the user.

The portal uses portlets to configure content

The portal references directly the content and use portlet to interact with content

9.1. Window content

The content of a window is defined by

  • The content URI which is the resource that the window is pointing to. It is an arbitrary string that the portal cannot interpret and is left up to the content provider to interpret.
  • The window content type which defines how the portal interpret the window content
    • The default content type is for portlets and has the value portlet. In this case the content URI is the portlet instance id.
    • The CMS content type allows to integrate content from the CMS at the page and it has the value cms. For that content type, the content URI is the CMS file path.
  • The content parameters which are a set of additional key/value string pairs holding state that is interpreted by the content provider.

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 168 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.

9.2. Content customization

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 168 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.

Example of content customization - CMS Portlet

9.3. Content Driven Portlet

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.

9.3.1. Displaying content

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 render parameters 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 render parameters values are the key/value pairs that form the content properties and the resource URI is available under the uri parameter name.

9.3.2. Configuring content

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:

  • The portal needs to configure a new content item for a new window. In that use case the portal will not send special render parameters to the portlet and the initial set of render parameters will be empty. The portlet can then use render parameters in order to provide navigation in the content repository. For example the portlet can navigate the CMS tree and store the current CMS path in the render parameters. Whenever the portlet has decided to tell the portal that content has been selected by the user it needs to use an action URL with a special set of parameters:
    • content.action.select equals to any value
    • content.uri equals to the content URI
    • content.param. used as prefix to configure content parameters
  • The second use case happens when the portal needs to edit existing content. In such situation everything works as explained before except that the initial set of render parameters of the portlet will be prepopulated with the content uri URI and parameters.

9.3.3. Step by step example of a content driven portlet

9.3.3.1. The Portlet skeleton

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");

   /** The select_content mode. */
   public static final PortletMode SELECT_CONTENT_MODE = new PortletMode("select_content");

   ...

}

9.3.3.2. Overriding the dispatch method

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()) || 
       SELECT_CONTENT_MODE.equals(req.getPortletMode()))
   {
      doEditContent(req, resp);
   }
   else
   {
      super.doDispatch(req, resp);
   }
}

9.3.3.3. Utilities methods

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;
         }
      }
   };

9.3.3.4. The editor

The editor is probably the longest part of the portlet. It tries to stay simple though and goes directly to the point.

Content editor of FSContentDrivenPortlet in action
protected void doEditContent(RenderRequest req, RenderResponse resp)
                  throws PortletException, PortletSecurityException, IOException
{
   // Get the uri value optionally provided by the portal
   String uri = req.getParameter("content.uri");

   // Get the working directory directory
   File workingDir;
   if (uri != null)
   {
      workingDir = getFile(uri).getParentFile();
   }
   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("content.uri", getContentURI(child));
         writer.print("<li><a href=\"" + selectFileURL + "\">" + child.getName() +
                      "</a></li>");
      }
   }
   writer.print("</ul><br/>");

   //
   writer.close();
}

9.3.3.5. Viewing content at runtime

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();
}

9.3.3.6. Hooking the portlet into the portal

Management portlet with filesystem content type enabled

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.

<?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>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.portlet.test.FSContentDrivenPortlet</portlet-class>
      <supports>
         <mime-type>text/html</mime-type>
      </supports>
      <portlet-info>
         <title>File Portlet</title>
         <keywords>sample,test</keywords>
      </portlet-info>
   </portlet>
   ...
</portlet-app>

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

Warning

You don't need to add the listener class into your war file. As it is provided by the portal it will always be available.

9.4. Configuring window content in deployment 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>
Final effect - portal window with FSContentDrivenPortlet

Note

How to configure CMS file this way is covered in the CMS chapter: Section 21.3, “CMS content”

Chapter 10. Widget Integration

Emanuel Muckenhuber

10.1. Introduction

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'.

10.2. Widget portlet configuration

It is possible to modify certain behavior of caching and fetching widgets by changing the init-param values of the portlet.

  • connectionTimeout

    Connection timeout used for the directory lookup in milliseconds.

  • widgetExpiration

    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.

  • queryExpiration

    Times in minutes for which a directory query should be cached. After this time the cached query information will be deleted.

  • fetchWidgetsOnDirectoryLookup

    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:

  • jboss-portal.sar/portal-widget.war/WEB-INF/portlet.xml (for google gadgets)
  • or jboss-portal.sar/portal-widget-netvibes.war/WEB-INF/portlet.xml (for netvibes widgets).

...
   <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.

Chapter 11. Portlet Modes

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.

11.1. 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.

11.1.1. Portlet configuration

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>

11.1.2. Declarative instance security configuration

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>
...

11.1.3. Instance security configuration with the administration portlet

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

Chapter 12. Portal API

Julien Viet

Thomas Heute

12.1. Introduction

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

Note

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.

12.2. Portal URL

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.

12.3. Portal session

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.

12.4. Portal runtime context

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.

12.5. Portal nodes

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();
   ...
}

12.6. Portal navigational state

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

12.7. Portal events

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.

Note

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.

12.7.1. Portal node events

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.

12.7.1.1. Portal node event propagation model

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

12.7.1.2. Portal node event listener

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.

12.7.1.3. Portal node event context

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.

12.7.2. Portal session events

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

12.7.3. Portal user events

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

12.8. Examples

The events mechanism is quite powerful, in this section of the chapter we will see few simple examples to explain how it works.

12.8.1. UserAuthenticationEvent example

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.

12.8.2. Achieving Inter Portlet Communication with the events mechanism

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.

Note

The portlet 2.0 specification (JSR 286) will cover Inter Portlet Communication so that portlets using it can work with different portal vendors.

12.8.3. Link to other pages

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.

Samples

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.

Chapter 13. Clustering Configuration

Roy Russo

This section covers configuring JBoss Portal for a clustered environment.

13.1. Introduction

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:

    1. Used to make the deployer a singleton on the cluster, in order to avoid concurrency issues when deploying the various *-object.xml files. Without that, each node would try to create the same objects in the database when it deploys an archive containing such descriptors.
    2. Used with JCR. The Apache Jackrabbit server is not able to run in a cluster by itself, therefore we make a singleton on the cluster. This provides HA-CMS, which is similar to the current HA JBossMQ provided in JBoss AS.

  • 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.

Note

JBoss Clustering details can be found in the Wiki or the clustering documentation.

13.2. Considerations

When you want to run JBoss Portal on a cluster there are a few things to keep in mind:

  • Deploy the portal under the all application server configuration as it contains the clustering services that is leveraged by JBoss Portal.
  • All the portal instances have to use the same datasource : the database is used to store the portal persistent state like pages. If you don't use a shared database then you will have consistency problems.

13.3. JBoss Portal Clustered Services

13.3.1. Portal Session Replication

The portal associates with each user a http session in order to keep specific objects such as:

  • Navigational state : this is mainly the state of different portlet windows that the user will manipulate during its interactions with the portal. For instance a maximized portlet window with specific render parameters.
  • WSRP objects : the WSRP protocol can require to provide specific cookies during interactions with a remote portlet.

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>

13.3.2. Hibernate clustering

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 :

  • jboss-portal.sar/conf/hibernate/user/hibernate.cfg.xml
  • jboss-portal.sar/conf/hibernate/instances/hibernate.cfg.xml
  • jboss-portal.sar/conf/hibernate/portal/hibernate.cfg.xml
  • jboss-portal.sar/conf/hibernate/portlet/hibernate.cfg.xml

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.

13.3.3. Identity clustering

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.

13.3.4. CMS clustering

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 to cache CMS content cluster wide.

13.4. Setup

We are going to outline how to setup a two node cluster on the same machine in order to test JBoss Portal HA. The only missing part from the full fledged setup is the addition of a load balancer in front of Apache Tomcat. However a lot of documentation exist on the subject. A detailed step by step setup of Apache and mod_jk is available from the JBoss Wiki.

As we need two application servers running at the same time, we must avoid any conflict. For instance we will need Apache Tomcat to bind its socket on two different ports otherwise a network conflict will occur. We will leverage the service binding manager this chapter of the JBoss AS documentation.

The first step is to copy the all configuration of JBoss into two separate configurations that we name ports-01 and ports-02 :

>cd $JBOSS_HOME/server
>cp -r all ports-01
>cp -r all ports-02

Edit the file $JBOSS_HOME/server/ports-01/conf/jboss-service.xml and uncomment the service binding manager :

<mbean code="org.jboss.services.binding.ServiceBindingManager"
   name="jboss.system:service=ServiceBindingManager">
   <attribute name="ServerName">ports-01</attribute>
   <attribute name="StoreURL">
   ${jboss.home.url}/docs/examples/binding-manager/sample-bindings.xml</attribute>
   <attribute name="StoreFactoryClassName">org.jboss.services.binding.XMLServicesStoreFactory</attribute>
</mbean>

Edit the file $JBOSS_HOME/server/ports-02/conf/jboss-service.xml, uncomment the service binding manager and change the value ports-01 into ports-02:

<mbean code="org.jboss.services.binding.ServiceBindingManager"
   name="jboss.system:service=ServiceBindingManager">
   <attribute name="ServerName">ports-02</attribute>
   <attribute name="StoreURL">
   ${jboss.home.url}/docs/examples/binding-manager/sample-bindings.xml</attribute>
   <attribute name="StoreFactoryClassName">
   org.jboss.services.binding.XMLServicesStoreFactory</attribute>
</mbean>

Setup a database that will be shared by the two nodes and obviously we cannot use an embedded database. For instance using postgresql we would need to copy the file portal-postgresql-ds.xml into $JBOSS_HOME/server/ports-01/deploy and $JBOSS_HOME/server/ports-02/deploy.

Copy JBoss Portal HA to the deploy directory of the two configurations.

Note

To improve CMS performance JBoss Cache is leveraged to cache the content cluster wide. We recommend that you use the following version of JBoss Cache for best performance:

  • JBoss Cache 1.4.0.SP1 and above
  • JGroups 2.2.7 or 2.2.8

When building from source the following command: {core}/build.xml deploy-ha automatically upgrades your JBoss Cache version.

Alternative: If upgrading your JBoss Cache version is not an option, the following configuration change is needed in the jboss-portal-ha.sar/portal-cms.sar/META-INF/jboss-service.xml. Replace the following configuration in the cms.pm.cache:service=TreeCache Mbean:

<!--
   Configuring the PortalCMSCacheLoader
   CacheLoader configuration for 1.4.0
-->
<attribute name="CacheLoaderConfiguration">
   <config>
       <passivation>false</passivation>
       <preload></preload>
       <shared>false</shared>
       <cacheloader>
           <class>org.jboss.portal.cms.hibernate.state.PortalCMSCacheLoader</class>
           <properties></properties>
           <async>false</async>
           <fetchPersistentState>false</fetchPersistentState>
           <ignoreModifications>false</ignoreModifications>
       </cacheloader>
   </config>
</attribute>
               

with the following configuration:

<!--
   Configuring the PortalCMSCacheLoader
   CacheLoader configuratoon for 1.2.4SP2
-->
<attribute name="CacheLoaderClass">org.jboss.portal.cms.hibernate.state.PortalCMSCacheLoader
</attribute>
<attribute name="CacheLoaderConfig" replace="false"></attribute>
<attribute name="CacheLoaderPassivation">false</attribute>
<attribute name="CacheLoaderPreload"></attribute>
<attribute name="CacheLoaderShared">false</attribute>
<attribute name="CacheLoaderFetchTransientState">false</attribute>
<attribute name="CacheLoaderFetchPersistentState">false</attribute>
<attribute name="CacheLoaderAsynchronous">false</attribute>        

Finally we can start both servers, open two shells and execute :

>cd $JBOSS_HOME/bin
>sh run.sh -c ports-01

>cd $JBOSS_HOME/bin
>sh run.sh -c ports-02

13.5. Portlet Session Replication

Web containers offer the capability to replicate sessions of web applications. In the context of a portal using portlets the use case is different. The portal itself is a web application that benefits of web application session replication. We have to make the distinction between local or remote portlets :

  • Local portlets are web applications deployed in the same virtual machine as the portal web application. At runtime the access to a portlet is done using the mechanism of request dispatching. The portlet session is actually a mere wrapper of the underlying http session of the web application in which the portlet is deployed.
  • Remote portlets are accessed using a web service, we will not cover the replication in this chapter.

The servlet specification is very loose on the subject of replication and does not state anything about the replication of sessions during a dispatched request. JBoss Portal offers a portlet session replication mechanism that leverages the usage of the portal session instead which has several advantages

  • Replicate only the portlet that requires it.
  • Portal session replication is just web application replication and is very standard.

There are, however, some limitations. For example, you can only replicate portlet-scoped attributes of a portlet session. This means that any application-scoped attribute are not replicated.

13.5.1. JBoss Portal configuration

The mandatory step to make JBoss Portal able to replicate portlet sessions is to configure the portal web application to be distributed as explained in Section 13.3.1, “Portal Session Replication”

13.5.2. Portlet configuration

In order to activate portlet session replication you need to:

  • Add a Portal-specific listener class to the /WEB-INF/web.xml file of your portlet web application
  • Configure your portlet to be distributed in the /WEB-INF/jboss-portlet.xml file

<web-app>
   ...
   <listener>
      <listener-class> org.jboss.portal.portlet.session.SessionListener </listener-class>
   </listener>
   ...
</web-app>

Example web.xml

<portlet-app>
   ...
   <portlet>
      <portlet-name>YourPortlet</portlet-name>
      ...
      <session-config>
         <distributed>true</distributed>
      </session-config>
      ...
   </portlet>
   ...
</portlet-app>

Configure YourPortlet to be replicated in jboss-portlet.xml

13.5.3. Limitations

As we noted above there are advantages as well as limitations to the clustering configuration

  • You can only replicate portlet scoped attributes of a portlet. The main reason of this is to keep consistency with the session state. If accessing a portlet would trigger replication of application scoped attribute during the rendering of a page then another portlet on the same page could use this attribute for generating its markup. Then the state seen by this second portlet would not necessarily be the same depending on the order in which the portlets on this page are rendered.
  • Mutable objects need an explicit call to setAttribute(String name, Object value) on the portlet session object in order to trigger replication by the container.

public void processAction(ActionRequest req, ActionResponse resp)
               throws PortletException, IOException
{
   ...
   if ("addItem".equals(action))
   {
      PortletSession session = req.getPortletSession();
      ShoppingCart cart = (PortletSession)session.getAttribute("cart");
      cart.addItem(item);

      // Perform an explicit set in order to signal to the container that the object
      // state has changed
      session.setAttribute("cart", cart);
   }
   ...
}

Chapter 14. Web Services for Remote Portlets (WSRP)

Julien Viet

14.1. Introduction

The Web Services for Remote Portlets specification defines a web service interface for accessing and interacting with interactive presentation-oriented web services. It has been produced through the efforts of the Web Services for Remote Portlets (WSRP) OASIS Technical Committee. It is based on the requirements gathered and on the concrete proposals made to the committee.

Scenarios that motivate WSRP functionality include:

  • Content hosts, such as portal servers, providing Portlets as presentation-oriented web services that can be used by aggregation engines.
  • Aggregating frameworks, including portal servers, consuming presentation-oriented web services offered by content providers and integrating them into the framework.

More information on WSRP can be found on the official website for WSRP. We suggest reading the primer for a good, albeit technical, overview of WSRP.

14.2. Level of support in JBoss Portal

The WSRP Technical Committee defined WSRP Use Profiles to help with WSRP interoperability. We will refer to terms defined in that document in this section.

JBoss Portal provides a Simple level of support for our WSRP Producer except that out-of-band registration is not currently handled. We support in-band registration and persistent local state (which are defined at the Complex level).

On the Consumer side, JBoss Portal provides a Medium level of support for WSRP, except that we only handle HTML markup (as Portal itself doesn't handle other markup types). We do support explicit portlet cloning and we fully support the PortletManagement interface.

As far as caching goes, we have Level 1 Producer and Consumer. We support Cookie handling properly on the Consumer and our Producer requires initialization of cookies (as we have found that it improved interoperabilty with some consumers). We don't support custom window states or modes, as Portal doesn't either. We do, however, support CSS on both the Producer (though it's more a function of the portlets than inherent Producer capability) and Consumer.

While we provide a complete implementation of WSRP 1.0, we do need to go through the Conformance statements and perform more interoperability testing (an area that needs to be better supported by the WSRP Technical Committee and Community at large).

14.3. Deploying JBoss Portal's WSRP services

JBoss Portal provides a complete support of WSRP 1.0 standard interfaces and offers both consumer and producer services. WSRP support is provided by the portal-wsrp.sar service archive, included in the main jboss-portal.sar service archive, if you've obtained JBoss Portal from a binary distribution. If you don't intend on using WSRP, we recommend that you remove portal-wspr.sar from the main jboss-portal.sar service archive.

If you've obtained the source distribution of JBoss Portal, you need to build and deploy the WSRP service separately. Please follow the instructions on how to install JBoss Portal from the sources. Once this is done, navigate to JBOSS_PORTAL_HOME_DIRECTORY/wsrp and type: build deploy At the end of the build process, portal-wsrp.sar is copied to JBOSS_HOME/server/default/deploy.

14.3.1. Considerations to use WSRP when running Portal on a non-default port or hostname

If you have modified the port number on which Portal runs or bound your Application Server to a specific host name, you will also need update the port and/or hostname information for WSRP as found on JBoss Portal's wiki.

14.3.2. Considerations to use WSRP with SSL

It is possible to use WSRP over SSL for secure exchange of data. Please refer to the instructions on how to do so from JBoss Portal's wiki.

14.4. Making a portlet remotable

JBoss Portal does NOT, by default, expose local portlets for consumption by remote WSRP consumers. In order to make a portlet remotely available, it must be made "remotable" by adding a remotable element to the jboss-portlet.xml deployment descriptor for that portlet. If a jboss-portlet.xml file does not exist, one must be added to the WEB-INF folder of the web application containing the portlet.

In the following example, the "BasicPortlet" portlet is specified as being remotable. The remotable element is optional.

Example 14.1. 

<?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>BasicPortlet</portlet-name>
      <remotable>true</remotable>
   </portlet>
</portlet-app>

It is also possible to specify that all the portlets declared within a given jboss-portlet.xml file have a specific "remotable" status by default. This is done by adding a single remotable element to the root portlet-app element. Usually, this feature will be used to remotely expose several portlets without having to specify the status for all the declared portlets. Let's look at an example:

Example 14.2. 

<?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>
   <remotable>true</remotable>
   <portlet>
      <portlet-name>RemotelyExposedPortlet</portlet-name>
      ...
   </portlet>
   <portlet>
      <portlet-name>NotRemotelyExposedPortlet</portlet-name>
      <remotable>false</remotable>
      ...
   </portlet>
</portlet-app>
         

In the example above, we defined two portlets with a default "remotable" status set to true. This means that all portlets defined in this descriptor are, by default, exposed remotely by JBoss Portal's WSRP producer. Note, however, that it is possible to override the default behavior by adding a remotable element to a portlet description. In that case, the "remotable" status defined by the portlet takes precedence over the default. In the example above, the RemotelyExposedPortlet inherits the "remotable" status defined by default since it does not specify a remotable element in its description. The NotRemotelyExposedPortlet, however, overrides the default behavior and is not remotely exposed. Note that in the absence of a top-level remotable element, portlets are NOT remotely exposed.

14.5. Consuming JBoss Portal's WSRP portlets from a remote Consumer

WSRP Consumers vary a lot as far as how they are configured. Most of them require that you either specify the URL for the Producer's WSDL definition or the URLs for the individual endpoints. Please refer to your Consumer's documentation for specific instructions. For instructions on how to do so in JBoss Portal, please refer to Section 14.6, “Consuming remote WSRP portlets in JBoss Portal”.

JBoss Portal's Producer is automatically set up when you deploy a portal instance with the WSRP service. You can access the WSDL file at http://{hostname}:{port}/portal-wsrp/MarkupService?wsdl. You can access the endpoint URLs at:

  • http://{hostname}:{port}/portal-wsrp/ServiceDescriptionService
  • http://{hostname}:{port}/portal-wsrp/MarkupService
  • http://{hostname}:{port}/portal-wsrp/RegistrationService
  • http://{hostname}:{port}/portal-wsrp/PortletManagementService

The default hostname is localhost and the default port is 8080.

14.6. Consuming remote WSRP portlets in JBoss Portal

14.6.1. Overview

To be able to consume WSRP portlets exposed by a remote producer, JBoss Portal's WSRP consumer needs to know how to access that remote producer. One can configure access to a remote producer using WSRP Producer descriptors. Alternatively, a portlet is provided to configure remote producers.

Once a remote producer has been configured, it can be made available in the list of portlet providers in the Management portlet on the Admin page of JBoss Portal. You can then examine the list of portlets that are exposed by this producer and configure the portlets just like you would for local portlets.

JBoss Portal's default configuration exposes some of the sample portlets for remote consumption. As a way to test the WSRP service, a default consumer has been configured to consume these portlets. To make sure that the service indeed works, check that there is a portlet provider with the self identifier in the portlet providers list in the Management portlet of the Admin page. All local portlets marked as remotable are exposed as remote portlets via the self portlet provider so that you can check that they work as expected with WSRP. The portal-wsrp.sar file contains a WSRP Producer descriptor (default-wsrp.xml) that configures this default producer. This file can be edited or removed if needed.

14.6.2. Configuring a remote producer walk-through

Let's work through the steps of defining access to a remote producer so that its portlets can be consumed within JBoss Portal. We will configure access to BEA's public WSRP producer. We will first examine how to do so using the configuration portlet. We will then show how the same result can be accomplish with a producer descriptor.

14.6.2.1. Using the configuration portlet

As of Portal 2.6, a configuration portlet is provided to configure access to remote WSRP Producers grahically. You can access it at http://{hostname}:{port}/portal/auth/portal/admin/WSRP or by logging in as a Portal administrator and clicking on the WSRP tab in the Admin portal. If all went well, you should see something similar to this:

This screen presents all the configured producers associated with their status and possible actions on them. A Consumer can be active or inactive. Activating a Consumer means that it is ready to act as a portlet provider. Deactivating it will remove it from the list of available portlet providers. Note also that a Consumer can be marked as requiring refresh meaning that the information held about it might not be up to date and refreshing it from the remote Producer might be a good idea. This can happen for several reasons: the service description for that remote Producer has not been fetched yet, the cached version has expired or modifications have been made to the configuration that could potentially invalidate it, thus requiring re-validation of the information.

Next, we create a new Consumer which we will callbea. Type "bea" in the "Create a consumer named:" field then click on "Create consumer":

You should now see a form allowing you to enter/modify the information about the Consumer. Set the cache expiration value to 300 seconds and enter the WSDL URL for the producer in the text field and press the "Refresh & Save" button:

This will retrieve the service description associated with the Producer which WSRP is described by the WSDL file found at the URL you just entered. In our case, querying the service description will allow us to learn that the Producer requires registration and that it expects a value for the registration property named registration/consumerRole:

Note

At this point, there is no automated way to learn about which possible values (if any) are expected by the remote Producer. In the case of BEA's public producer, the possible values are indicated in the registration property description. This is not always the case... Please refer to the specific Producer's documentation.

Enter "public" as the value for the registration property and press "Save & Refresh" once more. You should now see something similar to:

The Consumer for the bea Producer should now be available as a portlet provider and is ready to be used.

A producer is configured, by default, by retrieving the producer's information via a WSDL URL. There are rare cases, however, where URLs need to be provided for each of the producer's end points. You can do exactly that by unchecking the "Use WSDL?" checkbox, as is the case for the self producer:

14.6.2.2. Using a WSRP Producer XML descriptor

We will create a public-bea-wsrp.xml descriptor. Note that the actual name does not matter as long as it ends with -wsrp.xml:

Example 14.3. 

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE deployments PUBLIC "-//JBoss Portal//DTD WSRP Remote Producer Configuration 2.6//EN"
   "http://www.jboss.org/portal/dtd/jboss-wsrp-consumer_2_6.dtd">
<deployments>
  <deployment>
    <wsrp-producer id="bea" expiration-cache="300">
      <endpoint-wsdl-url>http://wsrp.bea.com:7001/producer/producer?WSDL</endpoint-wsdl-url>
      <registration-data>
        <property>
          <name>registration/consumerRole</name>
          <lang>en</lang>
          <value>public</value>
        </property>
      </registration-data>
    </wsrp-producer>
  </deployment>
</deployments>

This producer descriptor gives access to BEA's public WSRP producer. We will look at the details of the different elements later. Note for now the producer-id element with a "bea" value. Put this file in the deploy directory and start the server (with JBoss Portal and its WSRP service deployed).

Note

A DTD and an XML Schema for WSRP Producer XML descriptors are available in jboss-portal.sar/portal-wsrp.sar/dtd/jboss-wsrp-consumer_2_6.dtd and jboss-portal.sar/portal-wsrp.sar/xsd/jboss-wsrp-consumer_2_6.xsd

14.6.2.3. Configuring access to a remote portlet

Let's now look at the Admin page and the Management portlet. Click on the "Portlet definitions" tab at the top. Once this is done, look at the list of available portlet providers. If all went well, you should see something similar to this:

We have 3 available portlet providers: local, self andbea. The local portlet provider exposes all the portlets deployed in this particular instance of Portal. As explained above, the self provider refers to the default WSRP consumer bundled with Portal that consumes the portlets exposed by the default WSRP producer. The bea provider corresponds to BEA's public producer we just configured. Select it and click on "View portlets". You should now see something similar to:

From there on out, you should be able to configure WSRP portlets just as any other. In particular, you can create an instance of one of the remote portlets offered by BEA's public producer just like you would create an instance of a local portlet and then assign it to a window in a page. If you go to that page, you should see something similar to below for this portlet:

14.6.3. WSRP Producer descriptors

A WSRP Producer descriptor is an XML file which name ends in -wsrp.xml and which can be dropped in the deploy directory of the JBoss application server or nested in .sar files. It is possible to configure access to several different producers within a single descriptor or use one file per producer, depending on your needs. An XML Schema for the WSRP Producer descriptor format can be found at jboss-portal.sar/portal-wsrp.sar/xsd/jboss-wsrp-consumer_2_6.xsd, while a (legacy) DTD can be found at jboss-portal.sar/portal-wsrp.sar/dtd/jboss-wsrp-consumer_2_6.dtd.

Note

It is important to note how WSRP Producer descriptors are processed. They are read the first time the WSRP service starts and the associated information is then put in the Portal database. Subsequent launch of the WSRP service will use the database-stored information for all producers which identifier is already known to Portal. More specifically, all the descriptors are scanned for producer identifiers. Any identifier that is already known will be bypassed and the configuration associated with this remote producer in the database will be used. If a producer identifier is found that wasn't already in the database, that producer information will be processed and recorded in the database. Therefore, if you wish to delete a producer configuration, you need to delete the associated information in the database (this can be accomplished using the configuration portlet as we saw in Section 14.6.2.1, “Using the configuration portlet”) AND remove the associated information in any WSRP Producer descriptor (if such information exists) as the producer will be re-created the next time the WSRP is launched if that information is not removed.

14.6.3.1. Required configuration information

Let's now look at which information needs to be provided to configure access to a remote producer.

First, we need to provide an identifier for the producer we are configuring so that we can refer to it afterwards. This is accomplished via the mandatory id attribute of the <wsrp-producer> element.

JBoss Portal also needs to learn about the remote producer's endpoints to be able to connect to the remote web services and perform WSRP invocations. Two options are currently supported to provide this information:

  • You can provide the URLs for each of the different WSRP interfaces offered by the remote producer via the <endpoint-config> element and its <service-description-url>, <markup-url>, <registration-url> and <portlet-management-url> children. These URLs are producer-specific so you will need to refer to your producer documentation or WSDL file to determine the appropriate values.
  • Alternatively, and this is the easiest way to configure your producer, you can provide a URL pointing to the WSDL description of the producer's WSRP services. This is accomplished via the <endpoint-wsdl-url> element. JBoss Portal will then heuristically determine, from the information contained in the WSDL file, how to connect appropriately to the remote WSRP services.

    Note

    It is important to note that, when using this method, JBoss Portal will try to match a port name to an interface based solely on the provided name. There are no standard names for these ports so it is possible (though rare) that this matching process fails. In this case, you should look at the WSDL file and provide the endpoint URLs manually, as per the previous method.

Both the id attribute and either <endpoint-config> or <endpoint-wsdl-url> elements are required for a functional remote producer configuration.

14.6.3.2. Optional configuration

It is also possible to provide addtional configuration, which, in some cases, might be important to establish a proper connection to the remote producer.

One such optional configuration concerns caching. To prevent useless roundtrips between the local consumer and the remote producer, it is possible to cache some of the information sent by the producer (such as the list of offered portlets) for a given duration. The rate at which the information is refreshed is defined by the expiration-cache attribute of the <wsrp-producer> element which specifies the refreshing period in seconds. For example, providing a value of 120 for expiration-cache means that the producer information will not be refreshed for 2 minutes after it has been somehow accessed. If no value is provided, JBoss Portal will always access the remote producer regardless of whether the remote information has changed or not. Since, in most instances, the information provided by the producer does not change often, we recommend that you use this caching facility to minimize bandwidth usage.

Additionally, some producers require consumers to register with them before authorizing them to access their offered portlets. If you know that information beforehand, you can provide the required registration information in the producer configuration so that the Portal consumer can register with the remote producer when required.

Note

At this time, though, only simple String properties are supported and it is not possible to configure complex registration data. This should however be sufficient for most cases.

Registration configuration is done via the <registration-data> element. Since JBoss Portal can generate the mandatory information for you, if the remote producer does not require any registration properties, you only need to provide an empty <registration-data> element. Values for the registration properties required by the remote producer can be provided via <property> elements. See the example below for more details. Additionally, you can override the default consumer name automatically provided by JBoss Portal via the <consumer-name> element. If you choose to provide a consumer name, please remember that this should uniquely identify your consumer.

14.6.4. Examples

Here is the configuration of the self producer as found in default-wsrp.xml with a cache expiring every five minutes:

Example 14.4. 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE deployments PUBLIC "-//JBoss Portal//DTD WSRP Remote Producer Configuration 2.6//EN"
   "http://www.jboss.org/portal/dtd/jboss-wsrp-consumer_2_6.dtd">

<deployments>
   <deployment>
      <wsrp-producer id="self" expiration-cache="300">
         <!--
         we need to use the individual endpoint configuration because the configuration via
         wsdl forces an immediate attempt to access the web service description which is not
         available yet at this point of deployment
         -->
         <endpoint-config>
            <service-description-url>
              http://localhost:8080/portal-wsrp/ServiceDescriptionService
            </service-description-url>
            <markup-url>http://localhost:8080/portal-wsrp/MarkupService</markup-url>
            <registration-url>
              http://localhost:8080/portal-wsrp/RegistrationService
            </registration-url>
            <portlet-management-url>
              http://localhost:8080/portal-wsrp/PortletManagementService
            </portlet-management-url>
         </endpoint-config>
         <registration-data/>
      </wsrp-producer>
   </deployment>
</deployments>
            

Here is an example of a WSRP descriptor with a 2 minute caching time and manual definition of the endpoint URLs:

Example 14.5. 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE deployments PUBLIC "-//JBoss Portal//DTD WSRP Remote Producer Configuration 2.6//EN"
   "http://www.jboss.org/portal/dtd/jboss-wsrp-consumer_2_6.dtd">

<deployments>
   <deployment>
      <wsrp-producer id="MyProducer" expiration-cache="120">
         <endpoint-config>
            <service-description-url>
             http://www.someproducer.com/portal-wsrp/ServiceDescriptionService
            </service-description-url>
            <markup-url>
             http://www.someproducer.com/portal-wsrp/MarkupService
            </markup-url>
            <registration-url>
             http://www.someproducer.com/portal-wsrp/RegistrationService
            </registration-url>
            <portlet-management-url>
             http://www.someproducer.com/portal-wsrp/PortletManagementService
            </portlet-management-url>
         </endpoint-config>
      </wsrp-producer>
   </deployment>
</deployments>

Here is an example of a WSRP descriptor with endpoint definition via remote WSDL file, registration data and cache expiring every minute:

Example 14.6. 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE deployments PUBLIC "-//JBoss Portal//DTD WSRP Remote Producer Configuration 2.6//EN"
   "http://www.jboss.org/portal/dtd/jboss-wsrp-consumer_2_6.dtd">

<deployments>
   <deployment>
      <wsrp-producer id="AnotherProducer" expiration-cache="60">
         <endpoint-wsdl-url>http://example.com/producer/producer?WSDL</endpoint-wsdl-url>
         <registration-data>
            <property>
               <name>property name</name>
               <lang>en</lang>
               <value>property value</value>
            </property>
         </registration-data>
      </wsrp-producer>
   </deployment>
</deployments>

14.7. Consumers maintenance

14.7.1. Modifying a currently held registration

14.7.1.1. Registration modification for service upgrade

Producers often offer several levels of service depending on consumers' subscription levels (for example). This is implemented at the WSRP level with the registration concept: producers assert which level of service to provide to consumers based on the values of given registration properties.

It is therefore sometimes necessary to modify the registration that concretizes the service agreement between a consumer and a producer. An example of easily available producer offering different level of services is BEA's public producer. We configured access to that producer in Section 14.6.2.1, “Using the configuration portlet”. If you recall, the producer was requiring registration and required a value to be provided for the registration/consumerRole property. The description of that property indicated that three values were possible: public, partner or insider each corresponding to a different service level. We registered using the public service level. This gave us access to three portlets as shown here:

Suppose now that we would like to upgrade our service level to the "insider" level. We will need to tell BEA's producer that our registration data has been modified. Let's see how to do this. Assuming you have configured access to the producer as previously described, please go to the configuration screen for the bea producer and modify the value of the registration/consumerRole to insider instead of public:

Now click on "Update properties" to save the change. A "Modify registration" button should now appear to let you send this new data to the remote producer:

Click on this new button and, if everything went well and your updated registration has been accepted by the remote producer, you should see something similar to:

You can now check the list of available portlets from the bea provider and verify that new portlets are now available:

14.7.1.2. Registration modification on producer error

It can also happen that a producer administrator decided to require more information from registered consumers. In this case, invoking operations on the producer will fail with an OperationFailedFault. JBoss Portal will attempt to help you in this situation. Let's walk through an example using the self producer. Let's assume that registration is required without any registration properties (as is the case by default). If you go to the configuration screen for this producer, you should see:

Now suppose that the administrator of the producer now requires a value to be provided for an email registration property. We will actually see how to do perform this operation in JBoss Portal when we examine how to configure Portal's producer in Section 14.8, “Configuring JBoss Portal's WSRP Producer”. Operations with this producer will now fail. If you suspect that a registration modification is required, you should go to the configuration screen for this remote producer and refresh the information held by the consumer by pressing "Refresh & Save":

As you can see, the configuration screen now shows the currently held registration information and the expected information from the producer. Enter a value for the email property and then click on "Modify registration". If all went well and the producer accepted your new registration data, you should see something similar to:

Note

As of WSRP 1, it is rather difficult to ascertain for sure what caused an OperationFailedFault as it is the generic exception returned by producers if something didn't quite happen as expected during a method invocation. This means that OperationFailedFault can be caused by several different reasons, one of them being a request to modify the registration data. Please take a look at the log files to see if you can gather more information as to what happened. WSRP 2 introduces an exception that is specific to a request to modify registrations thus reducing the ambiguity that currently exists.

14.7.2. Consumer operations

Several operations are available from the consumer list view of the WSRP configuration portlet:

The available operations are:

  • Configure: displays the consumer details and allows user to edit them
  • Refresh: forces the consumer to retrieve the service description from the remote producer to refresh the local information (offered portlets, registration information, etc.)
  • Activate/Deactivate: activates/deactivates a consumer, governing whether it will be available to provide portlets and receive portlet invocations
  • Register/Deregister: registers/deregisters a consumer based on whether registration is required and/or acquired
  • Delete: destroys the consumer, after deregisterting it if it was registered

14.7.3. Erasing local registration data

There are rare cases where it might be required to erase the local information without being able to deregister first. This is the case when a consumer is registered with a producer that has been modified by its administrator to not require registration anymore. If that ever was to happen (most likely, it won't), you can erase the local registration information from the consumer so that it can resume interacting with the remote producer. To do so, click on "Erase local registration" button next to the registration context information on the consumer configuration screen:

Note

This operation is dangerous as it can result in inability to interact with the remote producer if invoked when not required. A warning screen will be displayed to give you a chance to change your mind!

14.8. Configuring JBoss Portal's WSRP Producer

14.8.1. Overview

You can configure the behavior of Portal's WSRP Producer by using the WSRP administration interface, which is the preferred way, or by editing the conf/config.xml file found in portal-wsrp.sar. Several aspects can be modified with respects to whether registration is required for consumers to access the Producer's services. An XML Schema for the configuration format is available at jboss-portal.sar/portal-wsrp.sar/xsd/jboss-wsrp-producer_2_6.xsd, while a (legacy) DTD is available at jboss-portal.sar/portal-wsrp.sar/dtd/jboss-wsrp-producer_2_6.dtd

14.8.2. Default configuration

The default producer configuration is to require that consumers register with it before providing access its services but does not require any specific registration properties (apart from what is mandated by the WSRP standard). It does, however, require consumers to be registered before sending them a full service description. This means that our WSRP producer will not provide the list of offered portlets and other capabilities to unregistered consumers. The producer also uses the default RegistrationPolicy paired with the default RegistrationPropertyValidator. We will look into property validators in greater detail later in Section 14.8.3, “Registration configuration”. Suffice to say for now that this allows users to customize how Portal's WSRP Producer decides whether a given registration property is valid or not.

JBoss Portal 2.6.3 introduces a web interface to configure the producer's behavior. You can access it by clicking on the "Producer Configuration" tab of the "WSRP" page of the "admin" portal. Here's what you should see with the default configuration:

As would be expected, you can specify whether or not the producer will send the full service description to unregistered consumers, and, if it requires registration, which RegistrationPolicy to use (and, if needed, which RegistrationPropertyValidator), along with required registration property description for which consumers must provide acceptable values to successfully register.

14.8.3. Registration configuration

In order to require consumers to register with Portal's producer before interacting with it, you need to configure Portal's behavior with respect to registration. Registration is optional, as are registration properties. The producer can require registration without requiring consumers to pass any registration properties as is the case in the default configuration. Let's configure our producer starting with a blank state:

We will allow unregistered consumers to see the list of offered portlets so we leave the first checkbox ("Access to full service description requires consumers to be registered.") unchecked. We will, however, specify that consumers will need to be registered to be able to interact with our producer. Check the second checkbox ("Requires registration. Modifying this information will trigger invalidation of consumer registrations."). The screen should now refresh and display:

You can specify the fully-qualified name for your RegistrationPolicy and RegistrationPropertyValidator there. We will keep the default value. See Section 14.8.3.1, “Customization of Registration handling behavior” for more details. Let's add, however, a registration property called email. Click "Add property" and enter the appropriate information in the fields, providing a description for the registration property that can be used by consumers to figure out its purpose:

Press "Save" to record your modifications.

Note

At this time, only String (xsd:string) properties are supported. If your application requires more complex properties, please let us know.

Note

If consumers are already registered with the producer, modifying the configuration of required registration information will trigger the invalidation of held registrations, requiring consumers to modify their registration before being able to access the producer again. We saw the consumer side of that process in Section 14.7.1.2, “Registration modification on producer error”.

14.8.3.1. Customization of Registration handling behavior

Registration handling behavior can be customized by users to suit their Producer needs. This is accomplished by providing an implementation of the RegistrationPolicy interface. This interface defines methods that are called by Portal's Registration service so that decisions can be made appropriately. A default registration policy that provides basic behavior is provided and should be enough for most user needs.

While the default registration policy provides default behavior for most registration-related aspects, there is still one aspect that requires configuration: whether a given value for a registration property is acceptable by the WSRP Producer. This is accomplished by plugging a RegistrationPropertyValidator in the default registration policy. This allows users to define their own validation mechanism.

Please refer to the Javadoc™ for org.jboss.portal.registration.RegistrationPolicy and org.jboss.portal.Registration.policies.RegistrationPropertyValidator for more details on what is expected of each method.

Defining a registration policy is required for the producer to be correctly configured. This is accomplished by specifying the qualified class name of the registration policy. Since we anticipate that most users will use the default registration policy, it is possible to provide the class name of your custom property validator instead to customize the default registration policy behavior. Note that property validators are only used by the default policy.

Note

Since the policy or the validator are defined via their class name and dynamically loaded, it is important that you make sure that the identified class is available to the application server. One way to accomplish that is to deploy your policy implementation as JAR file in your AS instance deploy directory. Note also that, since both policies and validators are dynamically instantiated, they must provide a default, no-argument constructor.

14.8.4. WSRP validation mode

The lack of conformance kit and the wording of the WSRP specification leaves room for differing interpretations, resulting in interoperability issues. It is therefore possible to encounter issues when using consumers from different vendors. We have experienced such issues and have introduced a way to relax the validation that our WSRP producer performs on the data provided by consumers to help with interoperability by accepting data that would normally be invalid. Note that we only relax our validation algorithm on aspects of the specification that are deemed harmless such as invalid language codes.

By default, the WSRP producer is configured in strict mode. If you experience issues with a given consumer, you might want to try to relax the validation mode. This is accomplished by editing jboss-portal.sar/portal-wsrp.sar/META-INF/jboss-service.xml and setting the value of the UseStrictMode attribute to false as shown below:

<!-- WSRP Producer implementation -->
<mbean code="org.jboss.portal.wsrp.producer.WSRPProducerImpl"
       name="portal.wsrp:service=WSRPProducer"
       xmbean-dd=""
       xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
   <xmbean/>
   <depends optional-attribute-name="Invoker" proxy-type="attribute">portal:service=PortletInvoker,type=Producer
   </depends>
   <depends optional-attribute-name="RegistrationManager" proxy-type="attribute">
      portal.wsrp:service=RegistrationManager,type=Producer
   </depends>
   <depends optional-attribute-name="ProducerConfigurationService" proxy-type="attribute">
      portal.wsrp:service=ProducerConfiguration
   </depends>
   <attribute name="UseStrictMode">true</attribute><!-- Set to false to switch to lenient mode -->
</mbean>

Chapter 15. Security

Roy Russo

Julien Viet

15.1. Securing Portal Objects

This section describes how to secure portal objects (portal instances, pages, and portlet instances), using the JBoss Portal *-object.xml descriptor OR portlet-instances.xml descriptor. View the User Guide for information on how to secure objects using the Management Portlet.

Securing portal objects declaratively, is done through the *-object.xml ( Section 6.2.1, “*-object.xml Descriptors” ), for Portal Instances and Pages, or the portlet-instances.xml ( Section 6.2.2, “The portlet-instances.xml Descriptor” ) for Portlet Instances. The portion you will be adding to each object is denoted by the <security-constraint> tag:

<?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-exists>overwrite</if-exists>
      <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>
               <action-name>viewrecursive</action-name>
               <unchecked/>
            </policy-permission>
         </security-constraint>
      </page>
   </deployment>
</deployments>

The basic principle of the security mechanism is that everything is restricted unless you grant privileges. You grant privilege on a portal node by adding a security constraint as explained here:

<security-constraint>
   <policy-permission>
      <unchecked/>
      <action-name>viewrecursive</action-name>
   </policy-permission>
</security-constraint>

The example above will grant the view privilege to anyone (unchecked role) to the current object and any child object recursively.

The security contraint portion is worth taking a look at, in an isolated fashion. It allows you to secure a specific window/page/portal-instance based on a user's role.

Role definition: You must define a role that this security constraint will apply to. Possible values are:

  • <unchecked/> Anyone can view this page.
  • <role-name>SOMEROLE</role-name> Access to this page is limited to the defined role.

Access Rights: You must define the access rights given to the role defined. Possible values are:

  • view Users can view the page.
  • viewrecursive Users can view the page and child pages.
  • personalize Users are able to personalize the page's theme.
  • personalizerecursive Users are able to personalize the page AND its children's pages themes.

Restricting access

Out of the box the default portal as a viewrecursive right for all the users, it means that whenever a page is added, this page will be seen by any user. To restrict access to this page, the default portal security constraint must be changed from viewrecursive to view, and viewrecursive security constraints must be added to its children so that they can be viewed except the one you want to restrict access to.

We provide three live samples of this descriptor, here Section 6.2.2, “The portlet-instances.xml Descriptor” , Section 6.4.1, “Defining a new Portal Page” ,and Section 6.4.2, “Defining a new Portal Instance”

15.2. Securing the Content Management System

The JBoss Portal CMS system consists of a directory structure of Files organized unto their respective Folders. Both Files and Folders are considered to be CMS resources that can be secured based on portal Roles and/or Users.

The following features are supported by the fine grained security system of Portal CMS:

  • You can associate "Read", "Write", and "Manage" Permissions at the CMS node level. (Both Files and Folders are treated as CMS nodes)
  • The Permissions are propagated recursively down a folder hierarchy
  • Any Permissions specified explicitly on the CMS Node overrides the policy inherited via recursive propagation
  • You can manage the Permissions using the CMS Admin GUI tool via the newly added "Secure Node" feature

Table 15.1.  Portal CMS Permission Matrix:

PermissionsAllowed ActionsImplies
Read Read Contents of Folder, File and its versions N/A
Write Create and Update new Folder and File Read Access
Manage Delete/Copy/Move/Rename Folders and Files Read and Write Access

15.2.1. CMS Security Configuration

The configuration for the CMS Security service is specified in the jboss-portal.sar/portal-cms.sar/META-INF/jboss-service.xml file. The portion of the configuration relevant for securing the CMS service is listed as follows:

      	  	  
			   <!-- CMS Authorization Security Service -->
			   <mbean
			      code="org.jboss.portal.cms.security.AuthorizationManagerImpl"
			      name="portal:service=AuthorizationManager,type=cms"
			      xmbean-dd=""
			      xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
			      <xmbean/>
			      <attribute name="JNDIName">java:portal/cms/AuthorizationManager</attribute>  
			      <depends optional-attribute-name="Provider" proxy-type="attribute">
			      	portal:service=AuthorizationProvider,type=cms
			      </depends>         
			   </mbean>   
			   <mbean
			      code="org.jboss.portal.cms.security.AuthorizationProviderImpl"
			      name="portal:service=AuthorizationProvider,type=cms"
			      xmbean-dd=""
			      xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
			      <xmbean/> 
			      <!--
			      	NOTE: cmsRootUserName denotes a single Portal user that has access to everything in the CMS. Denote this user
				carefully and should be synonymous to the 'root' user in UNIX operating systems. By default: this value is the built-in
			      	'admin' user account. This can be changed to any other user account registered in your Portal
			      -->
			      <attribute name="CmsRootUserName">admin</attribute>  
			      <depends optional-attribute-name="IdentityServiceController" proxy-type="attribute">portal:service=Module,type=IdentityServiceController</depends>     
			   </mbean>			
			   <!-- ACL Security Interceptor -->
			   <mbean
			      code="org.jboss.portal.cms.impl.interceptors.ACLInterceptor"
			      name="portal:service=Interceptor,type=Cms,name=ACL"
			      xmbean-dd=""
			      xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
			      <xmbean/>
			      <attribute name="JNDIName">java:/portal/cms/ACLInterceptor</attribute>
			      <attribute name="CmsSessionFactory">java:/portal/cms/CMSSessionFactory</attribute>
			      <attribute name="IdentitySessionFactory">java:/portal/IdentitySessionFactory</attribute>
			      <attribute name="DefaultPolicy">
			      	<policy>
			      			<!-- permissions on the root cms node -->      			
			      			<criteria name="path" value="/">
			      				<permission name="cms" action="read">
			      					<role name="Anonymous"/>
			      				</permission>
			      				<permission name="cms" action="write">
			      					<role name="User"/>
			      				</permission>
			      				<permission name="cms" action="manage">
			      					<role name="Admin"/>
			      				</permission>
			      			</criteria>
			      			<!-- permissions on the default cms node -->      			
			      			<criteria name="path" value="/default">
			      				<permission name="cms" action="read">
			      					<role name="Anonymous"/>
			      				</permission>
			      				<permission name="cms" action="write">
			      					<role name="User"/>
			      				</permission>
			      				<permission name="cms" action="manage">
			      					<role name="Admin"/>
			      				</permission>
			      			</criteria>      			
			      			<!-- permissions on the private/protected node -->
			      			<criteria name="path" value="/default/private">
			      				<permission name="cms" action="manage">
			      					<role name="Admin"/>
			      				</permission>
			      			</criteria>
			      	</policy>
			      </attribute>
			      <depends optional-attribute-name="AuthorizationManager" proxy-type="attribute">
			      	portal:service=AuthorizationManager,type=cms
			      </depends>            
			      <depends>portal:service=Hibernate,type=CMS</depends>
			      <depends>portal:service=Module,type=IdentityServiceController</depends>      
			   </mbean>
      	  

15.2.1.1. CMS Super User

A CMS Super User is a designated Portal User Account that has access to all resources/functions in the CMS. It is a concept similar to the super user concept in a Linux and UNIX security systems. This account should be carefully used and properly protected. By default, JBoss Portal designates the built-in 'admin' user account as a CMS Super User. This can be changed by modifying the cmsRootUserName value in the jboss-portal.sar/portal-cms.sar/META-INF/jboss-service.xml configuration.

      					      
			    <mbean
			      code="org.jboss.portal.cms.security.AuthorizationProviderImpl"
			      name="portal:service=AuthorizationProvider,type=cms"
			      xmbean-dd=""
			      xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
			      <xmbean/> 
			      <!--
			      	NOTE: cmsRootUserName denotes a single Portal user that has access to everything in the CMS. Denote this user
				carefully and should be synonymous to the 'root' user in UNIX operating systems. By default: this value is the built-in
			      	'admin' user account. This can be changed to any other user account registered in your Portal
			      -->
			      <attribute name="CmsRootUserName">admin</attribute>  
			      <depends optional-attribute-name="IdentityServiceController" proxy-type="attribute">portal:service=Module,type=IdentityServiceController</depends>     
			   </mbean>			
			   
      			

15.2.1.2. CMS Security Console

The CMS Security Console is used to assign proper permissions to all the nodes/content in the CMS. Besides protection on CMS content, this console itself needs to be secured against unauthorized acceess. Currently, the console can be accessed only by Portal users that are members of the specified Role. By default, JBoss Portal uses the built-in Admin role to allow access to this security console. This can be customized by modifying the value of defaultAdminRole option specified in jboss-portal.sar/conf/identity/standardidentity-config.xml

15.3. Authentication with JBoss Portal

JBoss Portal relies on Java Platform, Enterprise Edition (Java EE) for the authentication of users. The Java EE authentication has its advantages and drawbacks. The main motivation for using Java EE security is the integration with the application server and the operational environment in which the portal is deployed. The servlet layer provides already the authentication functionality and obviously it is not a responsibility of the portal. Whenever a user is authenticated by the servlet layer its security identity is propagated throughout the call stack in the different layers of the Java EE stack. The weaknesses are the lack of an explicit logout mechanism and the lack of dynamicity in the mapping of URL as security resources. However JBoss Portal improves that behavior when it is possible to do so.

15.3.1. Authentication configuration

JBoss Portal can be seen before all as a web application and therefore inherits all the configuration mechanisms related to web applications. The main entry point of the whole portal is the jboss-portal.sar/portal-server.war deployment which is the web application that defines and maps the portal servlet. Here you can configure various things

  • In the WEB-INF/web.xml you can change the authentication mode. The default authentication mechanism uses the form based authentication, however you can change it to any of the mechanism provided by the servlet specification.
  • In the WEB-INF/jboss-web.xml you can change the security domain used by the portal. The default security domain used by the portal is java:/jaas/portal. That setting is specific to the JBoss Application Server and how it binds the Java EE security to the operational environment. A security domain is a scope defined at the Application Server Level and defines usually a JAAS authentication stack. The portal security domain authentication stack is defined in the jboss-portal.sar/conf/login-config.xml and is dynamically deployed with the portal. The JBoss Application Server documentation is certainly the best reference for that topic.
  • The files login.jsp and error.jsp represent the pages used the form based authentication process. More information can be found in any good servlet documentation.

15.3.2. The portal servlet

The portal defines a single servlet to take care of all portal requests. The class name of that servlet is org.jboss.portal.server.servlet.PortalServlet. That servlet needs to be declared two times with different configurations otherwise the portal would not be able to know about some request details which are importants.

  • PortalServletWithPathMapping is used for path mapping mappings.
  • PortalServletWithDefaultServletMapping is used for the default servlet mapping.

The portal servlet is mapped four times with different semantics, the differences between the semantics are related to the transport layer. Each one of those for mappings will have the same request meaning for the portal beside the transport aspect. By default those mappings are

  • /* : the default access, does not define any security constraint. This is the default access that everybody uses.
  • /sec/* : the secured access, requires https usage. It is triggered when a portlet is defined as secure or when a secure portlet link is created. It requires the configuration of the https connector in JBoss Web. The JBoss Application Server documentation provides more information about it.
  • /auth/* : the authenticated access, requires the user to be authenticated to be used.
  • /authsec/* : combine the two previous options into a single one.

Usually ones should not care much about those mappings as the portal will by itself switch to the most appropriate mapping.

15.4. Authorization with JBoss Portal

JBoss Portal defines a framework for authorization. The default implementation of that framework is based on the Java Authorization Contract for Containers (JACC) which is implemented by J2EE™ 1.4 Application Servers. This section of the documentation focuses on defining the framework and its usage and is not an attempt to define what authorization is or is not because it is out of scope of this context. Instead we will try to straightforwardly describe the framework and how it is used. No specific knowledge is expected about JACC although it is a recommended read.

15.4.1. The portal permission

The org.jboss.portal.security.PortalPermission object is used to describe a permission for the portal. It extends the java.security.Permission class and any permission checked in the portal should extend the PortalPermission as well. That permission adds two fields to the Permission class

  • uri : is a string which represents an URI of the resource described by the permission.
  • collection : an object of class org.jboss.portal.security.PortalPermissionCollection which is used when the permission act as a container for other permissions. If that object exists then the uri field should be null as a portal permission represents an uri or acts as a container in an exclusive manner.

15.4.2. The authorization provider

The org.jboss.portal.security.spi.provider.AuthorizationDomain is an interface which provides access to several services.

public interface AuthorizationDomain
{
   String getType();
   DomainConfigurator getConfigurator();
   PermissionRepository getPermissionRepository();
   PermissionFactory getPermissionFactory();
}
            

  • org.jboss.portal.security.spi.provider.DomainConfigurator provides configuration access to an authorization domain. The authorization schema is very simple as it consists of bindings between URI, roles and permissions.
  • org.jboss.portal.security.spi.provider.PermissionRepository provides runtime access to the authorization domain. Usually it is used to retrieve the permissions for a specific role and URI. It is used at runtime by the framework to take security decisions.
  • org.jboss.portal.security.spi.provider.PermissionFactory is a factory to instantiate permissions for the specific domain. It is used at runtime to create permissions objects of the appropriate type by the security framework.

15.4.3. Making a programmatic security check

Making a security check is an easy thing as it consists in creating a permission of the appropriate type and make a check against the org.jboss.portal.spi.auth.PortalAuthorizationManager service. That service is used by the portal to make security checks. It is connected to the different authorization providers in order to take decisions at runtime based on the type of the permission. Access to that service is done through the org.jboss.portal.spi.auth.PortalAuthorizationManagerFactory. The factory is a portal service which is usually injected in other services like that

<?xml version="1.0" encoding="UTF-8"?>
<server>
   ...
   <mbean
      code='MyService"
      name="portal:service=MyService">
	   <depends
         optional-attribute-name="PortalAuthorizationManagerFactory"
         proxy-type="attribute">portal:service=PortalAuthorizationManagerFactory</depends>
      ...
   </mbean>
   ...
</server>

It can be injected in the servlet context of a war file in the file WEB-INF/jboss-portlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<!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>PortalAuthorizationManagerFactory</service-name>
      <service-class>
      org.jboss.portal.security.spi.auth.PortalAuthorizationManagerFactory
      </service-class>
      <service-ref>:service=PortalAuthorizationManagerFactory</service-ref>
   </service>
   ...
</portlet-app>

Here is an example of how a security check is made for a specific page

PortalAuthorizationManager pam = factory.getManager();
PortalObjectId id = page.getId();
PortalObjectPermission perm = new PortalObjectPermission(id, PortalObjectPermission.VIEW_MASK);
if (pam.checkPermission(perm) == false)
{
   System.out.println("Current user is not authorized to view page " + id);
}

15.4.4. Configuring an authorization domain

Configuring a domain can be done through the DomainConfigurator interface

public interface DomainConfigurator
{
   Set getSecurityBindings(String uri);
   void setSecurityBindings(String uri, Set securityBindings)
           throws SecurityConfigurationException;
   void removeSecurityBindings(String uri) throws SecurityConfigurationException;
}

The various methods of that interface allows to configure security bindings for a given resource where a resource is naturally identified by an URI. The org.jboss.portal.security.RoleSecurityBinding object is an object which encapsulate a role name and a set of actions bound to this role.

RoleSecurityBinding binding1 = new RoleSecurityBinding(Collections.singleton("view"), "Admin");
RoleSecurityBinding binding2 = new RoleSecurityBinding(Collections.singleton("view"), "User");
Set bindings = new HashSet();
bindings.add(binding1);
bindings.add(binding2);
configurator.setSecurityBinding(pageURI, bindings);            

Chapter 16. JBoss Portal Identity Management

This chapter addresses identity management in JBoss Portal 2.6

16.1. Identity management API

Since JBoss Portal 2.6 there are 4 identity services and 2 identity related interfaces. The goal of having such a fine grained API is to enable flexible implementations based on different identity storage like relational databases or LDAP servers. The Membership service takes care of managing the relationship between user objects and role objects. The User Profile service is responsible for managing the profile of a user, it has database and LDAP implementations as well as a mode that combines data from both.

  • The org.jboss.portal.identity.User interface represents a user and exposes the following operations:

     /** The user identifier. */
     public Object getId();
    
     /** The user name. */
     public String getUserName();
    
     /** Set the password using proper encoding. */
     public void updatePassword(String password);
    
     /** Return true if the password is valid. */
     public boolean validatePassword(String password);
     

    Warning

    Important Note! The proper usage of getId() method is:
    // Always use it like this:
    user.getId().toString();
    
    // Do not use it like this:
    
    // We would get a Long object if we are using the database implementation
    (Long)user.getId();
    
    // We would get a String with an LDAP server
    (String)user.getId();
    
    This is because the ID value depends on the User implementation. It'll probably be String object with the LDAP implementation and a Long object with the database implementation but it could be something else if one has chosen to make its own implementation.
  • The org.jboss.portal.identity.Role interface represents a Role and exposes the following operations:

    /** The role identifier. */
    public Object getId();
    
    /** The role name used in security rules. This name can not be modified */
    public String getName();
    
    /** The role display name used on screens. This name can be modified */
    public String getDisplayName();
    
    /** */
    public void setDisplayName(String name);
    
  • The org.jboss.portal.identity.UserModule interface exposes operations for users management:

    /**Retrieve a user by its name.*/
    User findUserByUserName(String userName)
       throws IdentityException, IllegalArgumentException, NoSuchUserException;
    
    /**Retrieve a user by its id.*/
    User findUserById(Object id)
       throws IdentityException, IllegalArgumentException, NoSuchUserException;
    
    /**Retrieve a user by its id.*/
    User findUserById(String id)
       throws IdentityException, IllegalArgumentException, NoSuchUserException;
    
    /** Creates a new user with the specified name.*/
    User createUser(String userName, String password)
       throws IdentityException, IllegalArgumentException;
    
    /** Remove a user.*/
    void removeUser(Object id)
       throws IdentityException, IllegalArgumentException;
    
    /** Get a range of users.*/
    Set findUsers(int offset, int limit)
       throws IdentityException, IllegalArgumentException;
    
    /** Get a range of users.*/
    Set findUsersFilteredByUserName(String filter, int offset, int limit)
       throws IdentityException, IllegalArgumentException;
    
    /**Returns the number of users.*/
    int getUserCount() throws IdentityException, IllegalArgumentException;
    
  • The org.jboss.portal.identity.RoleModule interface exposes operations for roles management:

    /** Retrieves a role by its name*/
    Role findRoleByName(String name)
       throws IdentityException, IllegalArgumentException;
    
    /**Retrieve a collection of role from the role names.*/
    Set findRolesByNames(String[] names)
       throws IdentityException, IllegalArgumentException;
    
    /** Retrieves a role by its id.*/
    Role findRoleById(Object id)
       throws IdentityException, IllegalArgumentException;
    
    /** Retrieves a role by its id.*/
    Role findRoleById(String id)
       throws IdentityException, IllegalArgumentException;
    
    /** Create a new role with the specified name.*/
    Role createRole(String name, String displayName)
       throws IdentityException, IllegalArgumentException;
    
    /** Remove a role.*/
    void removeRole(Object id)
       throws IdentityException, IllegalArgumentException;
    
    /** Returns the number of roles. */
    int getRolesCount()
       throws IdentityException;
    
    /** Get all the roles */
    Set findRoles() throws IdentityException;
    
  • The MembershipModule interface exposes operations for obtaining or managing relationships beetween users and roles. The role of this service is to decouple relationship information from user and roles. Indeed while user role relationship is pretty straightforward with a relational database (using a many to many relationship with an intermediary table), with an LDAP server there a different ways to define relationships between users and roles.

    /** Return the set of role objects that a given user has.*/
    Set getRoles(User user) throws IdentityException, IllegalArgumentException;
    
    Set getUsers(Role role) throws IdentityException, IllegalArgumentException;
    
    /** Creates a relationship beetween a role and set of users. Other roles that have
        assotiontions with those users remain unaffected.*/
    void assignUsers(Role role, Set users) throws IdentityException, IllegalArgumentException;
    
    /** Creates a relationship beetween a user and set of roles. This operation will erase any
        other assotientions beetween the user and roles not specified in the provided set.*/
    void assignRoles(User user, Set roles) throws IdentityException, IllegalArgumentException;
    
    /** Returns role members based on rolename - depreciated method ethod here only
        for compatibility with old RoleModule interface */
    Set findRoleMembers(String roleName, int offset, int limit, String userNameFilter)
       throws IdentityException, IllegalArgumentException;
    
  • The UserProfileModule interface exposes operations to access and manage informations stored in User profile:

    public Object getProperty(User user, String propertyName)
       throws IdentityException, IllegalArgumentException;
    
    public void setProperty(User user, String name, Object property)
       throws IdentityException, IllegalArgumentException;
    
    public Map getProperties(User user)
       throws IdentityException, IllegalArgumentException;
    
    public ProfileInfo getProfileInfo()
       throws IdentityException;
    

    Warning

    UserProfileModule.getProperty() method returns an Object. In most cases with DB backend it will always be String object. But normally you should check what object will be retrieved using getProfileInfo() method.
  • The ProfileInfo interface can be obtained using the UserProfileModule and exposes meta information of a profile:

    /** Returns a Map o PropertyInfo objects describing profile properties */
    public Map getPropertiesInfo();
    
    public PropertyInfo getPropertyInfo(String name);
    
  • PropertyInfo interface expose methods to obtain information about accessible property in User profile

    public static final String ACCESS_MODE_READ_ONLY = "read-only";
    public static final String ACCESS_MODE_READ_WRITE = "read-write";
    public static final String USAGE_MANDATORY = "mandatory";
    public static final String USAGE_OPTIONAL = "optional";
    public static final String MAPPING_DB_TYPE_COLUMN = "column";
    public static final String MAPPING_DB_TYPE_DYNAMIC = "dynamic";
    
    public String getName();
    
    public String getType();
    
    public String getAccessMode();
    
    public String getUsage();
    
    public LocalizedString getDisplayName();
    
    public LocalizedString getDescription();
    
    public String getMappingDBType();
    
    public String getMappingLDAPValue();
    
    public String getMappingDBValue();
    
    public boolean isMappedDB();
    
    public boolean isMappedLDAP();
    

16.1.1. How to obtain identity modules services ?

The advocated way to get a reference to the identity modules is by using JNDI:

import org.jboss.portal.identity.UserModule;
import org.jboss.portal.identity.RoleModule;
import org.jboss.portal.identity.MembershipModule;
import org.jboss.portal.identity.UserProfileModule;

[...]

(UserModule)new InitialContext().lookup("java:portal/UserModule");
(RoleModule)new InitialContext().lookup("java:portal/RoleModule");
(MembershipModule)new InitialContext().lookup("java:portal/MembershipModule");
(UserProfileModule)new InitialContext().lookup("java:portal/UserProfileModule");

Another way to do this is, if you are fimiliar with JBoss Microkernel architecture is to get the IdentityServiceController mbean. You may want to inject it into your services like this:

<depends optional-attribute-name="IdentityServiceController" proxy-type="attribute">
   portal:service=Module,type=IdentityServiceController
</depends>

or simply obtain in your code by doing a lookup using the portal:service=Module,type=IdentityServiceController name. Please refer to the JBoss Application Server documentation if you want to learn more about service MBeans. Once you obtained the object you can use it:

(UserModule)identityServiceController.getIdentityContext()
            .getObject(IdentityContext.TYPE_USER_MODULE);

(RoleModule)identityServiceController.getIdentityContext()
            .getObject(IdentityContext.TYPE_ROLE_MODULE);

(MembershipModule)identityServiceController.getIdentityContext()
            .getObject(IdentityContext.TYPE_MEMBERSHIP_MODULE);

(UserProfileModule)identityServiceController.getIdentityContext()
            .getObject(IdentityContext.TYPE_USER_PROFILE_MODULE);