Apache Pluto, a subproject of the Apache Portals project, is an open source implementation of the Java Portlet Specification. The Pluto project provides a portlet container runtime environment, as mandated by the specification, in which portlets can be instantiated and managed. In this article, I discuss the high-level features of Pluto and how Pluto can be integrated with Apache Geronimo. There's also a sample application (see the Downloads section) containing Geronimo GBeans, which abstract the public interfaces of the primary components of the Pluto framework. These GBeans can then be deployed to a running Geronimo instance, where they can be used to monitor and manage Pluto's portal features.
The Pluto project provides a portlet container for managing portlets and a special-purpose portal application known as the Portal Driver, which provides configuration services, a template framework, and a framework for invoking individual portlets embedded within the container. The Pluto portlet container manages portlet invocations, portlet context handling, portlet deployment descriptor registry functionality, and portlet deployment descriptor services. The container also provides a plug-in framework for extending itself with additional functionality.
The Pluto portlet container exposes a set of mandatory and optional services for facilitating, among other things, communication between portlets and calling parties. These services are described later in this article.
The diagram in Figure 1 illustrates the primary components of Apache Pluto.
Figure 1. Architectural components of Apache Pluto
Introduction to Apache Geronimo
Apache Geronimo is a fully compliant Java EE platform that you can use to build enterprise-grade applications and services. Geronimo is based on an architecture that uses Inversion of Control (IoC) techniques to decouple components and services. This decoupling makes an extremely configurable and modular runtime environment. Geronimo also takes advantage of Java Management Extensions (JMX) and a similar proprietary managed-bean framework that makes Geronimo an easy platform to monitor, configure, and manage.
Geronimo is bootstrapped using a given aggregation of assembled modules that are connected and managed internally by a lightweight kernel component. A Geronimo module is an arbitrary component made up of a set of classes: dependencies, other modules, and a serialized configured state. The Geronimo kernel loads and assembles modules when a Geronimo instance is started. Modules determine functionality for a runtime Geronimo subsystem and the dependencies that are required for each Geronimo subsystem. All core services in a Geronimo run time are deployed as modules.
Modules are described using an XML document that's referred to as a deployment plan or plan. A final deployment plan in Geronimo is made up of a combination of an initial deployment plan, a Maven Project Object Model (POM) file, and a Maven project.properties file. Figure 2 shows how these files are processed to create a final deployment plan.
Figure 2. Geronimo deployment plans
The contents of a plan are constrained by an XML Schema Document (XSD). Among other things, a plan defines a module ID, a module's dependencies, environment properties for a module, services provided by the module, and GBeans for the module.
The example in Listing 1 illustrates a simple Geronimo deployment plan.
Listing 1. A simple Geronimo deployment plan
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="http://geronimo.apache.org/xml/ns/deployment-1.1">
<environment>
<moduleId>
<groupId>geronimo</groupId>
<artifactId>simple</artifactId>
<version>1.0.0</version>
<type>car</type>
</moduleId>
<dependencies>
<dependency>
<groupId>geronimo</groupId>
<artifactId>j2ee-server</artifactId>
<type>car</type>
</dependency>
</dependencies>
<hidden-classes/>
<non-overridable-classes/>
</environment>
<gbean name="SimpleService" class="com.example.myservices.MyServiceGBean">
<attribute name="prop1">12345</attribute>
<attribute name="prop2">This is the value for property 2</attribute>
</gbean>
</module>
|
When a deployment plan similar to the plan in Listing 1 is transformed by the build process, a Configuration Archive (CAR) file is created with a unique name. The unique name generated for the configuration in Listing 1 is geronimo/simple-1.0.0/car.
A CAR file is an automatically generated Java Archive (JAR) file containing the serialized state of a deployment plan and any other ancillary resources. A serialized deployment plan is embodied in a file called config.ser in the META-INF directory of the CAR. CAR files are created by the build process via the Geronimo packaging plug-in for Maven.
A Geronimo repository is a data store and registry of artifacts, typically structured as a directory hierarchy on the file system. The binary distribution of Geronimo provides a directory named repository that contains all dependencies for the modules that make up the core Geronimo platform.
A Geronimo artifact is an arbitrary entity, such as a JAR file, Web Archive (WAR) file, CAR file, and so on, that's added to a Geronimo repository using either the Geronimo Web console or the command-line deployment and build utilities provided with the Geronimo distribution.
Download and install Apache Geronimo
Download the Geronimo platform from the site listed in the Resources section, and extract the files to a directory to be referred to as {GERONIMO_HOME}. After you've downloaded and extracted the Geronimo distribution, execute the startup script found in the {GERONIMO_HOME}\bin\ directory of your Geronimo installation. You should see a console window similar to Figure 3.
Figure 3. Geronimo startup
The startup console shows a number of modules, connectors, and applications that are loaded and started and from which the Geronimo runtime environment is created. You can stop the Geronimo run time using the shutdown script, also found in the {GERONIMO_HOME}\bin\ directory of your Geronimo installation.
Pluto services used by Geronimo
Geronimo 1.1.1 uses Pluto 1.0.1 as the portal environment for its management console. In this portal environment, services required by the portal container and services used by the portal driver are defined and loaded when the Web console initializes.
The following is a list of the standard services defined for Geronimo's Pluto-enabled Web console:
-
Config service —
The
ConfigServiceinterface represents information about Geronimo's Pluto portal configuration. -
Factory manager service —
The
FactoryManagerServiceinterface represents functionality for managing the lifetime of factories registered during the Pluto container startup. -
Log service —
The
LogManagerServiceinterface represents functionality defining the Pluto portal driver's logging implementation. -
Portlet definition registry service —
The
PortletDefinitionRegistryServiceinterface represents all portlets and portlet applications available in the Web console portal. This service presents and manages information about the Web console portlets and portlet applications. -
Portlet entity registry service —
The
PortletEntityRegistryServiceinterface represents a registry of all portlet and portlet application instances available in the Web console portal. -
Page registry service —
The
PageRegistryServiceinterface represents a registry of pages, windows, and portlet entries that make up the Geronimo Web console.
In this article, you create GBeans and utilities that expose these Pluto services to an administration framework operating in the Geronimo runtime environment.
Managing the Pluto portal environment
Before you begin work to manage the Pluto environment, you need to download the source for the Pluto framework (see the Resources section for a link). Download and extract the files to a directory to be referred to as {PLUTO_HOME}.
Object instances representing the Pluto services mentioned previously can be retrieved by a component running within the same servlet context as the Web console Web application. This allows access to configuration information that can be wrapped by Geronimo GBeans.
Configuration information for the Pluto portal environment is referenced by the
object stored in the
org.apache.pluto.portalImpl.services.ServiceManager
class and retrieved using the getService method of the
ServiceManager class. A reference to the
org.apache.pluto.portalImpl.services.config.ConfigService
class must be passed as a parameter to the getService
method of the ServiceManager class to retrieve an
instance of the ConfigService component.
With an instance of the ConfigService component
available, you can wrap this component as a standard Geronimo GBean and make it
available to the Pluto admin environment. Listing 2 illustrates how the
ConfigService information is presented by a Geronimo
GBean.
Listing 2. ConfigService as a Geronimo GBean
public class ConfigServiceGBean
implements GBeanLifecycle
{
public static final GBeanInfo GBEAN_INFO;
static
{
GBeanInfoBuilder infoBuilder =
new GBeanInfoBuilder("ConfigServiceGBean", ConfigServiceGBean.class);
infoBuilder.addAttribute("parameters",
org.apache.pluto.portalImpl.util.Parameters.class,
true);
infoBuilder.addOperation("getParameters");
infoBuilder.addOperation("setString", new Class[] { String.class,
String.class });
infoBuilder.addOperation("getString", new Class[] { String.class });
infoBuilder.addOperation("getInteger", new Class[] { String.class });
infoBuilder.addOperation("getBoolean", new Class[] { String.class });
infoBuilder.addOperation("paramKeys");
GBEAN_INFO = infoBuilder.getBeanInfo();
}
public static GBeanInfo getGBeanInfo()
{
return GBEAN_INFO;
}
private org.apache.pluto.portalImpl.services.config.ConfigServiceImpl
configServiceImpl = null;
public ConfigServiceGBean()
{
try
{
Class configServiceCls =
Class.forName("org.apache.pluto.portalImpl.services.config.ConfigService");
org.apache.pluto.portalImpl.services.Service configService =
org.apache.pluto.portalImpl.services.ServiceManager.getService(configServiceCls);
if (configService != null)
{
configServiceImpl =
(org.apache.pluto.portalImpl.services.config.ConfigServiceImpl)
configService;
}
}
catch(Exception e)
{
System.err.println("Exception in ConfigServiceGBean: " + e);
}
}
public org.apache.pluto.portalImpl.util.Parameters getParameters()
{
return configServiceImpl.getParameters();
}
public java.util.Iterator paramKeys()
{
return configServiceImpl.getParameters().keys();
}
public String getString(String name)
{
return configServiceImpl.getString(name);
}
public void setString(String name, String value)
{
configServiceImpl.getParameters().setString(name, value);
}
public Integer getInteger(String name)
{
return configServiceImpl.getInteger(name);
}
public Boolean getBoolean(String name)
{
return configServiceImpl.getBoolean(name);
}
public void doFail()
{
System.err.println(getClass().getName() + " failed");
}
public void doStart()
throws Exception
{
System.out.println("Starting " + getClass().getName());
}
public void doStop()
throws Exception
{
System.out.println("Stopping " + getClass().getName());
}
}
|
After you've created a standard Geronimo GBean for the
ConfigService component, it must be loaded and started
by the Geronimo kernel. You retrieve the Geronimo kernel using the
getSingleKernel method of the
org.apache.geronimo.kernel.KernelRegistry class.
With a reference to the kernel, you can describe a GBean using a
GBeanData instance. The GBean is then loaded and
started by the kernel, as shown in Listing 3.
Listing 3. Loading and starting a GBean using the GBeanManager
public class GBeanManager
{
public static void loadAndStartGBean(Class gBeanCls,
GBeanInfo gBeanInfo,
String serviceType)
{
java.net.URI gBeanURI =
java.net.URI.create("devworks/" + gBeanCls.getName() + "/1.0.0/?service="
+ serviceType);
org.apache.geronimo.gbean.AbstractName abstractName =
new org.apache.geronimo.gbean.AbstractName(gBeanURI);
org.apache.geronimo.gbean.GBeanData gBeanData =
new org.apache.geronimo.gbean.GBeanData(abstractName, gBeanInfo);
System.out.println("Loaded gBeanData for class: " + gBeanCls.getName());
org.apache.geronimo.kernel.Kernel geronimoKernel =
org.apache.geronimo.kernel.KernelRegistry.getSingleKernel();
System.out.println("Found kernel: " + geronimoKernel.getKernelName());
ClassLoader clsLoader = Thread.currentThread().getContextClassLoader();
try
{
geronimoKernel.loadGBean(gBeanData, clsLoader);
System.out.println("Loaded gBean: " + gBeanCls.getName());
}
catch (GBeanAlreadyExistsException e)
{
System.out.println("GBean [" + gBeanCls.getName() + "] already loaded");
}
try
{
geronimoKernel.startGBean(gBeanCls);
System.out.println("Started gBean: " + gBeanCls.getName());
}
catch (GBeanNotFoundException e)
{
System.err.println("GBean [" + gBeanCls.getName() + "] not found");
}
}
public static void stopAndUnloadGBean(Class gBeanCls)
{
org.apache.geronimo.kernel.Kernel geronimoKernel =
org.apache.geronimo.kernel.KernelRegistry.getSingleKernel();
System.out.println("Found kernel: " + geronimoKernel.getKernelName());
try
{
geronimoKernel.stopGBean(gBeanCls);
System.out.println("Stopped gBean: " + gBeanCls.getName());
}
catch (GBeanNotFoundException e)
{
System.err.println("GBean [" + gBeanCls.getName() + "] not found");
return;
}
try
{
geronimoKernel.unloadGBean(gBeanCls);
System.out.println("Unloaded gBean: " + gBeanCls.getName());
}
catch (GBeanNotFoundException e)
{
System.err.println("GBean [" + gBeanCls.getName() + "] not found");
return;
}
}
public static Object getGBean(Class gBeanCls)
throws GBeanNotFoundException
{
org.apache.geronimo.kernel.Kernel geronimoKernel =
org.apache.geronimo.kernel.KernelRegistry.getSingleKernel();
System.out.println("Found kernel: " + geronimoKernel.getKernelName());
return geronimoKernel.getGBean(gBeanCls);
}
}
|
After the ConfigService component has been wrapped in
a Geronimo GBean and loaded and started by the kernel, a JavaServer Pages (JSP)
component or
servlet can use the GBean to access information managed by the
ConfigService component.
The JSP example in Listing 4 illustrates retrieving the
ConfigService GBean and using it to get and set
information managed by the ConfigService component.
Listing 4. Management page for the ConfigService GBean
<h3>Pluto Admin on Geronimo: Config Service</h3>
<%
try
{
com.devworks.pluto.gbeans.GBeanManager.loadAndStartGBean(
com.devworks.pluto.gbeans.ConfigServiceGBean.class,
com.devworks.pluto.gbeans.ConfigServiceGBean.GBEAN_INFO,
"config");
Object gbeanObj =
com.devworks.pluto.gbeans.GBeanManager.getGBean(
com.devworks.pluto.gbeans.ConfigServiceGBean.class);
if (gbeanObj != null)
{
com.devworks.pluto.gbeans.ConfigServiceGBean configServiceGBean =
(com.devworks.pluto.gbeans.ConfigServiceGBean)gbeanObj;
java.util.Enumeration reqParams = request.getParameterNames();
while (reqParams.hasMoreElements())
{
String paramName = (String)reqParams.nextElement();
String newParamValue = request.getParameter(paramName);
String oldParamValue = configServiceGBean.getString(paramName);
if (newParamValue.equalsIgnoreCase(oldParamValue) == false)
{
System.out.println("Setting param: " + paramName + " to value: "
+ newParamValue);
configServiceGBean.setString(paramName, newParamValue);
}
}
out.println("<form name='configForm' method='post' "
+ "action='ConfigServiceAdmin.jsp'><table>");
java.util.Iterator keys = configServiceGBean.paramKeys();
while (keys.hasNext())
{
String paramKey = keys.next().toString();
String paramValue = configServiceGBean.getString(paramKey);
out.println("<tr><td>Param " + paramKey + "</td>"
+ "<td><input type='text' name='" + paramKey
+ "' value='" + paramValue + "'/></td>"
+ "<td><input type='submit' value='submit'/></td></tr>");
}
out.println("</table>");
com.devworks.pluto.gbeans.GBeanManager.stopAndUnloadGBean(
com.devworks.pluto.gbeans.ConfigServiceGBean.class);
}
else
{
out.println("Unable to find ConfigServiceGBean<br/>");
}
}
catch(Exception e)
{
e.printStackTrace(System.out);
out.println("<br/>Exception: " + e);
}
%>
|
You can access information managed by other services, such as the portlet definition registry service or portlet entity registry service, using the same techniques to wrap each component as a GBean. These GBeans can then be loaded and started by the kernel and referenced by administration components, such as JSPs or servlets. (See the Resources section for the source code demonstrating these concepts.)
Security role references (represented by
org.apache.pluto.om.common.SecurityRoleRef instances)
determine whether a user is mapped to a specified role for each portlet request.
Standard Java 2 Platform, Enterprise Edition (J2EE) and Java EE security measures
are taken to determine the rights given to an authenticated user in the context of a
particular portlet by applying the security information configured within the set
of security role references stored within each portlet definition.
The portlet entity registry service GBean is used to retrieve and modify
security role references for a given portlet definition. As with the
ConfigService GBean, a static
GBeanInfo object is created and made available in a
static getGBeanInfo method, as shown in Listing 5.
Listing 5. GBeanInfo for the portlet entity registry service GBean
public class PortletEntityRegistryServiceGBean
implements GBeanLifecycle
{
public static final GBeanInfo GBEAN_INFO;
static
{
GBeanInfoBuilder infoBuilder =
new GBeanInfoBuilder("PortletEntityRegistryServiceGBean",
PortletEntityRegistryServiceGBean.class);
infoBuilder.addOperation("getPortletEntityKeys");
infoBuilder.addOperation("getPortletEntityID",
new Class[] { String.class });
infoBuilder.addOperation("getPortletEntityWindowList",
new Class[] { String.class });
infoBuilder.addOperation("getPortletEntityDefName",
new Class[] { String.class });
infoBuilder.addOperation("getPortletEntityDefAppID",
new Class[] { String.class });
infoBuilder.addOperation("getPortletEntityDefAppContext",
new Class[] { String.class });
infoBuilder.addOperation("getSecurityRoleRefs",
new Class[] { String.class });
infoBuilder.addOperation("setSecurityRoleRefs",
new Class[] { String.class,
org.apache.pluto.om.common.SecurityRoleRefSet.class });
GBEAN_INFO = infoBuilder.getBeanInfo();
}
public static GBeanInfo getGBeanInfo()
{
return GBEAN_INFO;
}
|
Each operation defined by the GBeanInfo object is
implemented using an instance of the object stored in the
org.apache.pluto.portalImpl.services.ServiceManager
class and retrieved using the getService method of the
ServiceManager class. In a manner similar to the
ConfigService GBean, a reference to the
org.apache.pluto.portalImpl.services.portletentityregistry.PortletEntityRegistryService class
must be passed as a parameter to the getService method
of the ServiceManager class to retrieve an instance of
the PortletEntityRegistryService component.
With an instance of the
PortletEntityRegistryService component available and
exposed as a standard Geronimo GBean, security role information for a portlet can be made available to the Pluto admin environment, as illustrated by
the GBean methods in Listing 6.
Listing 6. Security role information presented by the portlet entity registry service GBean
public org.apache.pluto.om.common.SecurityRoleRefSet
getSecurityRoleRefs(String entityKey)
{
org.apache.pluto.portalImpl.om.portlet.impl.PortletDefinitionImpl
portletDefinitionImpl = getPortletDefImpl(entityKey);
if (portletDefinitionImpl == null)
{
return null;
}
return portletDefinitionImpl.getCastorInitSecurityRoleRefs();
}
public void setSecurityRoleRefs(String entityKey,
org.apache.pluto.om.common.SecurityRoleRefSet securityRoleRefSet)
{
org.apache.pluto.portalImpl.om.portlet.impl.PortletDefinitionImpl
portletDefinitionImpl = getPortletDefImpl(entityKey);
if (portletDefinitionImpl == null)
{
return;
}
portletDefinitionImpl.setCastorInitSecurityRoleRefs(securityRoleRefSet);
}
|
When you wrap the desired services as GBeans and make them available to the kernel, you can use them to monitor and manage portal applications, as covered in the next section.
Monitor and manage portal applications
To use the GBeans described previously, you must use them in the same context as the Web console application. You do so by adding JSPs, servlets, and/or Java classes to the Web console CAR file. For the Jetty Web console, you can find the CAR file in the Geronimo repository at Geronimo/webconsole-jetty/1.1.1/car directory. The Web application for the Web console is in a .war file named framework.war, which is a child of the CAR directory.
To add Pluto administration functionality to Geronimo using the GBeans defined earlier, create a new subdirectory of framework.war, called plutoadmin. In the plutoadmin
directory, place the JSPs found in the sample code (see the
Downloads section). These JSPs provide the
GBeanManager class to access the GBeans.
After you've populated the plutoadmin directory with the desired JSPs and other Web resources (and each time a modification is made to the plutoadmin resources), you must restart the Web console CAR file using the Geronimo deployer utility, as shown in Listing 7.
Listing 7. Command line for restarting the Web console CAR file
C:\<GERONIMO_HOME>\bin>deploy --user system --password manager restart \
geronimo/webconsole-jetty/1.1.1/car
|
The result of this command line is shown in Listing 8.
Listing 8. Results of restarting the Web console CAR file
Restarted geronimo/webconsole-jetty/1.1.1/car
`-> standard.war
`-> framework.war
|
Now point a Web browser to http://localhost:8080/console/plutoadmin/ to access the Pluto management pages. Links are provided for each of the primary services described in this article. You can investigate each link and the GBean associated with each.
Apache Geronimo uses Apache Pluto as the portal environment for its management console. Using Geronimo's managed-bean framework, Pluto services can be wrapped and presented to components and services to allow a flexible and powerful environment for managing Pluto components and services.
| Description | Name | Size | Download method |
|---|---|---|---|
| Sample code for this article | os-ag-geronpluto.zip | 104KB | HTTP |
Information about download methods
Learn
- Browse and research the
Apache Pluto project.
- Investigate the
JSR-000168 Portlet Specification.
- Check out the developerWorks Apache Geronimo project area for articles, tutorials, and other resources to help you get started developing with Geronimo today.
- Find helpful resources for beginners and experienced
users at the Get started now with Apache Geronimo section of developerWorks.
- Check out the IBM® Support for Apache Geronimo offering, which lets you develop Geronimo applications backed by world-class IBM support.
- Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products.
- Stay current with developerWorks technical events and webcasts.
- Browse all the Apache articles and free Apache tutorials available in the developerWorks Open source zone.
- Browse for books on these and other technical topics at the Safari bookstore.
Get products and technologies
- Download the
Apache Pluto framework.
- Download the latest version of Apache Geronimo.
- Download your free copy of IBM WebSphere® Application Server Community Edition — a lightweight J2EE application server built on Apache Geronimo open source technology that is designed to help you accelerate your development and deployment efforts.
- Innovate your next open source development project with IBM trial software, available for download or on DVD.
Discuss
- Participate in the discussion forum.
- Get involved in the developerWorks community by participating in developerWorks blogs.

Jeff Hanson has more than 20 years of experience in the software industry, including working as senior engineer for the Microsoft Windows port of the OpenDoc project, lead architect for the Route 66 framework at Novell, and chief architect for eReinsure.com, Inc., where he directed design and implementation of frameworks and platforms for J2EE-based reinsurance systems. Jeff is currently the CTO for Max Software, Inc., where he directs efforts to provide desktop and enterprise applications and platforms for Internet safety and parental controls. Jeff is the author of numerous articles and books, including .NET versus J2EE Web Services: A Comparison of Approaches, Pro JMX: Java Management Extensions, and Web Services Business Strategies and Architectures.
Comments (Undergoing maintenance)





