Table of Contents
Release 2.4 "Devil"
July 2006
![]() |
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 Inc. 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, Inc. developers, Novell developers, and community contributors.
The JBoss Portal framework and architecture includes the portal container and supports 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 includes a rich content management system and message board support.
JBoss Portal Resources:
The JBoss Portal team encourages you to use this guide to install and configure JBoss Portal. If you encounter any configuration issues or simply want to take part in our community, we would love to hear from you in our forums.
The following list details features found in this document's related release. For a technical view of our features, view the Project Roadmap and Task List .
Technology and Architecture
Supported Standards
Portal and Portal Container
Web Services for Remote Portlets
Themes and Layouts
User and Group Functionality
Permissions Management
Content Management System
Message Boards
Portlet developers, Portal administrators, and those wishing to implement/extend the JBoss Portal framework.
For end-user documentation, please download our User Guide from our documentation page .
We would like to thank all the developers that participate in the JBoss Portal project effort.
Specifically,
Contributions of any kind are always welcome, you can contribute by providing ideas, filling bug reports, producing some code, designing a theme, writing some documentation, etc... To report a bug please use our Jira system .
A list of tested versions or reported as working by users, before reporting a problem please make sure that you are using a compatible version.
If you successfully installed JBoss Portal on versions not listed here please let us know so we can add it here.
JBoss Portal is 100% pure Java and therefore interoperable with most operating systems capable of running a Java Virtual Machine (JVM); including Windows, UNIX, and Linux.
JBoss Portal only works with JBoss Application Server.
Currently we recommend using JBoss AS 4.0.4.GA, or greater. Previous versions of JBoss Application Server are not supported with JBoss Portal 2.4
JBoss Portal is Database-Agnostic.
JBoss Portal employs Hibernate as an interface to RDBMS. Most RDBMS supported by Hibernate will work with JBoss Portal.
The following list, outlines known-to-be-working database vendor and version combinations:
There are 3 different methods to getting JBoss Portal up and running. The one you choose is up to you, but all result in your being able to run/deploy the best Portal application in the world. ;-)
This is the easiest and fastest way to get JBoss Portal installed and running. The reason, is that the download bundle contains JBoss Application Server, and JBoss Portal uses the embedded Hypersonic Database.
Get the Bundle: The download bundle is available from our download page . Bundles are noted with the 'JBoss Portal + AS' naming convention.
Extract the bundle: Extract the zip archive to a directory of your choosing. In windows, we recommend, C:\jboss-X.X.X
Start the Server: Go to JBOSS_INSTALL_DIRECTORY/bin and execute run.bat (run.sh, if Linux)
16:43:39,234 WARN [JDBCExceptionReporter] SQL Error: -22, SQLState: S0002 16:43:39,234 ERROR [JDBCExceptionReporter] Table not found in statement ...
Point your browser to http://localhost:8080/portal , and you should see the Portal HomePage. You can now login using one of the two default accounts: user/user or admin/admin .
The binary download package typically consists of the jboss-portal.sar , documentation (which you are already reading), and a set of preconfigured datasource descriptors that allow JBoss Portal to communicate with a database.
This installation method is preferred by those who already have JBoss Application Server installed.
The binary download is available from our download page .
Once downloaded and extracted, the folder hierarchy should look like this:
![]() |
We will be using files contained in this download in the further sections, so please download and extract it first.
Of course you will need to install JBoss Application Server prior to installing JBoss portal, if you didn't do so yet, please install JBoss 4.0.4+ from here .
You will need a database for JBoss Portal to function, you can use any database supported by Hibernate.
Create a new Database: For example purposes we call this new database jbossportal
Grant access rights for a user to your database: You must make sure the user has access to this new DB, as JBoss Portal will need to create the tables and modify data within them.
Deploy your JDBC connector: You must make available a JDBC connector for JBoss Portal to communicate with your database. The connector lib should be placed in JBOSS_INSTALL_DIRECTORY/server/default/lib/*
The JBoss Portal download you extracted in Section 2.2.1.1, “Getting the Binary” contains pre-configured datasource descriptors, you can use for most popular RDBMS under the setup directory.
![]() |
At this point, you should configure the one that suits you best with your Database and JDBC driver.
<?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>
Please verify that the username, password, url, and driver-class are correct for your flavor of DB. You can deploy the datasource file by itself to test, in advance.
Deploy: Copy the datasource descriptor file (*-ds.xml) you modified above AND the jboss-portal.sar from the download folder to JBOSS_INSTALL_DIRECTORY/server/default/deploy/.
Start the Server: Go to JBOSS_INSTALL_DIRECTORY/bin and execute run.bat (run.sh, if Linux)
16:43:39,234 WARN [JDBCExceptionReporter] SQL Error: -22, SQLState: S0002 16:43:39,234 ERROR [JDBCExceptionReporter] Table not found in statement ...
Point your browser to http://localhost:8080/portal , and you should see the Portal HomePage. You can now login using one of the two default accounts: user/user or admin/admin .
There are two ways for you to obtain the JBoss Portal source files:
From our download page
From CVS, running the following command:
cvs -d :pserver:anonymous@anoncvs.forge.jboss.com:/cvsroot/jboss co jboss-portal-2.4
After checking out of CVS or extracting the Source zip, your directory structure should look like this:
![]() |
Of course you will need to install JBoss Application Server prior to installing JBoss portal, if you didn't do so yet, please install JBoss 4.0.4+ from here .
For the build targets to work, you must first set the JBOSS_HOME environment variable in your operating system, to the root directory of the JBoss Application Server installation.
In Windows, this is accomplished by going to Start > Settings > Control Panel > System > Advanced > Environment Variables . Now under the System Variables section, click New . You will be setting the JBOSS_HOME environment variable to the location of your JBoss Application Server installation:
![]() |
On a Unix-like Operating System, you would accomplish this by typing:
export JBOSS_HOME=/path/to/your/jboss/directory
You will need a database for JBoss Portal to function, you can use any database supported by Hibernate.
Create a new Database: For example purposes we call this new database jbossportal
Grant access rights for a user to your database: You must make sure the user has access to this new DB, as JBoss Portal will need to create the tables and modify data within them.
Deploy your JDBC connector: You must make available a JDBC connector for JBoss Portal to communicate with your database. The connector lib should be placed in JBOSS_HOME/server/default/lib/*
You will need a valid datasource descriptor, for JBoss Portal to communicate with your database. Having obtained the sources and having set your JBOSS_HOME environment variable ( Section 2.3.2.2, “Operating System Environment Setting” ), you can now have the JBoss Portal build system generate preconfigured datasources for you.
Navigate to JBOSS_PORTAL_HOME_DIRECTORY/core and type:
build datasource
![]() |
Once complete, the datasource build should produce the following directory and file structure:
![]() |
At this point, you should configure the one that suits you best with your Database and JDBC driver.
<?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>
Please verify that the username, password, url, and driver-class are correct for your flavor of DB.
Now copy your datasource descriptor to JBOSS_HOME/server/default/deploy
To build and deploy the JBoss Portal service, go to JBOSS_PORTAL_HOME_DIRECTORY/build and type:
build deploy
![]() |
build mainThen, go to JBOSS_PORTAL_HOME_DIRECTORY/core and type:
build deploy-haThis will copy the jboss-portal-ha.sar to your all configuration for you.
At the end of the build process, the jboss-portal.sar is copied to JBOSS_HOME/server/default/deploy :
![]() |
Please verify that your JBOSS_HOME/server/default/deploy directory, contains both necessary files before starting JBoss Application Server.
Start the Server: Go to JBOSS_HOME/bin and execute run.bat (run.sh, if Linux)
16:43:39,234 WARN [JDBCExceptionReporter] SQL Error: -22, SQLState: S0002 16:43:39,234 ERROR [JDBCExceptionReporter] Table not found in statement ...
Point your browser to http://localhost:8080/portal , and you should see the Portal HomePage. You can now login using one of the two default accounts: user/user or admin/admin .
This section is intended to describe some customization features available in JBoss Portal. If it is not covered here, please view the FAQ chapter at the end of this document or the descriptor chapter ( Section 6.2, “JBoss Portal Descriptors” ) for further documentation on configuration and tuning JBoss Portal.
It is common to have a server running on the port 80 instead of the default port 8080.
It might be easier to use port forwarding than to change the port manually. Since port forwarding is not always possible, below are the instructions to change the port number manually.
To change it, you need to edit the file $JBOSS_HOME/server/default/deploy/jbossweb-tomcat50.sar/server.xml and change the port value of the HTTP Connector. You can also change the value of the SSL port, by default it is set to 8443. Remember to uncomment the following when you have configured it:
<!-- SSL/TLS Connector configuration using the admin devl guide keystore
<Connector port="8443" address="${jboss.bind.address}"
maxThreads="100" strategy="ms" maxHttpHeaderSize="8192"
emptySessionPath="true"
scheme="https" secure="true" clientAuth="false"
keystoreFile="${jboss.server.home.dir}/conf/chap8.keystore"
keystorePass="rmi+ssl" sslProtocol = "TLS" />
-->
You also need to change the port number in the following files for WSRP:
Now you can restart JBoss and use the new port that you defined. On systems like Linux, you need privileges to be able to run a server on a port lower than 1000, starting JBoss on the port 80 as a regular user will not work, for testing you can log as root but is not recommended if the server is public as it could be a security breach in your system.
By default, the "main" page of JBoss portal will be accessible at http://localhost:8080/portal/index.html . You may want to change that either to a different name or to http://localhost:8080/index.html .
You can accomplish this, with either a deployed jboss-portal.sar or before you build from source:
Binary method:
Open JBOSS_INSTALL_DIRECTORY/server/default/deploy/jboss-portal.sar/portal-server.war/WEB-INF/jboss-web.xml
<?xml version="1.0"?>
<jboss-web>
<security-domain>java:jaas/portal</security-domain>
<context-root>/portal</context-root>
<replication-config>
<replication-trigger>SET_AND_GET</replication-trigger>
<replication-type>SYNC</replication-type>
</replication-config>
<resource-ref>
<res-ref-name>jdbc/PortalDS</res-ref-name>
<jndi-name>java:PortalDS</jndi-name>
</resource-ref>
</jboss-web>
Edit the context-root element to whatever you desire.
<context-root>/</context-root>
Source method: Edit the file $PORTAL_HOME/build/local.properties (You can copy the file $PORTAL_HOME/build/etc/local.properties-example and modify it for your own settings.) and change portal.web.context-root to anything you want.
Now clean the project (ant clean) then build JBoss portal (ant) and redeploy it for the context path changes to take effect. For build instructions, please see: Section 2.3, “Installing from Sources”
If you encounter that the Hibernate dialect is not working properly and would like to override the default behaviour, follow the instructions contained in this section:
Modify jboss-portal.sar/conf/hibernate/[module]/hibernate.cfg.xml . A list of supported dialects for Hibernate3, can be found here .
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.datasource">java:PortalDS</property>
<property name="show_sql">false</property>
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<property name="cache.use_query_cache">true</property>
<!-- Force the dialect instead of using autodetection -->
<!--
<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
-->
<!-- Mapping files -->
<mapping resource="conf/hibernate/user/domain.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Modify jboss-portal.sar/portal-cms.sar/conf/hibernate/cms/hibernate.cfg.xml . A list of supported dialects for Hibernate3, can be found here .
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.datasource">java:@portal.datasource.name@</property>
<property name="show_sql">@portal.sql.show@</property>
<property name="cache.use_second_level_cache">false</property>
<property name="cache.use_query_cache">true</property>
<!-- Force the dialect instead of using autodetection -->
<!--
<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
-->
<!-- Mapping files -->
<mapping resource="conf/hibernate/cms/domain.hbm.xml"/>
</session-factory>
</hibernate-configuration>
This chapter addresses migration issues from version 2.2 to 2.4 of JBoss Portal.
JBoss Portal 2.4 comes with dedicated web application for database migration. This application will migrate your existing JBoss Portal 2.2 database data to a new one, for use with JBoss Portal 2.4.
You will need two database instances for this migration process to function:
Source JBP 2.2 database from which we migrate portal data. (You should already have this!)
Destination JBP 2.4 database to which we migrate portal data.
Before you begin the process you must create a separate database to which the data will be migrated. Note that the Migration Application performs a Hibernate SchemaExport which drops and recreates tables - It is recommended that you backup your database before starting!
For our example, we have two databases... the existing one for JBoss Portal 2.2, and the new (empty) one for JBoss Portal 2.4:
JBoss Portal 2.2 DB: jbossportal22
JBoss Portal 2.4 DB: jbossportal24
We will use the above database naming, as examples in the next chapter on configuring the datasource.
The Migration Application will need access to both databases, while its running. For this reason, we need to make available both JBoss Application Server datasource files.
You should have an existing JBoss Portal 2.2 datasource, portal-ds.xml or portal-*-ds.xml file that looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>
<jndi-name>PortalDS</jndi-name>
<connection-url>jdbc:mysql://localhost:3306/jbossportal22?useServerPrepStmts=false</connection-url>
<driver-class>org.gjt.mm.mysql.Driver</driver-class>
<user-name>portal</user-name>
<password>portalpassword</password>
</local-tx-datasource>
</datasources>
Now, you will need to create a second datasource for the destination database. In our example we will create, portal-migration-ds.xml file that looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>
<jndi-name>PortalDS_2_4</jndi-name>
<connection-url>jdbc:mysql://localhost:3306/jbossportal24?useServerPrepStmts=false</connection-url>
<driver-class>org.gjt.mm.mysql.Driver</driver-class>
<user-name>portal</user-name>
<password>portalpassword</password>
</local-tx-datasource>
</datasources>
The JBoss Portal Migration Application can be obtained either as a ready to deploy web application or in source form.
You can find a prepared binary at:
Download section of JBoss Portal project page
You can obtain portal sources from either:
Download section of JBoss Portal project page
CVS by running following command:
cvs -d :pserver:anonymous@anoncvs.forge.jboss.com:/cvsroot/jboss co jboss-portal-2.4
Using the second method you will always have all latest updates from portal 2.4 cvs branch
After downloading the sources you need to build the Migration Application. Before you start be sure you have JBOSS_HOME environment variable set pointing to JBoss Application Server directory. Migration Application archive can be build using following commands:
cd jboss-portal-2.4
cd build
./build.sh
cd ..
cd migration
./build.sh
Deployable web application archive can be found at jboss-portal-2.4/migration/output/lib/portal-migration.war
You can also deploy it automatically by executing:
cd jboss-portal-2.4
cd migration
./build.sh deploy
The steps below will guide you through deploying and running the migration application:
Shut down JBoss Application Server
Undeploy/Remove JBoss Portal 2.2 (JBOSS_HOME/server/default/deploy/jboss-portal.sar)
Delete JBOSS_HOME/server/default/data/portal/cms (This directory will be created for you, once again, when JBoss Portal 2.4 initializes.
Deploy the two necessary datasource descriptors, from Section 4.1.2, “DataSource Requirements/Preparation” to JBOSS_HOME/server/default/deploy/*
Deploy the Migration Application, you obtained from Section 4.1.3, “Obtaining the Migration Application” to JBOSS_HOME/server/default/deploy/portal-migration.war
Start JBoss Application Server
After deploying Migration Application you can access it at http://localhost:8080/portal-migration . It is password protected so you need to specify:
User: admin
Password: simplePassword
If you logged in successfully you should access this page:
![]() |
At Step 2: 2.4 Database Connectivity Check you need to provide datasouce name that points to JBoss Portal 2.4 database (the destination one)
![]() |
Step 3: Create Tables
![]() |
If both connections were valid and database schema was created successfully you can follow with the migration process. It is separated into following parts:
CMS Data Migration - migrates portal CMS tables content
![]() |
User/Role Data Migrate - migrates portal user, roles and relations beetween them
![]() |
Portal Object Data Migrate - migrates whole portal objects structure. This means nodes like portals, pages and windows.
![]() |
Portal Portlet Instance Data Migrate - migrates all portlet instances presented in portal. For each portlet instance its preferences are also persisted. Next, all already migrated users are iterated and user preferences related to portlet instance are migrated
![]() |
Portal Security Data Migrate - migrates security data for portal objects and portlet instances.
![]() |
Which should lead to a successfull end :)
![]() |
![]() |
![]() |
After running the Migration Application you need to perform some additional steps to finish the process:
Shutdown JBoss Application Server
Undeploy JBoss Portal 2.2 (jboss-portal.sar)
Undeploy the JBoss Portal 2.2 datasource descriptor
Delete JBOSS_HOME/server/default/data/portal/cms (This directory will be created for you, once again, when JBoss Portal 2.4 initializes.
Edit your 2.4 datasource file and modify the jndi name: <jndi-name>PortalDS</jndi-name>
Deploy JBoss Portal 2.4.
Start JBoss Application Server
Since 2.2 version of JBoss Portal data from portlet descriptor files are persisted in database. There is special <if-exists/> tag that describes what should portal do when he process descriptor and found data for such portlet application already in database. Therefore after database migration portal will use persisted data.
There are some differences beetween 2.2 and 2.4 descriptors. portlet-instances.xml file was reintroduced because of WSRP implementation caused portal architecture changes. Altough to avoid confusion legacy descriptors support was implemented in 2.4 so all 2.2 compiliant portlets should work out of box.
Even if your 2.2 portlets deployed successfully in 2.4 you should update their descriptors. Legacy descriptors support will expire in 2.6 and you will need to use new format to achive more complex targets.
Let's show descriptor changes using Car Demo portlet example which is a presentation of JSF portlet. It can be obtained at PortletSwap . In 2.2 prepared version it has such descriptor:
cardemo-object.xml
<?xml version="1.0" encoding="UTF-8"?>
<deployments>
<deployment>
<if-exists>overwrite</if-exists>
<parent-ref>default</parent-ref>
<page>
<page-name>samples</page-name>
<window>
<window-name>CarDemoWindow</window-name>
<instance-ref>CarDemoPortletInstance</instance-ref>
<region>center</region>
<height>0</height>
</window>
</page>
</deployment>
<deployment>
<if-exists>overwrite</if-exists>
<instance>
<instance-name>CarDemoPortletInstance</instance-name>
<component-ref>cardemo.CarDemoPortlet</component-ref>
</instance>
</deployment>
</deployments>
Note that as we said before you can successfully deploy it on JBoss Portal 2.4. But because such descriptor format is 2.2 specific you will end with a warning on JBoss Application Server console output:
INFO [PortletAppDeployment] These instances have been found in -object.xml, you should put them in the file
c:\jboss-4.0.4.GA\server\default\.\deploy\cardemo.war\WEB-INF/portlet-instances.xml
INFO [PortletAppDeployment] <?xml version="1.0" encoding="utf-8" standalone="yes"?>
<deployments>
<deployment>
<instance>
<instance-id>CarDemoPortletInstance</instance-id>
<portlet-ref>CarDemoPortlet</portlet-ref>
</instance>
</deployment>
</deployments>
So all you need to do is to follow suggestion you got in the warning message :)
To have descriptors in our example portlet 2.4 valid you need to follow few simple steps:
In cardemo-object.xml file comment out whole <deployment>...</deployment> tag which contains <instance>...</instance> .
Copy the text you just commented out and put it in newly created portlet-instances.xml file.
Edit and change portlet-instances.xml file using following rules:
Surround whole file content with </deployments> tag.
Replace </instance-name> tag with </instance-id> one
Replace </component-ref> tag with </portlet-ref> one
So after updates your portlet descriptors should look like this:
cardemo-object.xml
<?xml version="1.0" encoding="UTF-8"?>
<deployments>
<deployment>
<if-exists>overwrite</if-exists>
<parent-ref>default</parent-ref>
<page>
<page-name>samples</page-name>
<window>
<window-name>CarDemoWindow</window-name>
<instance-ref>CarDemoPortletInstance</instance-ref>
<region>center</region>
<height>0</height>
</window>
</page>
</deployment>
</deployments>
portlet-instances.xml
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<deployments>
<deployment>
<instance>
<instance-id>CarDemoPortletInstance</instance-id>
<portlet-ref>CarDemoPortlet</portlet-ref>
</instance>
</deployment>
</deployments>
The JSR 168 specification aims at defining porlets that can be used by any JSR168 portlet container also called portals. There are different portals out there with commercial and non-commercial licences. In this chapter we will briefly describe such portlets but for more details you should read the specifications available on the web.
As of today, JBoss portal is fully JSR168 1.0 compliant, that means that any JSR168 portlet will behave as it should inside the portal.
A portal can be seen as pages with different areas and inside areas, different windows and each window having one portlet.
![]() |
A porlet can have different view modes, three modes are defined by the specification but a portal can extend those modes. The 3 modes are:
Window states are an indicator of how much page real-estate a portlet should consume on any given page. There are 3 states defined by the specification:
The tutorials contained in this chapter are targetted toward portlet developers. Although they are a good starting and reference point, we do heavily recommend that portlet developers read and understand the Portlet Specification (JSR-168) . We also recommend, using our JBoss Portal User Forums for user-to-user help, when needed.
This section will introduce the reader to deploying his first portlet in JBoss Portal. It requires you download the HelloWorldPortlet from PortletSwap.com, using this link .
Portlets are packaged in war files, just like other JEE applications. A typical portlet war file can also include servlets, resource bundles, images, html, jsps, and other static or dynamic files you would commonly include.
![]() |
Included in the download bundle you should have one java source file: HelloWorldPortlet\src\main\org\jboss\portlet\hello\HelloWorldPortlet.java , and it should contain the following:
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();
}
}
Now lets dissect our simplest of portlets:
public class HelloWorldPortlet extends GenericPortlet
All Portlets MUST implement the javax.portlet.GenericPortlet Interface.
protected void doView(RenderRequest rRequest, RenderResponse rResponse) throws
PortletException, IOException, UnavailableExceptionIn this case, our doView will be called when the portlet is asked to render output in VIEW Mode.
rResponse.setContentType("text/html");Just like in the servlet-world, you must declare what content-type the portlet will be responding in.
PrintWriter writer = rResponse.getWriter();
writer.write("Hello World!");
writer.close();Here we output the text Hello World! in our portlet window.
JBoss Portal requires certain descriptors be included in your portlet war, for different reasons. Some of these descriptors are defined by the Portlet Specification, and some are specific to JBoss Portal.
![]() |
Now lets explain what each of these does:
portlet.xml
<?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>This file must adhere to its definition in the Portlet Specification. You may define more than one portlet application in this file.
<portlet-name>HelloWorldPortlet</portlet-name>
Define your portlet name. It does not have to be the Class name.
<portlet-class>org.jboss.portlet.hello.HelloWorldPortlet</portlet-class>
The FQN of your portlet class must be declared here.
<supports> <mime-type>text/html</mime-type> <portlet-mode>VIEW</portlet-mode> </supports>
The supports attributes allow you to declare extra vital information about the portlet. In this case, we are letting the portal know that it will be outputting text/html and only support a VIEW mode.
<portlet-info> <title>HelloWorld Portlet</title> </portlet-info>
The portlet's title will be displayed as the header in the portlet window, when rendered, unless it is overridden programatically.
portlet-instances.xml
<deployments>
<deployment>
<instance>
<instance-id>HelloWorldPortletInstance</instance-id>
<portlet-ref>HelloWorldPortlet</portlet-ref>
</instance>
</deployment>
</deployments>This is a JBoss Portal specific descriptor that allows you create an instance of a portlet. The portlet-ref value must match the portlet-name value given in the packaged portlet.xml . The instance-id value can be named anything, but it must match the instance-ref value given in the *-object.xml file we will explore below.
helloworld-object.xml
<deployments>
<deployment>
<if-exists>overwrite</if-exists>
<parent-ref>default.default</parent-ref>
<window>
<window-name>HelloWorldPortletWindow</window-name>
<instance-ref>HelloWorldPortletInstance</instance-ref>
<region>center</region>
<height>1</height>
</window>
</deployment>
</deployments>The *-object.xml is responsible for creating/configuring windows, pages, and even portal instances. In our example, we are creating a portlet window, assigning it to a page, and specifying where it should appear on that page. This is a specific descriptor to JBoss Portal.
<if-exists>overwrite</if-exists>
Instructs the portal to overwrite or keep this object if it already exists. Possible values are overwrite or keep . Overwrite will destroy the existing object and create a new one based on the content of the deployment. Keep will maintain the existing objct deployment or create a new one if it does not yet exist.
<parent-ref>default.default</parent-ref>
Tells the portal where this portlet should appear. In this case, default.default specifies that this portlet should appear in the portal instance named default and the page named default .
<window-name>HelloWorldPortletWindow</window-name>Can be named anything.
<instance-ref>HelloWorldPortletInstance</instance-ref>The value of instance-ref must match the value of instance-id found in the portlet-instances.xml .
<region>center</region> <height>1</height>
Specify the layout region and order this window will be found on the portal page.
To illustrate the relationship between the descriptors , we have provided this simple diagram
![]() |
If you have downloaded the sample, you can execute the build.xml with ANT or inside your IDE. Executing the deploy target will compile all src files and produce a helloworldportlet.war under HelloWorldPortlet\helloworldportlet.war.
![]() |
If you want to create an expanded war directory, after executing the above deploy target, you should execute the explode target.
![]() |
The above target will produce the following:
![]() |
This will deflate the helloworldportlet.war, and allow you to deploy it as an expanded directory. It will work just the same, with some additional benefits noted below:
The advantage to expanded war deployments is that you can modify xml descriptors, resource files jsp/jsf pages easily during development. Simply touch the web.xml to have JBoss Application Server hot-deploy the web appllication on a live-running server instance
Deploying a portlet is as simple as copying/moving the helloworldportlet.war in to the server deploy directory. Doing this on a running instance of the portal and application server, will trigger a hot-deploy :
18:25:56,366 INFO [Server] JBoss (MX MicroKernel) [4.0.3SP1 (build: CVSTag=JBoss_4_0_3_SP1 date=200510231054)] Started in 1m:3s:688ms
18:26:21,147 INFO [TomcatDeployer] deploy, ctxPath=/helloworldportlet, warUrl=.../tmp/deploy/tmp35219helloworldportlet-exp.war/
Pointing your browser to http://localhost:8080/portal/ , should yield a view of our HelloWorldPortlet:
![]() |
This section will introduce the reader to deploying a simple JSP portlet in JBoss Portal. It requires you download the HelloWorldJSPPortlet from PortletSwap.com, using this link .
This portlet will introduce you to using JSPs for view rendering and the portlet taglib for generating links.
Portlets are packaged in war files, just like other JEE applications. A typical portlet war file can also include servlets, resource bundles, images, html, jsps, and other static or dynamic files you would commonly include.
![]() |
Included in the download bundle you should have one java source file: HelloWorldPortlet\src\main\org\jboss\portlet\hello\HelloWorldJSPPortlet.java , and it should contain the following:
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);
}
}
Now lets look at some of our methods:
protected void doHelp
AND
protected void doEdit
Support for these Modes must be declared in the portlet.xml. They will be 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 will be triggered upon clicking on an ActionURL from our view.jsp. It will retrieve yourname from the HTML form, and pass it along as a renderParameter to the doView().
rResponse.setContentType("text/html");Just like in the servlet-world, you must declare what content-type the portlet will be responding in.
protected void doView(RenderRequest rRequest, RenderResponse rResponse) throws PortletException, IOException, UnavailableException
In this case, our doView, is responsible for dispatching to the appropriate jsp view.jsp or view2.jsp , depending on the existence of the yourname parameter passed in from the processAction .
JBoss Portal requires certain descriptors be included in your portlet war, for different reasons. Some of these descriptors are defined by the Portlet Specification, and some are specific to JBoss Portal. For brevity, we only discuss the portlet.xml descriptor here. For discussion on the other descriptors, please view Section 5.2.1.4, “The Application Descriptors” or the chapter on descriptors: Section 6.1, “Portlet Descriptors” .
![]() |
portlet.xml
<?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>HelloWorldJSPPortlet</portlet-name>
<portlet-class>org.jboss.portlet.hello.HelloWorldJSPPortlet</portlet-class>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
<portlet-mode>EDIT</portlet-mode>
<portlet-mode>HELP</portlet-mode>
</supports>
<portlet-info>
<title>HelloWorld JSP Portlet</title>
</portlet-info>
</portlet>
</portlet-app>This file must adhere to its definition in the Portlet Specification. You may define more than one portlet application in this file.
Of importance in this tutorial are the two view jsps. The first, allows the user to input his name, which is then posted to the processAction method in our portlet class, set as a renderParameter , then the render method is invoked (in our case its the doView , which then dispatches to our view2.jsp .
![]() |
Now lets have a look at our view.jsp :
<%@ 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 will handle that for you.
<portlet:defineObjects/>
Calling defineObjects creates implicit objects in this jsp, that you can access, like: renderRequest, actionRequest, portletConfig .
<form action="<portlet:actionURL><portlet:param name="page" value="mainview"/></portlet:actionURL>" method="POST">We create an HTML form, but generate the URL it will post to, using the portlet tag library. In this case, notice how we are creating an actionURL , which will activate out processAction method, passing in any input parameters in the form.
<a href="<portlet:renderURL><portlet:param name="yourname" value="Roy Russo"></portlet:param></portlet:renderURL>">
Likewise, we are able to create a link to our doView , by simply creating it with a renderURL , that passes in our yourname parameter.
If you have downloaded the sample, you can execute the build.xml with ANT or inside your IDE. Executing the deploy target will compile all src files and produce a helloworldportlet.war under HelloWorldPortlet\helloworldjspportlet.war.
![]() |
If you want to create an expanded war directory, after executing the above deploy target, you should execute the explode target.
![]() |
The above target will produce the following:
![]() |
This will deflate the helloworldjspportlet.war, and allow you to deploy it as an expanded directory. It will work just the same, with some additional benefits noted below:
The advantage to expanded war deployments is that you can modify xml descriptors, resource files jsp/jsf pages easily during development. Simply touch the web.xml to have JBoss Application Server hot-deploy the web appllication on a live-running server instance
Deploying a portlet is as simple as copying/moving the helloworldjspportlet.war in to the server deploy directory. Doing this on a running instance of the portal and application server, will trigger a hot-deploy :
15:54:34,234 INFO [Server] JBoss (MX MicroKernel) [4.0.4.CR2 (build: CVSTag=JBoss_4_0_4_CR2 date=200603311500)] Started in 1m:9s:766ms
15:55:04,062 INFO [TomcatDeployer] deploy, ctxPath=/helloworldjspportlet, warUrl=.../tmp/deploy/tmp57782helloworldjspportlet-exp.war/
Pointing your browser to http://localhost:8080/portal/ , should yield a view of our HelloWorldPortlet:
![]() |
This section will introduce the reader to deploying a simple JSF portlet in JBoss Portal. It requires you download the HelloWorldJSFPortlet from PortletSwap.com, using this link .
This portlet will introduce you to leveraging the JSF framework in portlet development.
Portlets are packaged in war files, just like other JEE applications. A typical portlet war file can also include servlets, resource bundles, images, html, jsps, and other static or dynamic files you would commonly include.
![]() |
Like a typical JSF application, we also package our faces-config.xml that defines our managed-beans, converters, validators, navigation rules, etc...
JBoss Portal requires certain descriptors be included in your portlet war, for different reasons. Some of these descriptors are defined by the Portlet Specification, and some are specific to JBoss Portal. For brevity, we only discuss the portlet.xml and faces-config.xml descriptors here. For discussion on the other descriptors, please view Section 5.2.1.4, “The Application Descriptors” or the chapter on descriptors: Section 6.1, “Portlet Descriptors” .
![]() |
portlet.xml
<?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>This file must adhere to its definition in the Portlet Specification. You may define more than one portlet application in this file. Now lets look at the portions that deal with our use of JSF:
Here we define our portlet class, as we normally would. However, note the use of the MyFacesGenericPortlet. In this case, we will allow the MyFacesGenericPortlet to handle all requests/responses from our users:
<portlet-class>org.apache.myfaces.portlet.MyFacesGenericPortlet</portlet-class>
We need to initialize the portlet with a default view page for it to render, much like a welcome page:
<init-param> <name>default-view</name> <value>/WEB-INF/jsp/index.jsp</value> </init-param>
faces-config.xml
<?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>There is nothing special about the faces-config.xml included here. This application would work just as well outside of a portlet as it would inside a portlet container. In the above lines, we define a basic User Bean and a navigation rule to handle the submittal of the original form on the index.jsp.
If you have downloaded the sample, you can execute the build.xml with ANT or inside your IDE. Executing the deploy target will compile all src files and produce a helloworldjsfportlet.war under HelloWorldJSFPortlet\helloworldjsfportlet.war.
![]() |
If you want to create an expanded war directory, after executing the above deploy target, you should execute the explode target.
![]() |
The above target will produce the following:
![]() |
This will deflate the helloworldjsfportlet.war, and allow you to deploy it as an expanded directory. It will work just the same, with some additional benefits noted below:
The advantage to expanded war deployments is that you can modify xml descriptors, resource files jsp/jsf pages easily during development. Simply touch the web.xml to have JBoss Application Server hot-deploy the web application on a live-running server instance
Deploying a portlet is as simple as copying/moving the helloworldjsfportlet.war in to the server deploy directory. Doing this on a running instance of the portal and application server, will trigger a hot-deploy :
22:30:03,093 INFO [TomcatDeployer] deploy, ctxPath=/helloworldjsfportlet, warUrl=.../tmp/deploy/tmp5571helloworldjsfportlet-exp.war/ 22:30:03,312 INFO [FacesConfigurator] Reading standard config org/apache/myfaces/resource/standard-faces-config.xml 22:30:03,390 INFO [FacesConfigurator] Reading config jar:file:/C:/jboss-4.0.4.CR2/server/default/tmp/deploy/tmp5504jboss-portal.sar-contents/lib/jsf-facelets.jar!/META-INF/faces-config.xml 22:30:03,406 INFO [FacesConfigurator] Reading config jar:file:/C:/jboss-4.0.4.CR2/server/default/tmp/deploy/tmp5504jboss-portal.sar-contents/lib/tomahawk.jar!/META-INF/faces-config.xml 22:30:03,468 INFO [FacesConfigurator] Reading config /WEB-INF/faces-config.xml 22:30:03,484 ERROR [LocaleUtils] Locale name null or empty, ignoring 22:30:03,640 INFO [MyFacesGenericPortlet] PortletContext 'C:\jboss-4.0.4.CR2\server\default\.\tmp\deploy\tmp5571helloworldjsfportlet-exp.war\' initialized.
Pointing your browser to http://localhost:8080/portal/ , should yield a view of our HelloWorldJSFPortlet:
![]() |
To define your portal objects (portals, pages, portlet instances, windows, and portlets), you will be using the descriptors found in this section. This section seeks to describe these descriptors. It is recommended you also look at Section 5.2, “Tutorials” and Section 6.3, “Descriptor Examples” for samples on how they are used within a portlet application.
The *-object.xml file is used to define: portal instances, pages, windows, window layout. Additionally, you can also specify the themes and layouts used for specific portal instances, pages, and windows. The description below, only defines a portlet window being added to the default page in the default portal. For advanced functionality, using this descriptor, please read Section 6.3, “Descriptor Examples” .
<?xml version="1.0" encoding="UTF-8"?>
<deployments>
<deployment>
<if-exists>overwrite</if-exists>
<parent-ref>default.default</parent-ref>
<window>
<window-name>HelloWorldJSPPortletWindow</window-name>
<instance-ref>HelloWorldJSPPortletInstance</instance-ref>
<region>center</region>
<height>1</height>
</window>
</deployment>
</deployments>
<deployments>...</deployments>
The deployments tag, encapsulates the entire document. You may specify more than one deployment within this tag.
<deployment>...</deployment>
The deployment tag is used to specify object deployments: portals, pages, windows, etc...
<if-exists>...</if-exists>
Possible values are overwrite or keep . Overwrite will destroy the existing object in the database and create a new one, based on the content of the deployment. Keep will maintain the existing object deployment or create a new one if it does not yet exist.
<parent-ref>...</parent-ref>
The parent-ref tag specifies where a particulare object will exist within the portal object tree. In our example, above, we are defining a window and assigning it to default.default , interpreted, this means the window will appear in the default portal and the default page within it.
<window>...</window>
Used to define a portlet window. You will then need to assign to this window, a portlet instance and assign it to a layout region.
<window-name>...</window-name>
A unique name given to this portlet window.
<instance-ref>...</instance-ref>
The portlet instance that this window will represent. It must correspond to the value of instance-id , assigned in your portlet-instances.xml
<region>...</region><height>...</height>
The values are used to specify where this window will appear within the page layout. Region often depends on regions defined in your layout. Height can be any number between 0-X.
The example *-object.xml, above, makes reference to items found in other descriptor files. To help with this topic, we have included a sample image that depicts the relationship:
![]() |
This is a JBoss Portal specific descriptor that allows a developer to instantiate one-or-many instances of one-or-many portlets. The benefit of using this technique, is to allow one portlet to be instantiated several times with different preference parameters.
Our example, below, has us instantiating two separate instances of the NewsPortlet with different preference parameters, one instance will draw a feed for RedHat announcements and the other from McDonalds announcements.
<?xml version="1.0" standalone="yes"?>
<deployments>
<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=rhat</value>
</preference>
</preferences>
<security-constraint>
<policy-permission>
<unchecked/>
<action-name>view</action-name>
</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>
<unchecked/>
<action-name>view</action-name>
</policy-permission>
</security-constraint>
</instance>
</deployment>
</deployments>
<deployments>...</deployments>
The deployments tag, encapsulates the entire document. You may specify more than one portlet instance deployment, within this tag.
<deployment><instance>...</instance></deployment>
The deployment , and embedded instance tags are used to specify one portlet instance.
<instance-id>...</instance-id>
A unique name given to this instance of the portlet. It must correspond to the value of instance-ref , assigned to the window in your *-object.xml .
<portlet-ref>...</portlet-ref>
The portlet that this instance will represent. It must correspond to the value of portlet-name , assigned in your portlet.xml .
<preferences><preference>...</preference></preferences>Preferences for this portlet instance are defined here, as type String, in a key-value pair style. It is also possible to specify preferences as type String[], as in:
<preferences>
<preference>
<name>fruit</name>
<value>apple</value>
<value>orange</value>
<value>kiwi</value>
</preference>
</preferences>
<security-constraint>
<policy-permission>
<unchecked/>
<action-name>viewrecursive</action-name>
</policy-permission>
</security-constraint>The security contraint portion is worth taking a look at, in an isolated fashion. It allows you to secure a specific portlet instance based on a user's role.
Role definition: You must define a role that this security constraint will apply to. Possible values are:
Access Rights: You must define the access rights given to the role defined. Possible values are:
The example portlet-instances.xml, above, makes reference to items found in other descriptor files. To help with this topic, we have included a sample image that depicts the relationship:
![]() |
This descriptor is not mandatory, but is useful when having to add JBoss-Specific contexts to your portlet descriptor. It would normally be packaged inside your portlet war, alongside the other descriptors in this section.
<portlet-app>
<portlet>
<portlet-name>ManagementPortlet</portlet-name>
<header-content>
<link rel="stylesheet" type="text/css" href="/images/management/management.css" title="" media="screen"/>
</header-content>
</portlet>
</portlet-app>The above example will inject a specific style sheet link in the top of the portal page, allowing this portlet to leverage its specific style selectors.
<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>Injects the UserModule service in to the portlet context, allowing a portlet to then leverage the service. For example:
UserModule userModule = (UserModule) getPortletContext().getAttribute("UserModule");
String userId = request.getParameters().getParameter("userid");
User user = userModule.findUserById(userId);
This is the standard portlet descriptor covered by the JSR-168 Specification. It is advisable that developers read the specification items covering proper use of this descriptor, as it is only covered here briefly. For example purposes, we use an editted version of our JBoss Portal UserPortlet definition. Normally, you would package this descriptor in your portlet war.
<?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>Whether we should use ssl on login and throughout the Portal. 1=yes;0=no</description>
<name>useSSL</name>
<value>0</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 tag, encapsulates the entire document. You may specify more than one portlet, within this tag.
<portlet>...</portlet>
The portlet tag is used to define one portlet that is deployed withing this archive.
<description>...</description>
A verbal description of tis portlet's function.
<portlet-name>...</portlet-name>
The name of this portlet, usually the class name
<portlet-class>...</portlet-class>
The fully-qualified-name of this portlet class.
<init-param><name>...</name><value>...</value></init-param>Using the init-param tag, you can specify initialization parameters to create initial state inside your portlet class. Normally, they would be used in the portlet's init() method. You can specify more than one init-param.
<supports>...</supports>
Here, you would advertise the supported mime-type and supported portlet-modes for this portlet.
<supported-locale>...</supported-locale>
Here, you would advertise the supported locales for this portlet. You can specify many.
<resource-bundle>...</resource-bundle>
The resource bundle that will back the locales specified.
<portlet-info><title>...</title></portlet-info>
The portlet title that will be displayed in the portlet window's title bar.
JBoss Portal requires a Datasource descriptor to be deployed alongside the jboss-portal.sar for access to a database. This section does not explain what a Datasource Descriptor is, but does explain where to obtain some templates that you can configure for your own installation.
Several template datasource descriptors can be found in the binary and bundle distributions. They are commonly located under the setup directory:
![]() |
The directory setup should contain the following files, that you can customize for your own Database/Connector:
![]() |
You will need a valid datasource descriptor, for JBoss Portal to communicate with your database. Having obtained the sources and having set your JBOSS_HOME environment variable ( Section 2.3.2.2, “Operating System Environment Setting” ), you can now have the JBoss Portal build system generate preconfigured datasources for you.
Navigate to JBOSS_PORTAL_HOME_DIRECTORY/core and type:
build datasource
![]() |
Once complete, the datasource build should produce the following directory and file structure:
![]() |
At this point, you should configure the one that suits you best with your Database and JDBC driver.
<?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>
Please verify that the username, password, url, and driver-class are correct for your flavor of DB.
By default, JBoss Portal ships with all errors set to display. You can fine-tune this behaviour by modifying the file, jboss-portal.sar/conf/config.xml :
<properties> <!-- 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> </properties>
Either show or hide are allowed as flags in these elements. Depending on the setting and actual error, either an error message is deployed or a full stack trace within the portlet window. Additionally, the core.render.window_error property supports the message_only value. This value will only display the error message whereas show will display the full stack trace if it is available.
This sample application and descriptor will create a new page, named MyPage in your portal. To illustrate our example, we have made available a portlet with a page descriptor that you can download here: HelloWorld Page .
Our sample includes a descriptor to define this new portal page, helloworld-object.xml , located under helloworldportalpage.war/WEB-INF/ , and it looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<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 deployment file can be composed of a set of <deployments>. In our example file, above, we are defining a page, placing the portlet as a window on that page, and creating an instance of that portlet. You can then use the Management Portlet (bundled with JBoss Portal) to modify the instances of this portlet, reposition it, and so on...
<security-constraint>
<policy-permission>
<unchecked/>
<action-name>viewrecursive</action-name>
</policy-permission>
</security-constraint>The security contraint portion is worth taking a look at, in an isolated fashion. It allows you to secure a specific page/portal based on a user's role.
Role definition: You must define a role that this security constraint will apply to. Possible values are:
Access Rights: You must define the access rights given to the role defined. Possible values are:
To illustrate our example, we have made available a portlet that you can download here: HelloPortal .
For our example we make available helloworld-object.xml located under helloworldportal.war/WEB-INF/ , and it looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<deployments>
<deployment>
<parent-ref/>
<if-exists>overwrite</if-exists>
<portal>
<portal-name>HelloPortal</portal-name>
<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>Nphalanx</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>
<!-- set the default strategy name (used by the strategy interceptor) -->
<!-- see also portal-strategies.xml -->
<property>
<name>layout.strategyId</name>
<value>maximizedRegion</value>
</property>
</properties>
<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>
<page>
<page-name>default</page-name>
<properties/>
<window>
<window-name>MyPortletWindow</window-name>
<instance-ref>MyPortletInstance</instance-ref>
<region>center</region>
<height>0</height>
</window>
<security-constraint>
<policy-permission>
<unchecked/>
<action-name>viewrecursive</action-name>
</policy-permission>
</security-constraint>
</page>
<security-constraint>
<policy-permission>
<unchecked/>
<action-name>personalizerecursive</action-name>
</policy-permission>
</security-constraint>
</portal>
</deployment>
<deployment>
<if-exists>overwrite</if-exists>
<parent-ref>HelloPortal</parent-ref>
<page>
<page-name>foobar</page-name>
<window>
<window-name>MyPortletWindow</window-name>
<instance-ref>MyPortletInstance</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>
This example, when deployed, will register a new portal instance named HelloPortal with two pages in it. The portal instance can be accessed by navigating to: http://localhost:8080/portal/portal/HelloPortal for the default page, and http://localhost:8080/portal/portal/HelloPortal/foobar , for the second page created.
Most of the time portals use very complicated urls, however it is possible to setup entry points in the portal that follow simple patterns.
Each portal container can contain multiple portals and within a given portal, windows are organized in pages, a page simply being a collection of windows associated to a name.
Before reading this chapter you must know how to define a page and a portal, you can refer to the chapter about XML descriptors to have a better understanding of those notions.
Each portal container can contains multiple portals, also there is one special portal which is the default portal, i.e the one used when no portal is specified in particular.
It is possible to have multiple pages per portal. As for portal there is a default page for a given portal. Once the portal has been selected, then a page must be used and all the windows present in that page will be rendered. The page selection mechanism is the following.
The CMSPortlet delivers content transparently, without modifying the url displayed. However, if you wish to deliver binary content (gif, jpeg, pdf, zip, etc...), it is desirable to display this content outside of the confines of the portal.
This section covers configuring JBoss Portal to function in a clustered environment.
JBoss Portal leverages various clustered services that are found in JBoss Application Server. This section briefly details how each is leveraged:
JBoss Cache: Used to replicate data among the different hibernate session factories that are deployed in each node of the cluster.
JBoss HA Singleton:
HA-JNDI: Used to replicate a proxy that will talk to the HA CMS on the cluster.
Http Session Replication: Used to replicate the portal and the portlet sessions.
JBoss SSO: Used to replicate the user identity, an authenticated user does not have to login again when failover occurs.
When you want to run JBoss Portal on a cluster there are a few things to keep in mind:
The portal associates with each user an http session in order to keep specific objects such as:
Replicating the portal session ensures that this state will be kept in sync on the cluster, e.g he will see the portlet window he uses exactly the same on every node. The activation of the portal session replication is made through the configuration of the web application that is the main entry point of the portal. This setting is available in the file jboss-portal.sar/portal-server.war/WEB-INF/web.xml
<web-app> <description>JBoss Portal</description> <!-- Comment/Uncomment to enable portal session replication --> <distributable/> ... </web-app>
JBoss Portal leverages hibernate for its database access. In order to improve performances it uses the caching features provided by hibernate. On a cluster the cache needs to be replicated in order to avoid state inconsistencies. Hibernate is configured with JBoss Cache which performs that synchronization transparently. Therefore the different hibernate services must be configured to use JBoss Cache. The following hibernate configurations needs to use a replicated JBoss Cache :
The cache configuration should look like :
<!-- | Uncomment in clustered mode : use transactional replicated cache --> <property name="cache.provider_class">org.jboss.portal.core.hibernate.JMXTreeCacheProvider</property> <property name="cache.object_name">portal:service=TreeCacheProvider,type=hibernate</property> <!-- | Comment in clustered mode <property name="cache.provider_configuration_file_resource_path">conf/hibernate/instance/ehcache.xml</property> <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property> -->
Also we need to ensure that the cache is deployed by having in the file jboss-portal.sar/META-INF/jboss-service.xml the cache service uncommented :
<!-- | Uncomment in clustered mode : replicated cache for hibernate --> <mbean code="org.jboss.cache.TreeCache" name="portal:service=TreeCache,type=hibernate"> <depends>jboss:service=Naming</depends> <depends>jboss:service=TransactionManager</depends> <attribute name="TransactionManagerLookupClass">org.jboss.cache.JBossTransactionManagerLookup</attribute> <attribute name="IsolationLevel">REPEATABLE_READ</attribute> <attribute name="CacheMode">REPL_SYNC</attribute> <attribute name="ClusterName">portal.hibernate</attribute> </mbean> <mbean code="org.jboss.portal.core.hibernate.JBossTreeCacheProvider" name="portal:service=TreeCacheProvider,type=hibernate"> <depends optional-attribute-name="CacheName">portal:service=TreeCache,type=hibernate</depends> </mbean>
More information can be found here.
JBoss Portal leverages the servlet container authentication for its own authentication mechanism. When the user is authenticated on one particular node he will have to reauthenticate again if he use another node of the cluster (during a failover for instance). 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 is in the file $JBOSS_HOME/server/all/deploy/jbossweb-tomcat55.sar/server.xml and the clustered sso valve shall be uncommented
<Valve className="org.jboss.web.tomcat.tc5.sso.ClusteredSingleSignOn" />
More information can be found here.
The CMS backend storage relies on the Apache Jackrabbit project. Jackrabbit does not support clustering out of the box. So the portal run the Jackrabbit servicey 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.

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 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 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">node-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 copy the file portal-postgresql-ds.xml into $JBOSS_HOME/server/ports-01/all and $JBOSS_HOME/server/ports-02/all.
Copy JBoss Portal HA to the deploy directory of the two configurations.
JBoss Cache Configuration 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:
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 >./run.sh -c ports-01
>cd $JBOSS_HOME/bin >./run.sh -c ports-02
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 :
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
There are also some limitation such has you can only replicate portlet scoped attributes of a portlet session. It means that any attribute scoped using application scope are not replicated.
The mandatory step to make JBoss Portal able to replicate portlet sessions is to configure the portal web application to be distributed which is explained in Section 8.3.1, “Portal Session Replication”
In order to activate portlet session replication you need to
<web-app>
...
<listener>
<listener-class> org.jboss.portal.portlet.session.SessionListener </listener-class>
</listener>
...
</web-app>
Example of web.xml file of your web application
<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
As we noted above there are advantages as well as limitations to the clustering configuration
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);
}
...
}
Configures YourPortlet to be replicated in jboss-portlet.xml
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:
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.
JBoss Portal provides a base level support of the WSRP 1.0 standard 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 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.
JBoss Portal does not, by default, expose local portlets for consumption by remote WSRP consumers. In order to make a portlet remotely available, a jboss-portlet.xml deployment descriptor for that portlet must be added to the WEB-INF folder of the web application containing the portlet and must be similar to the example below:
<?xml version="1.0" encoding="UTF-8"?>
<portlet>
<portlet-name>BasicPortlet</portlet-name>
<remotable>true</remotable>
</portlet>
Here, the portlet named "BasicPortlet" is specified as being remotable. The "remotable" element is optional.
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. 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:
<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.
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.
JBoss Portal's Producer is automatically set up when you deploy a portal instance. Assuming you're running a default configuration (i.e. you haven't changed the server's port number), you can access the WSDL file at http://localhost:8080/portal-wsrp/MarkupService?wsdl. You can acces the endpoint URLs are:
To be able to consume WSRP portlets from a remote producer, JBoss Portal's WSRP consumer needs to know how to access the remote producer. This is done via -wsrp.xml descriptors that provide JBoss Portal's consumer information about which remote producers to access and with which configuration. These files can be dropped in the deploy directory of the JBoss application server or nested in .sar files for examples. It is possible to configure access to several different producers within a single -wsrp.xml file or use one file per producer.
JBoss Portal's producer exposes its information to the Portal itself as a default consumer with the identifier self. That means that all the remotable portlets are also exposed as remote portlets in the portal. The portal-wsrp.sar file contains the file default-wsrp.xml that contains this default producer. This file can be edited or removed if needed.
Once a remote producer has been configured in a -wsrp.xml file, it becomes available in the list of portlet provider 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.
Let's see how it works step by step. Let's create a public-bea-wsrp.xml file as follows:
<deployments>
<deployment>
<wsrp-producer>
<producer-id>bea</producer-id>
<expiration-cache>120</expiration-cache>
<endpoint-wsdl-url>http://wsrp.bea.com:7001/producer/producer?WSDL</endpoint-wsdl-url>
<registration-data>
<consumer-name>JBoss Portal 2.4 Test</consumer-name>
<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).
Let's now look at the Admin page and the management portlet. Click on the "Portlets" link at the top to manage the portlets. 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 and bea. The "local" portlet provider exposes all the portlets deployed in this particular instance of Portal. The "self" provider is 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 "Change portlet provider". You should now see something similar to:
![]() |
From there on out, you should be able to configure the portlet just as any other, baring the restriction that the WSRP Portlet Management interface is not yet supported in 2.4. If everything went well, you created an instance of the portlet and assigned it to a window in a page. If you go to that page, you should see something similar to below for this portlet:
![]() |
Let's 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 via the <producer-id> element.
JBoss Portal also needs to learn about the remote producer's endpoints to be able to connect to the web services and perform the WSRP invocations. Two options are currently provided to inform JBoss Portal of how to connect to the remote web service, both by providing the required information via children elements:
Both <producer-id> and either <endpoint-config> or <endpoint-wsdl-url> are required elements for a functional remote producer 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 is 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). Such information is refreshed periodically. The rate at which the information is refreshed is defined by the <expiration-cache> element which specifies the refreshing period in seconds.
Additionally, some producers require consumers to register with them before authorizing them to access their offered portlets. JBoss Portal currently only supports a very basic subset of in-band registration and it is thus possible to provide required registration information in the producer configuration so that the Portal consumer can register with the remote producer when required.
Registration configuration is done via the <registration-datat> element. We need to provide a consumer name (via the <consumer-name> element) for our consumer and then provide a list of values for the registration properties required by the remote producer via <property> elements. See the example below for more details.
Here is an example of a WSRP descriptor with a 2 minutes caching time and manual definition of the endpoint URLs:
<?xml version="1.0" encoding="UTF-8"?>
<deployments>
<deployment>
<wsrp-producer>
<producer-id>MyProducer</producer-id>
<expiration-cache>120</expiration-cache>
<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:
<?xml version="1.0" encoding="UTF-8"?>
<deployments>
<deployment>
<wsrp-producer>
<producer-id>AnotherProducer</producer-id>
<expiration-cache>60</expiration-cache>
<endpoint-wsdl-url>http://example.com/producer/producer?WSDL</endpoint-wsdl-url>
<registration-data>
<consumer-name>JBoss Portal 2.4 Test</consumer-name>
<property>
<name>property name</name>
<lang>en</lang>
<value>property value</value>
</property>
</registration-data>
</wsrp-producer>
<deployment>
</deployments>
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.1.1, “*-object.xml” ), for Portal Instances and Pages, or the portlet-instances.xml ( Section 6.1.2, “portlet-instances.xml” ) 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"?>
<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 security constraint on an object (our example above, secures a specific portal page), is explained as:
<security-constraint>
<policy-permission>
<unchecked/>
<action-name>viewrecursive</action-name>
</policy-permission>
</security-constraint>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:
Access Rights: You must define the access rights given to the role defined. Possible values are:
We provide three live samples of this descriptor, here Section 6.1.2, “portlet-instances.xml” , Section 6.3.1, “Defining a new portal page” ,and Section 6.3.2, “Defining a new portal instance”
JBoss Portal packages a Web Content Management System capable of serving and allowing administration of web content. This chapter describes the CMS Portlet which is responsible for serving resources requested, the following chapter describes the CMSAdmin Portlet and all administration functionality.
![]() |
The CMS Portlet displays content from the file store inside a portlet window, or, in the case of binary content, outside of the portlet window altogether.
The CMSPortlet handles all requests for all content types.
The methodology of serving content within the CMSPortlet, allows for some beneficial features, like:
The CMS portlet default page is defined as a preference and can be overriden like any other preference up to the user's preference level. The default CMS portlet displayed when you install JBoss Portal for the first time is describe in the following file: jboss-portal.sar/portal-core.war/WEB-INF/portlet.xml .
<portlet-preferences>
<preference>
<name>indexpage</name>
<value>/default/index.html</value>
</preference>
</portlet-preferences>
The preference key is "indexpage". To change the default page, just make sure to create an html document using the CMS Admin portlet then change the value of "indexpage" to the corresponding path.
JBoss Portal uses Apache Jackrabbit as its Java Content Repository implementation. Configuration of the service descriptor, allows for changing many of the variables associated with the service.
Here is the default configuration for the CMS repository found under portal-cms.sar/META-INF-INF/jboss-service.xml
...
<attribute name="DoChecking">true</attribute>
<attribute name="DefaultContentLocation">portal/cms/conf/default-content/default/</attribute>
<attribute name="DefaultLocale">en</attribute>
<attribute name="RepositoryName">PortalRepository</attribute>
<attribute name="HomeDir">${jboss.server.data.dir}${/}portal${/}cms${/}conf</attribute>
Below is a list of items found in the service descriptor and their definitions. Only items commonly changed are covered here and it is recommended you do not change any others unless you are very brave.
By default, the content will be accessible to a url like this: http://www.example.com/content/[...], if you need or prefer to change "content" to something else you will need to edit the following file: portal-cms.sar/META-INF-INF/jboss-service.xml and change the value of Prefix to something else. Please note that you cannot change it to "nothing", you need to provide a value.
...
<mbean
code="org.jboss.portal.core.cms.CMSObjectCommandFactory"
name="portal:commandFactory=CMSObject"
xmbean-dd=""
xmbean-code="org.jboss.portal.common.system.JBossServiceModelMBean">
<xmbean/>
<attribute name="Prefix">content</attribute>
<attribute name="TargetWindowRef">default.default.CMSPortletWindow</attribute>
<depends optional-attribute-name="Factory" proxy-type="attribute">portal:commandFactory=Delegating</depends>
<depends optional-attribute-name="CMSService" proxy-type="attribute">portal:service=CMS</depends>
</mbean>
...
By default, the JBoss Portal CMS stores all node properties, references, and binary content in the database, using the portal datasource. The location of some of these items is configurable, and there are 3 options:
To enable 100% Filesystem storage, you must edit the file: jboss-portal.sar/portal-cms.sar/META-INF/jboss-service.xml . You will note that the file is set to use the HibernateStore and HibernatePersistenceManager classes, by default. To have the CMS use 100% file system storage, simply comment these blocks. Then, you should uncomment to use the LocalFileSystem and XMLPersistenceManager classes. Follow these steps to activate 100% FS storage:
Comment out the following blocks (there are 3 in total):
<!-- HibernateStore: uses RDBMS + Hibernate for storage --> <FileSystem class="org.jboss.portal.cms.hibernate.HibernateStore"> ... </FileSystem>
And uncomment the blocks under them (there are 3 in total):
<!-- LocalFileSystem: uses FileSystem for storage. --> <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem"> ... </FileSystem>
Now comment out the following blocks (there are 2 in total):
<!-- HibernatePersistentManager: uses RDBMS + Hibernate for storage --> <PersistenceManager class="org.jboss.portal.cms.hibernate.state.HibernatePersistenceManager"> ... </PersistenceManager>
And uncomment the blocks under them (there are 2 in total):
<!-- XMLPersistenceManager: uses FileSystem for storage --> <PersistenceManager class="org.apache.jackrabbit.core.state.xml.XMLPersistenceManager"/>
This is the default configuration for the CMS store. Please view the original jboss-portal.sar/portal-cms.sar/META-INF/jboss-service.xml , for guidance on how to reset it.
Mixed storage consists of meta-data being stored in the DB and blobs being stored on the Filesystem. This is the recommended setting for those of you that serve large files or stream media content.
Setting the repository this way is simple. Change every instance in the file jboss-portal.sar/portal-cms.sar/META-INF/jboss-service.xml , from:
<param name="externalBLOBs" value="false"/>
to:
<param name="externalBLOBs" value="true"/>
The CMS Portlet now serves content based on the user's locale setting. For example: if a user's locale is set to Spanish in his browser, and he requests URL: default/index.html , the CMSPortlet will first try and retrieve the Spanish version of that file. If a Spanish version is not found, it will then try and retrieve the default language version set for the CMSPortlet.
The CMS portlet calls a CMS service that can be reused in your own portlets.
Since JBoss Portal 2.4 you can add your own interceptor stack to the CMS service. The interceptors are called around each command (Get a file, write a file, create a folder...), this is a very easy way to customize some actions based on your needs.
To create your own interceptor you just need to extend the org.jboss.portal.cms.CMSInterceptor class and provide the content of the invoke(JCRCommand) method. Do not forget to make a call to JCRCommand.invokeNext() or the command will never be executed.
JBoss Portal provides two CMS interceptors out of the box, a very basic Log interceptor ( org.jboss.portal.cms.impl.interceptors.LogInterceptor ) that prints all the commands called. And a cache interceptor to enable distributed caching or content ( org.jboss.portal.cms.impl.interceptors.CacheInterceptor ). For more information about the cache interceptor, see below.
To add or remove an interceptor, you just need to edit the following file: portal-cms-sar/META-INF/jboss-service.xml. It works the same way as the server interceptor, for each interceptor you need to define an mbean then add it to the cms interceptor stack. For example, if you have the 2 default interceptors, you should have the following lines in the jboss-service.xml file:
<mbean
code="org.jboss.portal.cms.impl.interceptors.LogInterceptor"
name="portal:service=Interceptor,type=Cms,name=Log"
xmbean-dd=""
xmbean-code="org.jboss.portal.common.system.JBossServiceModelMBean">
<xmbean/>
</mbean>
<mbean
code="org.jboss.portal.cms.impl.interceptors.CacheInterceptor"
name="portal:service=Interceptor,type=Cms,name=Cache"
xmbean-dd=""
xmbean-code="org.jboss.portal.common.system.JBossServiceModelMBean">
<xmbean/>
<depends>portal:service=CMSTreeCache</depends>
</mbean>
<mbean
code="org.jboss.portal.server.impl.invocation.JBossInterceptorStack"
name="portal:service=InterceptorStack,type=Cms"
xmbean-dd=""
xmbean-code="org.jboss.portal.common.system.JBossServiceModelMBean">
<xmbean/>
<depends-list optional-attribute-name="InterceptorNames">
<depends-list-element>portal:service=Interceptor,type=Cms,name=Log</depends-list-element>
<depends-list-element>portal:service=Interceptor,type=Cms,name=Cache</depends-list-element>
</depends-list>
</mbean>
The first two mbeans define the interceptors and the third mbean, define which interceptors to add to the CMS service.
If you create your own interceptor org.example.myCMSInterceptor, the service descriptor file will look like:
<mbean
code="org.example.myCMSInterceptor"
name="portal:service=Interceptor,type=Cms,name=MyName"
xmbean-dd=""
xmbean-code="org.jboss.portal.common.system.JBossServiceModelMBean">
<xmbean/>
</mbean>
<mbean
code="org.jboss.portal.cms.impl.interceptors.LogInterceptor"
name="portal:service=Interceptor,type=Cms,name=Log"
xmbean-dd=""
xmbean-code="org.jboss.portal.common.system.JBossServiceModelMBean">
<xmbean/>
</mbean>
<mbean
code="org.jboss.portal.cms.impl.interceptors.CacheInterceptor"
name="portal:service=Interceptor,type=Cms,name=Cache"
xmbean-dd=""
xmbean-code="org.jboss.portal.common.system.JBossServiceModelMBean">
<xmbean/>
<depends>portal:service=CMSTreeCache</depends>
</mbean>
<mbean
code="org.jboss.portal.server.impl.invocation.JBossInterceptorStack"
name="portal:service=InterceptorStack,type=Cms"
xmbean-dd=""
xmbean-code="org.jboss.portal.common.system.JBossServiceModelMBean">
<xmbean/>
<depends-list optional-attribute-name="InterceptorNames">
<depends-list-element>portal:service=Interceptor,type=Cms,name=Log</depends-list-element>
<depends-list-element>portal:service=Interceptor,type=Cms,name=Cache</depends-list-element>
<depends-list-element>portal:service=Interceptor,type=Cms,name=MyName</depends-list-element>
</depends-list>
</mbean>
The interceptor order is important ! For example the cache interceptor may stop the call, so if you place the log interceptor after the call you wouldn't see all the commands that have been executed by the portlets.
To check that the interceptors have been correctly added, you can check the JMX console, by going to: http://localhost.localdomain:8080/jmx-console/HtmlAdaptor?action=inspectMBean&name=portal%3Aservice%3DInterceptorStack%2Ctype%3DCms You should notice all the interceptors in the attribute "interceptors".
Portals usually render the markup fragments of several portlets, and aggregate these fragments into one page that ultimately gets sent back as response. Each portlet on that page will be decorated by the portal to limit the real estate the portlet has on the page, but also to allow the portal to inject extra functionality on a per portlet basis. Classic examples of this injection are the maximize, minimize and mode change links that will appear in the portlet window , together with the title.
Layouts and themes allow to manipulate the look and feel of the portal. Layouts are responsible to render markup that will wrap the markup fragments produced by the individual portlets. Themes, on the other hand, are responsible to style and enhance this markup.
In JBoss Portal, layouts are implemented as a JSP or a Servlet. Themes are implemeted using CSS Style sheets, java script and images. The binding elemement between layouts and themes are the class and id attributes of the rendered markup.
JBoss Portal has the concept of regions on a page. When a page is defined, and portlet windows are assigned to the page, the region, and order inside the region, has to be specified as well. For portal layouts this has significant meaning. It defines the top most markup container that can wrap portlet content (other then the static markup in the JSP itself). In other words: from a layout perspective all portlets of a page are assigned to one or more regions. Each region can contain one or more portlets. To render the page content to return from a portal request, the portal has to render the layout JSP, and for each region, all the portlets in the region.
Since the markup around each region, and around each portlet inside that region, is effectively the same for all the pages of a portal, it makes sense to encapsulate it in its own entity.
To implement this encapsulation there are several ways:
In JBoss Portal you can currently see two out of these approaches, namley the first and the last. Examples for the first can be found in the portal-core.war, implemented by the nodesk and phalanx layouts. Examples for the third approach can be found in the same war, implemented by the industrial and Nphalanx layout. What encapsulates the markup generation for each region, window, and portlet decoration in this last approach is what's called the RenderSet.
The RenderSet consist of four interfaces that correspond with the four markup containers that wrap the markup fragments of one of more portlets:
While we want to leave it open to you to decide which way to implement your layouts and themes, we strongly believe that the last approach is superior, and allows for far more flexibility, and clearer separation of duties between portal developers and web designers.
Portal layouts also have the concept of a layout strategy. The layout strategy is a pluggable API, and lets the layout developer have a last say about the content to be rendered. The strategy is called right after the portal has determined what needs to be rendered as part of the current request. So the strategy is invoked right between the point where the portal knows what needs to be done, and before the actual work is initiated. The strategy gets all the details about what is going to happen, and it can take measures to influence those details.
Some simple examples of those measures are:
The last topic to introduce in this overview is the one of portal themes. A theme is a collection of web design artifacts. It defines a set of css, java script and image files that together decide about the look and feel of the portal page. The theme can take a wide spectrum of control over the look and feel. It can limit itself to decide fonts and colors, or it can take over a lot more and decide the placement (location) of portlets and much more.
Layouts are used by the portal to produce the actual markup of a portal response. After all the portlets on a page have been rendered and have produced their markup fragments, the layout is responsible for aggregating all these pieces, mix them with some ingredients from the portal itself, and at the end write the response back to the requesting client.
Layouts can be either a JSP or a Servlet. The portal determines the layout to use via the configured properties of the portal, or the requested page. Both, portal and pages, can define the layout to use in order to render their content. In case both define a layout, the layout defined for the page will overwrite the one defined for the portal.
A Layout is defined in the layout descriptor named portal-layouts.xml. This descriptor must be part of the portal application, and is picked up by the layout deployer. If the layout deployer detects such a descriptor in a web application, it will parse the content and register the layouts with the layout service of the portal. Here is an example of such a descriptor file:
<layouts>
<layout>
<name>phalanx</name>
<uri>/phalanx/index.jsp</uri>
</layout>
<layout>
<name>industrial</name>
<uri>/industrial/index.jsp</uri>
<uri state="maximized">/industrial/maximized.jsp</uri>
</layout>
</layouts>
Portals and pages can be configured to use a particular layout. The connection to the desired layout is made in the portal descriptor (YourNameHere-object.xml). Here is an example of such a portal descriptor:
<portal>
<portal-name>default</portal-name>
<properties>
<!-- Set the layout for the default portal -->
<!-- see also portal-layouts.xml -->
<property>
<name>layout.id</name>
<value>phalanx</value>
</property>
</properties>
<pages>
<page>
<page-name>theme test</page-name>
<properties>
<!-- set a difference layout for this page -->
<property>
<name>layout.id</name>
<value>industrial</value>
</property>
</properties>
</page>
</pages>
</portal>The name specified for the layout to use has to match one of the names defined in the portal-layouts.xml descriptor of one of the deployed applications.
As you can see, the portal or page property points to the layout to use via the name of the layout. The name has been given to the layout in the layout descriptor. It is in that layout descriptor where the name gets linked to the physical resource (the JSP or Servlet) that will actually render the layout.
To access a layout from code, you need to get a reference to the LayoutService interface. The layout service is an mbean that allows access to the PortalLayout interface for each layout that was defined in a portal layout descriptor. As a layout developer you should never have to deal with the layout service directly. Your layout hooks are the portal and page properties to configure the layout, and the layout strategy, where you can change the layout to use for the current request, before the actual render process begins.
Both descriptors, the portal and the theme descriptor, are located in the WEB-INF/ folder of the deployed portal application. Note that this is not limited to the portal-core.war, but can be added to any WAR that you deploy to the same server. The Portal runtime will detect the deployed application and introspect the WEB-INF folder for known descriptors like the two metioned here. If present, the appropriate meta data is formed and added to the portal runtime. From that time on the resources in that application are available to be used by the portal. This is an elegant way to dynamically add new layouts or themes to the portal without having to bring down , or even rebuild the core portal itself.
As you might have noticed already, a layout definition consists of a name and one or more uri elements. We have already seen the function of the name element. Now let's take a closer look at the uri element. In the example above, the phalanx layout defined one uri element only, the industrial layout defines two. What you can see in the industrial layout is the option of defining different uri's for different states. In this example , we configured the layout to use a different JSP if the layout state is maximized. If no such separation is made in the layout descriptor, then the portal will always use the same JSP for this layout. Note that the 'state' attribute value works together with the state that was set by the layout strategy. Please refere to the section about the layout strategy for more details.
The portal comes with a set of JSP tags that allow the layout developer faster development.
There are currently two taglibs, containing tags for different approaches to layouts:
The theme-basic-lib.tld contains a list of tags that allow a JSP writer to access the state of the rendered page content. It is built on the assumption that regions, portlet windows and portlet decoration is managed inside the JSP.
The portal-layout.tld contains tags that work under the assumption that the RenderSet will take care of how regions, portlet windows and the portlet decoration will be rendered. The advantage of this approach is that the resulting JSP is much simpler and easier to read and maintain.
Here is an example layout JSP that uses tags from the latter:
<%@ taglib uri="/WEB-INF/theme/portal-layout.tld" prefix="p" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>JBoss Portal: 2.2 early (Industrial)</title>
<meta http-equiv="Content-Type" content="text/html;" />
<p:theme themeName='phalanx' />
<p:headerContent />
</head>
<body id="body">
<div id="portal-container">
<div id="sizer">
<div id="expander">
<div id="logoName"></div>
<table border="0" cellpadding="0" cellspacing="0" id="header-container">
<tr>
<td align="center" valign="top" id="header"><div id="spacer"></div></td>
</tr>
</table>
<div id="content-container">
<p:region regionName='This-Is-The-Page-Region-To-Query-The-Page'
regionID='This-Is-The-Tag-ID-Attribute-To-Match-The-CSS-Selector'/>
<p:region regionName='left' regionID='regionA'/>
<p:region regionName='center' regionID='regionB'/>
<hr class="cleaner" />
<div id="footer-container" class="portal-copyright">Powered by
<a class="portal-copyright" href="http://www.jboss.com/products/jbossportal">JBoss Portal</a><br/>
Theme by <a class="portal-copyright" href="http://www.novell.com">Novell</a>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
The theme tag looks for the determined theme of the current request (see Portal Themes for more details). If no theme was determined, this tag allows an optional attribute 'themeName' that can be used to specifiy a default theme to use as a last resort. Based on the determined theme name, the ThemeService is called to lookup the theme with this name and to get the resources associated with this theme. The resulting style and link elements are injected, making sure that war context URLS are resolved appropriately.
This tags allows portlets to inject content into the header. More details about this function are mentioned in the 'other Theme Functions' section of this document.
The region tag renders all the portlets in the specified region of the current page, using the determined RenderSet to produce the markup that surrounds the individual portlet markup fragments. The regionName attribute functions as a query param into the current page. It determines from what page region the portlets will be rendered in this tag. The regionID attribute is what the RenderSet can use to generate a css selector for this particular region. In case of the divRenderer, a DIV tag with an id attribute corresponding to the provided value will be rendered for this region. This id in turn can be picked up by the CSS to style the region.
The layout strategy is a pluggable API that allows the layout developer to influence the content of the page that is about to be rendered. Based on the current request URL, the portal determined the portal and page that needs to be rendered. The page contains a list of portlets, and those portlets are in a particular navigational state. The navigational state consists of the portlet mode and the window state of the portlet. This information, togeher with the determined layout, the region and order assignments of each portlet, the allowed window states and portlet modes for both, the portal and the individual portlets, is passed to the layout strategy before the actual rendering is invoked. The layout strategy can check what is about to be rendered, and take action in a limited way to influence the content that is about to be rendered.
A layout strategy is defined in the strategy descriptor. The descriptor is named portal-strategies.xml, and is located in the WEB-INF/layout folder of any web application deployed to the server. Here is an example of such a descriptor:
<portal-strategies>
<set name="default">
<strategy content-type="text/html">
<implementation>org.jboss.portal.theme.impl.strategy.DefaultStrategyImpl</implementation>
</strategy>
</set>
<set name="maximizedRegion">
<strategy content-type="text/html">
<implementation>org.jboss.portal.theme.impl.strategy.MaximizingStrategyImpl</implementation>
</strategy>
</set>
</portal-strategies>
Layout strategies are defined as sets. A set consists of one or more strategy definitions, separated by content type they are assigned for. The idea behind this is to allow the layout developer to apply different strategies based on requested content type. Each set has a name that is unique in the application context it is deployed in. The strategy can be refered to by this name. As a result of that it is considered a named layout strategy in contrast to an anonymous strategy as described below.
The strategy that will be used for a portal request is defined as a property of the current layout, the requested portal, or the requested page. If the layout defines a strategy to use it will overwrite all other assignments. If there is no particular strategy defined for the layout, then the page property will overwrite the portal property. If no strategy can be determined, then a last attempt will be made to use the strategy with the name 'default'. If no strategy can be determined at all, the request will proceed normally without invoking any strategy. Here is an example layout descriptor that defines a strategy for the layouts defined:
<layouts>
<strategy content-type="text/html">
<implementation>com.novell.portal.strategy.MaximizingStrategy</implementation>
</strategy>
<layout>
<name>generic</name>
<uri>/generic/index.jsp</uri>
<uri state="maximized">/generic/maximized.jsp</uri>
</layout>
</layouts>
In this case the strategy is anonymous and directly assigned to the generic layout. The strategy cannot be discovered independently from the generic layout. Here is an example portal descriptor that points to a strategy for the portal, and for a particular page:
<portal>
<portal-name>default</portal-name>
<properties>
<property>
<name>layout.strategyId</name>
<value>default</value>
</property>
</properties>
<pages>
<default-page>theme test</default-page>
<page>
<page-name>theme test</page-name>
<properties>
<!-- set a difference layout strategy for this page -->
<property>
<name>layout.strategyId</name>
<value>maximizedRegion</value>
</property>
</properties>
<window>
<window-name>CatalogPortletWindow</window-name>
<instance-ref>CatalogPortletInstance</instance-ref>
<region>left</region>
<height>0</height>
</window>
</page>
</pages>
</portal>
As you can see, analogous to how layouts are refered to, the strategy name is the linking element between the portal descriptor and the layout strategy descriptor. The content type is determined at runtime, and serves as a secondary query parameter to get the correct strategy for this content type out of the set that matches the name provided in the portal descriptor.
As mentioned above, the layout descriptor can link a strategy directly to the layout. This will overwrite all other defined strategies for the portal or the page, for any page that uses this layout.
The layout strategy can set a state to return to the portal as a result of the strategy evaluation. This state will be matched with the state attribute of the uri element of the layout. If there is a match, then the uri that matches this state will be used as the layout for the current request. So, if the strategy sets a state of 'maximized' , the portal will try to use the layout resource that is pointed to for that particular state in the currently selected layout. As you might remember from the previous layout section, a layout can point to another JSP or Servlet based on the state attribute of the uri element, like so:
<layouts>
<layout>
<name>industrial</name>
<uri>/industrial/index.jsp</uri>
<uri state="maximized">/industrial/maximized.jsp</uri>
</layout>
</layouts>In this case all reuquests that don't return a state 'maximized' from the evaluation of the strategy will use the /industrial/index.jsp as the layout. However, if the evaluation of the strategy returns a state of 'maximized' then the request will use /industrial/maximized.jsp as the layout.
A RenderSet can be used to produce the markup containers around portlets and portlet regions. The markup for each region, and each portlet window in a region is identical. Further more, it is most likely identical across several layouts. The way portlets are arranged and decorated will most likely not change across layouts. What will change is the look and feel of the decoration, the images, fonts, and colors used to render each portlet window on the page. This is clearly a task for the web designer, and hence should be realized via the portal theme. The layout only needs to provide enough information to the theme so that it can do its job. The RenderSet is exactly that link between the layout and the theme that takes the information available in the portal and renders markup containing the current state of the page and each portlet on it. It makes sure that the markup around each region and portlet contains the selectors that the theme css needs to style the page content appropriately.
A RenderSet consists of the implementations of four interfaces. Each of those interfaces corresponds to a markup container on the page.
Here are the four markup containers and their interface representation:
All the renderer interfaces are specified in the org.jboss.portal.theme.render package.
The four markup containers are hierarchical. The region contains one or more windows. A window contains the portlet decoration and the portlet content.
The region is responsible for arranging the positioning and order of each portlet window. Should they be arranged in a row or a column? If there are more then one portlet window in a region, in what order should they appear?
The window is responsible for placing the window decoration, including the portlet title, over the portlet content, or under, or next to it.
The decoration is responsible for inserting the correct markup with the links to the portlet modes and window states currently available for each portlet.
The portlet content is responsible for inserting the actually rendered markup fragment that was produced by the portlet itself.
Similar to layouts, render sets must be defined in a RenderSet descriptor. The RenderSet descriptor is located in the WEB-INF/layout folder of a web application, and is named portal-renderSet.xml. Here is an example descriptor:
<?xml version="1.0" encoding="UTF-8"?>
<portal-renderSet>
<renderSet name="divRenderer">
<set content-type="text/html">
<region-renderer>org.jboss.portal.theme.impl.render.DivRegionRenderer</region-renderer>
<window-renderer>org.jboss.portal.theme.impl.render.DivWindowRenderer</window-renderer>
<portlet-renderer>org.jboss.portal.theme.impl.render.DivPortletRenderer</portlet-renderer>
<decoration-renderer>org.jboss.portal.theme.impl.render.DivDecorationRenderer</decoration-renderer>
</set>
</renderSet>
<renderSet name="emptyRenderer">
<set content-type="text/html">
<region-renderer>org.jboss.portal.theme.impl.render.EmptyRegionRenderer</region-renderer>
<window-renderer>org.jboss.portal.theme.impl.render.EmptyWindowRenderer</window-renderer>
<portlet-renderer>org.jboss.portal.theme.impl.render.EmptyPortletRenderer</portlet-renderer>
<decoration-renderer>org.jboss.portal.theme.impl.render.EmptyDecorationRenderer</decoration-renderer>
</set>
</renderSet>
</portal-renderSet>
Analogous to how a strategy is specified, the RenderSet can be specified as a portal or page property, or a particular layout can specify an anonymous RenderSet to use. Here is an example of a portal descriptor:
<?xml version="1.0" encoding="UTF-8"?>
<portal>
<portal-name>default</portal-name>
<properties>
<!-- use the divRenderer for this portal -->
<property>
<name>theme.renderSetId</name>
<value>divRenderer</value>
</property>
</properties>
<pages>
<default-page>default</default-page>
<page>
<page-name>default</page-name>
<properties>
<!-- overwrite the portal's renderset for this page -->
<property>
<name>theme.renderSetId</name>
<value>emptyRenderer</value>
</property>
</properties>
<window>
<window-name>TestPortletWindow</window-name>
<instance-ref>TestPortletInstance</instance-ref>
<region>center</region>
<height>0</height>
</window>
</page>
</pages>
</portal>
Here is an example of a layout descriptor with an anonymous RenderSet:
<?xml version="1.0" encoding="UTF-8"?>
<layouts>
<renderSet>
<set content-type="text/html">
<region-renderer>org.foo.theme.render.MyRegionRenderer</region-renderer>
<window-renderer>org.foo.theme.render.MyWindowRenderer</window-renderer>
<portlet-renderer>org.foo.theme.render.MyPortletRenderer</portlet-renderer>
<decoration-renderer>org.foo.theme.render.MyDecorationRenderer</decoration-renderer>
</set>
</renderSet>
<layout>
<name>generic</name>
<uri>/generic/index.jsp</uri>
<uri state="maximized">/generic/maximized.jsp</uri>
</layout>
</layouts>
Again, anologous to layout strategies, the anonymous RenderSet overwrites the one specified for the page, and that overwrites the one specified for the portal. In other words: all pages that use the layout that defines an anonymous RenderSet will use that RenderSet, and ignore what is defined as RenderSet for the portal or the page.
In addition to specifying the renderSet for a portal or a page, each individual portlet window can define what renderSet to use for the one of the three aspects of a window, the window renderer, the decoration renderer, and the portlet renderer. This feature allow you to use the the window renderer implementation from one renderSet, and the decoration renderer from another. Here is an example for a window that uses the implementations of the emptyRenderer renderSet for all three aspects:
<window>
<window-name>NavigationPortletWindow</window-name>
<instance-ref>NavigationPortletInstance</instance-ref>
<region>navigation</region>
<height>0</height>
<!-- overwrite portal and page properties set for the renderSet for this window -->
<properties>
<!-- use the window renderer from the emptyRenderer renderSet -->
<property>
<name>theme.windowRendererId</name>
<value>emptyRenderer</value>
</property>
<!-- use the decoration renderer from the emptyRenderer renderSet -->
<property>
<name>theme.decorationRendererId</name>
<value>emptyRenderer</value>
</property>
<!-- use the portlet renderer from the emptyRenderer renderSet -->
<property>
<name>theme.portletRendererId</name>
<value>emptyRenderer</value>
</property>
</properties>
</window>
A portal theme is a collection of CSS styles, JavaScript files, and images, that all work together to style and enhance the rendered markup of the portal page. The theme works together with the layout and the RenderSet in procuding the content and final look and feel of the portal response. Through clean separation of markup and styles a much more flexible and powerfull approach to theming portals is possible. While this approach is not enforced, it is strongly encouraged. If you follow the definitions of the ThemeStyleGuide (see later), it is not necessary to change the layout or the strategy, or the RenderSet to achieve very different look and feels for the portal. All you need to change is the theme. Since the theme has no binary dependencies, it is very simple to swapt it, or change individual items of it. No compile or redeploy is necessary. Themes can be added or removed while the portal is active. Themes can be deployed in separate web applications furthering even more the flexibility of this approach. Web developers don't have to work with JSPs. They can stay in their favorite design tool and simple work against the exploded war content that is deployed into the portal. The results can be validated life in the portal.
Themes can be added as part of any web application that is deployed to the portal server. All what is needed is a theme descriptor file that is part of the deployed archive. This descriptor indicates to the portal what themes and theme resources are becoming available to the portal. The theme deployer scans the descriptor and adds the theme(s) to the ThemeService, which in turn makes the themes available for consumption by the portal. Here is an example of a theme descriptor:
<themes>
<theme>
<name>nodesk</name>
<link href="/nodesk/css/portal_style.css" rel="stylesheet" type="text/css" />
<link rel="shortcut icon" href="/images/favicon.ico" />
</theme>
<theme>
<name>phalanx</name>
<link href="/phalanx/css/portal_style.css" rel="stylesheet" type="text/css" />
<link rel="shortcut icon" href="/images/favicon.ico" />
</theme>
<theme>
<name>industrial-CSSSelect</name>
<link rel="stylesheet" id="main_css" href="/industrial/portal_style.css" type="text/css" />
<link rel="shortcut icon" href="/industrial/images/favicon.ico" />
<script language="JavaScript" type="text/javascript">
// MAF - script to switch current tab and css in layout...
function switchCss(currentTab,colNum) {
var obj = currentTab;
var objParent = obj.parentNode;
if (document.getElementById("current") != null) {
var o = document.getElementById("current");
o.setAttribute("id","");
o.className = 'hoverOff';
objParent.setAttribute("id","current");
}
var css = document.getElementById("main_css");
source = css.href;
if (colNum == "3Col") {
if (source.indexOf("portal_style.css" != -1)) {
source = source.replace("portal_style.css","portal_style_3Col.css");
}
if (source.indexOf("portal_style_1Col.css" != -1)) {
source = source.replace("portal_style_1Col.css","portal_style_3Col.css");
}
}
if (colNum == "2Col") {
if (source.indexOf("portal_style_3Col.css" != -1)) {
source = source.replace("portal_style_3Col.css","portal_style.css");
}
if (source.indexOf("portal_style_1Col.css" != -1)) {
source = source.replace("portal_style_1Col.css","portal_style.css");
}
}
if (colNum == "1Col") {
if (source.indexOf("portal_style_3Col.css" != -1)) {
source = source.replace("portal_style_3Col.css","portal_style_1Col.css");
}
if (source.indexOf("portal_style.css" != -1)) {
source = source.replace("portal_style.css","portal_style_1Col.css");
}
}
css.href = source;
}
</script>
</theme>
</themes>
Themes are defined in the portal-themes.xml theme descriptor, which is localted in the WEB-INF/ folder of the web application.
Again, analogous to the way it is done for layouts, themes are specified in the portal descriptor as a portal or page property. The page property overwrites the portal property. In addition to these two options, themes can also be specified as part of the theme JSP tag , that is placed on the layout JSP. Here is an example portal descriptor that specifies the phalanx theme as the theme for the entire portal, and the industrial theme for the theme test page:
<portal>
<portal-name>default</portal-name>
<properties>
<!-- Set the theme for the default portal -->
<property>
<name>layout.id</name>
<value>phalanx</value>
</property>
</properties>
<pages>
<page>
<page-name>theme test</page-name>
<properties>
<!-- set a difference layout for this page -->
<property>
<name>layout.id</name>
<value>industrial</value>
</property>
</properties>
<window>
<window-name>CatalogPortletWindow</window-name>
<instance-ref>CatalogPortletInstance</instance-ref>
<region>left</region>
<height>0</height>
</window>
</page>
</pages>
</portal>
And here is an example of a layout JSP that defines a default theme to use if no other theme was defined for the portal or page:
<%@ taglib uri="/WEB-INF/theme/portal-layout.tld" prefix="p" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title><%= "JBoss Portal :: 2.2 early (Industrial)" %></title>
<meta http-equiv="Content-Type" content="text/html;" />
<p:theme themeName='industrial' />
<p:headerContent />
</head>
<body id="body">
<div id="portal-container">
<div id="sizer">
<div id="expander">
<div id="logoName"></div>
<table border="0" cellpadding="0" cellspacing="0" id="header-container">
<tr>
<td align="center" valign="top" id="header"><div id="spacer"></div></td>
</tr>
</table>
<div id="content-container">
<p:region regionName='This-Is-The-Page-Region-To-Query-The-Page'
regionID='This-Is-The-Tag-ID-Attribute-To-Match-The-CSS-Selector'/>
<p:region regionName='left' regionID='regionA'/>
<p:region regionName='center' regionID='regionB'/>
<hr class="cleaner" />
<div id="footer-container" class="portal-copyright">Powered by
<a class="portal-copyright" href="http://www.jboss.com/products/jbossportal">JBoss Portal</a><br/>
Theme by <a class="portal-copyright" href="http://www.novell.com">Novell</a>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
For the function of the individual tags in this example, please refere to the layout section of this document.
This section contains all the functionalities that don't fit with any of the other topics. Bits and pieces of useful functions that are related to the theme and layout functionality.
Portlets can have their content rewritten by the portal. This is useful if you want to uniquely namespace markup (JavaScript functions for example) in the scope of a page. The rewrite functionality can be applied to the portlet content (the markup fragment) and to content a portlet wants to inject into the header. The rewrite is implemented as specified in the WSRP (OASIS: Web Services for Remote Portlets; producer write). As a result of this, the token to use for rewrite is the WSRP specified "wsrp_rewrite_". If the portlet sets the following response property
res.setProperty("WSRP_REWRITE","true");all occurences of the wsrp_rewrite_ token in the portlet fragment will be replaced with a unique token (the window id). If the portlet also specifies content to be injected into the header of the page, that content is also subject to this rewrite.
res.setProperty("HEADER_CONTENT", "<script>function wsrp_rewrite_OnFocus(){alert('hello button');}</script>");Note that in order for the header content injection to work, the layout needs to make use of the headerContent JSP tag, like:
<%@ taglib uri="/WEB-INF/theme/portal-layout.tld" prefix="p" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title><JBoss Portal 2.2 early</title>
<meta http-equiv="Content-Type" content="text/html;" />
<p:headerContent />
</head>
<body id="body">
<p>...</p>
</body>
</html>
If a portlet needs a CSS style sheet to be injected via a link tag in the page header, it can do so by providing the context relative URI to the file in the jboss-portlet.xml descriptor, like:
<portlet-app>
<portlet>
<portlet-name>HeaderContentPortlet</portlet-name>
<header-content>
<link rel="stylesheet" type="text/css" href="/portlet-styles/HeaderContent.css" title="" media="screen" />
</header-content>
</portlet>
</portlet-app>
This functionality, just like the previously described header content injection, requires the layout JSP to add the "headerContent" JSP tag (see example above). One thing to note here is the order of the tags. If the headerContent tag is placed after the theme tag, it will allow portlet injected CSS files to overwrite the theme's behaviour, making this feature even more powerful!
One possible use of window properties is demonstrated in the divRenderer RenderSet implementation. If a window definition (in the portal descriptor) contains a property like:
<window>
<window-name>HintPortletWindow</window-name>
<instance-ref>HintPortletInstance</instance-ref>
<region>center</region>
<height>0</height>
<properties>
<!-- turn the decoration off for this portlet (i.e. no title and mode/state links) -->
<property>
<name>theme.decorationRendererId</name>
<value>emptyRenderer</value>
</property>
</properties>
</window>
the DivWindowRenderer will use the decoration renderer from the emptyRenderer RenderSet to render the decoration for this window (not delegate to the DivDecorationRenderer). As a result, the portlet window will be part of the rendered page, but it will not have a title, nor will it have any links to change the portlet mode or window state.
This document outlines the different selectors used to handle the layout and look/feel of the Industrial theme included in the JBoss portal.
A couple of things to know about the theming approach discussed below:
Screen shot using color outline of main ID selectors used to control presentation and layout:
The following is a list of the selectors used in the theme stylesheet, including a brief explanation of how each selector is used in the portal:
Portal Body Selector
#body {
background-image: url(images/portal_background.gif);
margin: 0px;
padding: 0px;
}
Usage: This selector controls the background of the page, and can be modified to set a base font-family, layout margin, etc. that will be inherited by all child elements that do not have their own individual style applied. By default, the selector pulls an image background for the page.
Portal Header Selectors
#spacer {
width: 1024px;
line-height: 0px;
font-size: 0px;
height: 0px;
}
Usage: Spacer div used to keep header at certain width regardless of display size. This is done to avoid overlapping of tab navigation in header. To account for different display sizes, this selector can be modified to force a horizontal scroll in the browser which eliminates any issue with overlapping elements in the header.
#header-container {
background-image: url(images/portal_background.gif);
background-repeat: repeat-y;
height: 100%;
min-width: 1000px;
width: 100%;
/* test to reposition header on page
position: absolute;
bottom: 5px;*/
}
Usage: Wrapper selector used to control the position of the header on the page (see yellow border in screen shot). This selector is applied as an ID on the table used to structure the header. You can adjust the attributes to reposition the header location on the page and/or create margin space on the top, right, bottom and left sides of the header.
Screenshot:
#header {
background-image: url(images/header.gif);
background-repeat: repeat-x;
height: 100px;
padding: 0px;
/*margin: 0 25% 0 25%;*/
}
Usage: This selector applies the header background image in the portal. It can be adjusted to accommodate a header background of a certain width/height or, as it currently does, repeat the header graphic so that it tiles across the header portion of the page.
#logoName {
background-image: url(images/JBossLogo.gif);
background-repeat: no-repeat;
width: 187px;
height: 35px;
position: absolute;
left: 15px;
top: 16px;
z-index: 2;
}
Usage: Logo selector which is used to brand the header with a specific, customized logo. The style is applied as an ID on an absolutely positioned DIV element which enables it to be moved to any location on the page, and allows it to be adjusted to accommodate a logo of any set width/height.
Portal Layout Region Selectors
#portal-container {
/*width: 100%;*/
/*IE specific approach to preserve min-width for portlet regions */
padding: 0 350px 0 350px;
}
Usage: Wrapper for entire portal which starts/ends after/before the BODY tag (see red border in screen shot). The padding attribute for this selector is used to preserve a minimum width setting for the portlet regions (discussed below). Similar to body selector, this style can modified to create margin or padding space on the top, right, bottom and left sections of the page. It provides the design capability to accommodate most layouts (e.g. a centered look such as the phalanx theme where there is some spacing around the content of the portal, or a full width look as illustrated in the Industrial theme).
Screenshot:
/* min width for IE */
#expander {
margin: 0 -350px 0 -350px;
position: relative;
}
/* min width for IE */
#sizer {
width: 100%;
}
/* IE min width \*/
* html #portal-container,
* html #sizer,
* html #expander { height: 0; }
Usage: These selectors are used in conjunction with the above, portal-container, selector to preserve a minimum width setting for the portlet regions. This was implemented to maintain a consistent look across different browsers.
/*table that contains all regions. does not include header*/
#content-container {
height: 100%;
text-align:left;
max-width: 1600px;
min-width: 800px;
}
Usage: Wrapper that contains all regions in portal with the exception of the header (see orange border in screen shot). Its attributes can be adjusted to create margin space on page, as well as control positioning of the area of the page below the header.
Screenshot:
#regionA {
/* test to swap columns with regionB...
float: right; */
width: 30%;
float: left;
margin: 0px;
padding: 0px;
min-width: 250px;
}
Usage: First portlet region located within the content-container (see blue border in screen shot). This selector controls the width of the region as well as its location on the page. Designers can very easily reposition this region in the portal (e.g. swap left regionA with right regionB, etc.) by adjusting the attributes of this selector.
#regionB {
/*test to swap columns with regionA...
margin: 0 30% 0 0; */
/* two column layout*/
margin: 0 0 0 30%;
padding: 0;
width: 69%;
/* test to add 3rd region in layout...
width: 40%;
float: left;*/
}
Usage: Second portlet region located within the content-container (see blue border in screen shot). Similar to regionA, this selector controls the width of the region as well as its location on the page.
#regionC {
/* inclusion of 3rd region - comment out for 2 region testing
padding: 0px;
width: 27%;
float: left;*/
display: none;
}
Usage: Third portlet region located within the content-container (please refer to blue border in screen shot representing regionA and regionB for an example). Used for 3 column layout. Similar to regionA and regionB, this selector controls the width of the region as well as its location on the page.
/* give a maximized portlet more space */
#regionMaximized {
width: 100%;
float: left;
margin: 0px;
padding: 0px;
min-width: 400px;
}
Usage: Portlet region located within the content-container (please refer to blue border in screen shot representing regionA and regionB for an example). Used for a one column layout to allow one portlet to take over the entire page. Similar to regionA, regionB, and regionB, this selector controls the width of the region as well as its location on the page.
Screenshot:
hr.cleaner {
clear:both;
height:1px;
margin: -1px 0 0 0;
padding:0;
border:none;
visibility: hidden;
}
Usage: Used to clear floats in regionA, regionB and regionC DIVs so that footer spans bottom of page.
#footer-container {
margin: 30px 25% 0 25%;
text-align: center;
}
Usage: Footer region located towards the bottom of the content-container (see above screen shot). This region spans the entire width of the page, but can be adjusted (just like regionA, regionB and regionC) to take on a certain position and width/height in the layout.
#navigation-container {}
Usage: Unused at this time.
#sub-navigation-container {}
Usage: Unused at this time.
Tab Navigation Selectors for Header
UL#tabsHeader {
margin: 0;
padding-left: 300px;
min-width: 550px;
}
Usage: Used to provide position (through padding attribute) of tabbed navigational items in header. A padding-left of 300px gives space for the left hand logo area and can be adjusted as needed to set the desired location for the navigation.
UL#tabsHeader li {
list-style: none;
float: left;
margin-left: 0px;
margin-top: 74px;
margin-right: 0px;
line-height: 24px;
padding: 0px;
border-left: 1px solid #72828E;
}
Usage: Selector used to style list items as horizontal navigation and to set the spacing and position of each nav item that's available.
UL#tabsHeader li:hover {
background-image: url(images/highlightedTab.gif);
background-repeat: repeat-x;
}
Usage: Used to provide hover pseudo class on navigation items so that the tab background will change upon mouseover. Note that currently IE only supports the hover pseudo class on links, so this selector will only affect non-IE browsers (e.g. FireFox, etc.).
UL#tabsHeader li.hoverOn {
background-image: url(images/highlightedTab.gif);
background-repeat: repeat-x;
}
UL#tabsHeader li.hoverOff {
background-image:none;
}
Usage: These two selectors are implemented to account for the fact that IE cannot understand the use of a pseudo class on the LI element. They provide the same mouseover effect as the “UL#tabsHeader li:hover�? selector when hovering the navigation item in IE, and are used in combination with onmouseover/onmouseout event handlers in the header navigation:
<li onmouseover="this.className='hoverOn'" onmouseout="this.className='hoverOff'">
<a href="#">Tab Nav</a>
</li>
UL#tabsHeader a {
display: block;
float: left;
padding: 4px 15px 5px 15px;
text-decoration: none;
font: 13px/normal Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
background: 100% 0 no-repeat;
color: #596874;
}
Usage: This selector styles the navigational links, indicating padding surrounding the link as well as font family, color and text-decoration.
UL#tabsHeader a:hover {
text-decoration: underline;
}
Usage: Used to underline navigational links when hovering with mouse. Unlike the li:hover pseudo class, IE does support the hover effect on links, so there is no need for a separate set of selectors to deal with this effect.
UL#tabsHeader #current, UL#tabsHeader #current a {
font: 13px/normal Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-weight: 600;
color: #EBEAEA;
background-image: url(images/activeTab.gif);
background-repeat: repeat-x;
border-right: 0px;
border-left: 0px;
}
Usage: This selector is set on the current/selected navigation item to style both the background of the tab as well as font properties such as color and weight. Example:
<li id="current" onmouseover="this.className='hoverOn'" onmouseout="this.className='hoverOff'">
<a href="#">Tab Nav</a>
</li>
/* backslash for IE5-Mac \*/
UL#tabsHeader a {float: none;} /* End Mac Hack */
html>body UL#tabsHeader a {width: auto;} /* fixes IE issues */
Usage: Also known in the industry as an example of the “Holly Hack�?, the above is added to the stylesheet to handle certain buggy issues with IE. This section of the stylesheet should be left alone as subsequent changes can effect the way things behave in IE.
li.currentTabBackground {
background: #fff;
}
li.currentTabBackgroundSubNav {
background: #eeeeef;
}
Usage: The above two selectors are not currently in use. Included to account for future changes to the navigation where multiple tiers/levels might be incorporated.
Portlet Container Window Selectors
.portlet-container {
padding: 10px;
}
Usage: Wrapper that surrounds the portlet windows (see green border in screen shot). Currently, this selector is used to create space (padding) between the portlets displayed in each particular region.
Screenshot:
.portlet-titlebar-title {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 11px;
font-weight: 500;
color: #596874;
white-space: nowrap;
line-height: 100%;
float: left;
text-indent: 15px;
}
Usage: Class used to style the title of each portlet window. Attributes of this selector set font properties, indentation and position of title.
.portlet-titlebar-decoration {
background-image: url(images/portlet-win-decoration.gif);
background-repeat: no-repeat;
height: 11px;
width: 11px;
float: left;
position: relative;
top: 6px;
}
Usage: Used to display top left portlet window decoration (e.g. sphere icon in Industrial theme). Attributes for this selector set position and dimensions of this decoration.
.portlet-mode-container {
float: right;
}
Usage: Wrapper that contains the portlet window modes that display in the top right section of the portlet windows.
.portlet-titlebar-left {
background-image: url(images/portlet-top-left.gif);
background-repeat: no-repeat;
width: 9px;
height: 33px;
background-position: right;
min-width: 9px;
}
Usage: Used to style the top left corner of the portlet window. Each portlet window consists of one table that has 3 columns and 3 rows. This selector styles the first column (TD) in the first row (TR).
Screenshot:
.portlet-titlebar-center {
background-image: url(images/portlet-top-middle.gif);
background-repeat: repeat-x;
height: 33px;
}
Usage: Used to style the center section of the portlet title bar. Each portlet window consists of one table that has 3 columns and 3 rows. This selector styles the second column (TD) in the first row (TR).
Screenshot:
.portlet-titlebar-right {
background-image: url(images/portlet-top-right.gif);
background-repeat: no-repeat;
width: 10px;
height: 33px;
min-width: 10px;
}
Usage: Used to style the top right corner of the portlet window. Each portlet window consists of one table that has 3 columns and 3 rows. This selector styles the third column (TD) in the first row (TR).
Screenshot:
.portlet-content-left {
background-image: url(images/portlet-left-vertical.gif);
height: 100%;
background-repeat: repeat-y;
background-position: right;
width: 9px;
min-width: 9px;
}
Usage: Used to style the left hand vertical lines that make up the portlet window. Each portlet window consists of one table that has 3 columns and 3 rows. This selector styles the first column (TD) in the second row (TR).
Screenshot:
.portlet-content-center {
background-color: #f7f7f7;
background-repeat: repeat;
vertical-align: top;
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 13px;
}
Usage: Used to style the center, content area where the portlet content is injected into the portlet window (see below screen). Attributes for this selector control the positioning of the portlet content as well as the background and font properties. Each portlet window consists of one table that has 3 columns and 3 rows. This selector styles the second column (TD) in the second row (TR).
Screenshot:
.portlet-body {
background-color: #f7f7f7;
}
Usage: An extra selector for controlling the content section of the portlet windows (see below screen). This was added to better deal with structuring the content that gets inserted/rendered in the portlet windows, specifically if the content is causing display problems in a portlet.
Screenshot:
.portlet-content-right {
background-image: url(images/portlet-right-vertical.gif);
height: 100%;
background-repeat: repeat-y;
background-position: left;
width: 10px;
min-width: 10px;
}
Usage: Used to style the right hand vertical lines that make up the portlet window. Each portlet window consists of one table that has 3 columns and 3 rows. This selector styles the third column (TD) in the second row (TR).
Screenshot:
.portlet-footer-left {
background-image: url(images/portlet-bottom-left.gif);
width: 9px;
height: 9px;
background-repeat: no-repeat;
background-position: top right;
min-width: 9px;
}
Usage: Used to style the bottom left corner of the portlet window. Each portlet window consists of one table that has 3 columns and 3 rows. This selector styles the first column (TD) in the third row (TR).
Screenshot:
.portlet-footer-center {
background-image: url(images/portlet-bottom-middle.gif);
height: 14px;
background-repeat: repeat-x;
}
Usage: Used to style the bottom, center of the portlet window (i.e. the bottom horizontal line in the Industrial theme). Each portlet window consists of one table that has 3 columns and 3 rows. This selector styles the second column (TD) in the third row (TR).
Screenshot:
.portlet-footer-right {
background-image: url(images/portlet-bottom-right.gif);
width: 10px;
height: 9px;
background-repeat: no-repeat;
min-width: 10px;
}
Usage: Used to style the bottom right corner of the portlet window. Each portlet window consists of one table that has 3 columns and 3 rows. This selector styles the third column (TD) in the third row (TR).
Screenshot:
Portlet Window Mode Selectors
.portlet-mode-maximized {
background-image: url(images/maximize.gif);
width: 16px;
height: 23px;
background-repeat: no-repeat;
float: left;
display: inline;
cursor: pointer;
}
Usage: Selector used to display the portlet maximize mode. Attributes for this selector control the display and dimensions of the maximize icon, including the behavior of the mouse pointer when hovering the mode.
.portlet-mode-minimized {
background-image: url(images/minimize.gif);
width: 16px;
height: 23px;
background-repeat: no-repeat;
float: left;
display: inline;
cursor: pointer;
}
Usage: Selector used to display the portlet minimize mode. Attributes for this selector control the display and dimensions of the minimize icon, including the behavior of the mouse pointer when hovering the mode.
.portlet-mode-normal {
background-image: url(images/normal.gif);
width: 16px;
height: 23px;
background-repeat: no-repeat;
float: left;
display: inline;
cursor: pointer;
}
Usage: Selector used to display the portlet normal mode (i.e. the icon that when clicked, restores the portlet to the original, default view). Attributes for this selector control the display and dimensions of the normal icon, including the behavior of the mouse pointer when hovering the mode.
.portlet-mode-help {
background-image: url(images/help.gif);
width: 16px;
height: 23px;
background-repeat: no-repeat;
float: left;
display: inline;
cursor: pointer;
}
Usage: Selector used to display the portlet help mode. Attributes for this selector control the display and dimensions of the help icon, including the behavior of the mouse pointer when hovering the mode.
.portlet-mode-edit {
background-image: url(images/edit.gif);
width: 16px;
height: 23px;
background-repeat: no-repeat;
float: left;
display: inline;
cursor: pointer;
}
Usage: Selector used to display the portlet edit mode. Attributes for this selector control the display and dimensions of the edit icon, including the behavior of the mouse pointer when hovering the mode.
.portlet-mode-remove {
background-image: url(images/remove.gif);
width: 16px;
height: 23px;
background-repeat: no-repeat;
float: left;
display: inline;
cursor: pointer;
}
Usage: Currently not available. But here is the intended use: Selector used to display the portlet remove mode. Attributes for this selector control the display and dimensions of the remove icon, including the behavior of the mouse pointer when hovering the mode.
.portlet-mode-view {
background-image: url(images/view.gif);
width: 16px;
height: 23px;
background-repeat: no-repeat;
float: left;
display: inline;
cursor: pointer;
}
Usage: Selector used to display the portlet view mode. Attributes for this selector control the display and dimensions of the view icon, including the behavior of the mouse pointer when hovering the mode.
.portlet-mode-reload {
background-image: url(images/reload.gif);
width: 16px;
height: 23px;
background-repeat: no-repeat;
float: left;
display: inline;
cursor: pointer;
}
Usage: Currently not available. But here is the intended use: Selector used to display the portlet reload mode. Attributes for this selector control the display and dimensions of the reload icon, including the behavior of the mouse pointer when hovering the mode.
Copyright Selectors
.portal-copyright {
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 9px;
color: #5E6D7A;
}
a.portal-copyright {
color: #768591;
text-decoration: none;
}
a.portal-copyright:hover {
color: #96A5B1;
text-decoration: none;
}
Usage: The above three selectors are used to style copyright content in the portal. The portal-copyright selector sets the font properties (color, etc.), and the a.portal-copyright/a.portal-copyright:hover selectors style any links that are part of the copyright information.
Element Selectors
a {
color: #768591;
text-decoration: none;
}
a:hover {
color: #96A5B1;
text-decoration: none;
}
Usage: The above two selectors style all anchor elements that do not have their own class/selector applied.
INPUT {
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 10px;
}
Usage: The above selector styles all INPUT elements that do not have their own class/selector applied.
SELECT {
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 10px;
}
Usage: The above selector styles all SELECT elements that do not have their own class/selector applied.
FONT {
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 10px;
color: #768591;
}
Usage: The above selector styles all FONT elements that do not have their own class/selector applied.
FIELDSET {
background-color: #f7f7f7;
border:1px solid #BABDB6;
padding: 6px;
}
Usage: The above selector styles all FIELDSET elements that do not have their own class/selector applied.
LEGEND {
background-color: transparent;
padding-left: 6px;
padding-right: 6px;
padding-bottom: 0px;
font-size: 14px;
}
Usage: The above selector styles all LEGEND elements that do not have their own class/selector applied.
Table Selectors
.portlet-table-header {}
Usage: Not currently in use. Intended for styling tables (specifically, the TH or table header elements) that get rendered within a portlet window.
.portlet-table-body {}
Usage: Not currently in use. Intended for styling the table body element used to group rows in a table.
.portlet-table-alternate {}
Usage: Not currently in use. Used to style the background color (and possibly other attributes) for every other row within a table.
.portlet-table-selected {}
Usage: Not currently in use. Used to style text, color, etc. in a selected cell range.
.portlet-table-subheader {}
Usage: Not currently in use. Used to style a subheading within a table that gets rendered in a portlet.
.portlet-table-footer {}
Usage: Not currently in use. Similar to portlet-table-header and portlet-table-body, this selector is used to style the table footer element which is used to group the footer row in a table.
.portlet-table-text {}
Usage: Text that belongs to the table but does not fall in one of the other categories (e.g. explanatory or help text that is associated with the table). This selector can also be modified to provide styled text that can be used in all tables that are rendered within a portlet.
FONT Selectors
.portlet-font {
color:#000;
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 10px;
}
Usage: Used to style the font properties on text used in a portlet. Typically this class is used for the display of non-accentuated information.
.portlet-font-dim {
color:#888385;
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 10px;
}
Usage: A lighter version (color-wise) of the portlet-font selector.
FORM Selectors
.portlet-form-label {
color:#4A4A4A;
text-decoration:none;
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 9px;
}
Usage: Text used for the descriptive label of an entire form (not the label for each actual form field).
.portlet-form-button {
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 9px;
font-weight: bold;
color: #270F07;
}
Usage: Used to style portlet form buttons (e.g. Submit).
.portlet-icon-label {}
Usage: Not currently in use. Text that appears beside a context dependent action icon.
.portlet-dlg-icon-label {}
Usage: Not currently in use. Text that appears beside a "standard" icon (e.g Ok, or Cancel).
.portlet-form-field-label {
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 9px;
color: #4A4A4A;
}
Usage: Selector used to style portlet form field labels.
.portlet-form-field {
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 9px;
color: #4A4A4A;
margin-top: 10px;
}
Usage: Selector used to style portlet form fields (i.e. INPUT controls, SELECT elements, etc.).
LINK Selectors
.portal-links:link {
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 9px;
font-weight: bold;
color: #242424;
text-decoration: none;
}
.portal-links:hover {
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 9px;
font-weight: bold;
color: #5699B7;
text-decoration: none;
}
.portal-links:active {
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 9px;
font-weight: bold;
color: #242424;
text-decoration: none;
}
.portal-links:visited {
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 9px;
font-weight: bold;
color: #242424;
text-decoration: none;
}
Usage: The above four selectors are used to style links in the portal. Each pseudo class (i.e. hover, active, etc.) provides a different link style.
MESSAGE Selectors
.portlet-msg-status {
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 10px;
font-style: normal;
color: #788793;
}
Usage: Selector used to signify the status of a current operation that takes place in the portlet (e.g. “saving results�?, “step 1 of 4�?).
.portlet-msg-info {
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 9px;
font-style: italic;
color: #000;
}
Usage: Selector used to signify general information in a portlet (e.g. help messages).
.portlet-msg-error {
color:red;
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 9px;
font-weight: bold;
}
Usage: Selector used to signify an error message in the portlet (e.g. form validation error).
.portlet-msg-alert {
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 9px;
font-weight: bold;
color: #821717;
}
Usage: Selector used to style an alert that is displayed to the user.
.portlet-msg-success {
font-family: Verdana, Arial, Helvetica, Geneva, Swiss, SunSans-Regular;
font-size: 9px;
font-weight: bold;
color: #359630;
}
Usage: Selector used to indicate successful completion of an action in a portlet (e.g. “save successful�?).
SECTION Selectors
.portlet-section-header {
font-weight: bold;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 13px;
color: #768591;
background-color: #f7f7f7;
}
Usage: Table or section header.
.portlet-section-body {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10px;
}
Usage: Normal text in a table cell.
.portlet-section-alternate {
background-color: #ececed;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 9px;
}
Usage: Used to style background color and text in every other table row.
.portlet-section-selected {
background-color: #89AEC6;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 9px;
}
Usage: Used to style background and font properties in a selected cell range.
.portlet-section-subheader {
font-weight: bold;
font-size: 10px;
font-family: Verdana, Arial, Helvetica, sans-serif;
color: #000;
}
Usage: Used to style a subheading within a table/section that gets rendered in a portlet.
.portlet-section-footer {
font-family: Verdana, Arial, Helvetica, sans-serif;
background-color: #f7f7f7;
font-size: 8px;
}
Usage: Used to style footer area of a section/table that gets rendered in a portlet.
.portlet-section-text {}
Usage: Not currently used. Text that belongs to a section but does not fall in one of the other categories. This selector can also be modified to provide styled text that can be used in all sections that are rendered within a portlet.
MENU Selectors
.portlet-menu {}
Usage: Not currently used. General menu settings such as background color, margins, etc.
.portlet-menu-item {
color: #242424;
text-decoration: none;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 9px;
}
Usage: Not currently used. Normal, unselected menu item.
.portlet-menu-item:hover {
color: #5699B7;
text-decoration: none;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 9px;
}
Usage: Not currently used. Used to style hover effect on a normal, unselected menu item.
.portlet-menu-item-selected {}
Usage: Not currently used. Applies to selected menu items.
.portlet-menu-item-selected:hover {
}
Usage: Not currently used. Selector styles the hover effect on a selected menu item.
.portlet-menu-cascade-item {}
Usage: Not currently used. Normal, unselected menu item that has sub-menus.
.portlet-menu-cascade-item-selected {}
Usage: Not currently used. Selected sub-menu item.
.portlet-menu-description {}
Usage: Not currently used. Descriptive text for the menu (e.g. in a help context below the menu).
.portlet-menu-caption {}
Usage: Not currently used. Selector used to style menu captions.
WSRP Selectors
.portlet-horizontal-separator {}
Usage: Not currently used. A separator bar similar to a horizontal rule, but with styling matching the page.
.portlet-nestedTitle-bar {}
Usage: Not currently used. Allows portlets to mimic the title bar when nesting something.
.portlet-nestedTitle {}
Usage: Not currently used. Allows portlets to match the textual character of the title on the title bar.
.portlet-tab {}
Usage: Not currently used. Support portlets having tabs in the same style as the page or other portlets.
.portlet-tab-active {}
Usage: Not currently used. Highlight the tab currently being shown.
.portlet-tab-selected {}
Usage: Not currently used. Highlight the selected tab (not yet active).
.portlet-tab-disabled {}
Usage: Not currently used. A tab which can not be currently activated.
.portlet-tab-area {}
Usage: Not currently used. Top level style for the content of a tab.
Installation / Configuration
CMS
Errors
Miscellaneous
I am seeing "ERROR [JDBCExceptionReporter] Table not found in statement" in the logfile on first boot. What is this?
Ignore this error. It is used by the portal to create the initial database tables. On second boot, you should not see them at all.
I want to do a clean install/upgrade over my existing one. What are the steps?
Is my database vendor/version combination supported?
How do I force the Hibernate Dialect used for my database?
See Section 3.3, “Forcing the DB dialect”
How do I change the context-root of the portal to http://localhost:8080/?
See Section 3.2, “Changing the context path”
How do I change the CMS repository configuration?
There are 3 supported modes: 100% DB (default), 100% Filsystem, and Mixed (Blobs on the Filesystem and metadata in the DB). You can see configuration options here: Section 11.3.3, “Configuring the Content Store Location”
On reboot, the CMS is complaining about a locked repository.
This occurs when JBoss AS is improperly shutdown or the CMS Service errors on startup. To remove the lock, shutdown JBoss, and then remove the file under JBOSS_HOME/server/default/data/portal/cms/conf/.lock.
I created a file in the CMSAdmin. How do I view it?
Using the default configuration, the path to the file in the browser would be: http://localhost:8080/portal/content/path/to/file.ext. Note that all requests for cms content must be prepended with /content and then followed by the path/to/the/file.gif as it is in your directory structure.
When I access a specific portal-instance or page, I keep seeing "401 - not authorized" error in my browser.
You are likely not authorized to view the page or portal instance. You can either modify the security using the Management Portlet under the Admin Tab, or secure your portlets via the object descriptor, Section 10.1, “Securing Portal Objects”
How do I disable development-mode errors on the presentation layer?
See: Section 6.2.2, “Portlet Debugging (jboss-portal.sar/conf/config.xml)”
Is there a sample portlet I can look at to learn about portlet development and JBoss Portal deployments?