Apache Pluto 是 Apache Portals 项目的子项目,它是 Java Portlet Specification 的开源实现。Pluto 项目提供了符合规范要求的 portlet 容器运行时环境,可以在其中初始化和管理 portlet。在本文中,我将讨论 Pluto 的高级功能以及如何将 Pluto 与 Apache Geronimo 集成。还有包含 Geronimo GBean 的样例应用程序(请参阅 下载 部分),Geronimo GBean 将用于抽象化 Pluto 框架的主要组件的公共接口。这些 GBean 随后可以被部署到一个运行中的 Geronimo 实例中,其中 GBean 可用于监视和管理 Pluto 的门户功能。
Pluto 项目提供了以下组件:用于管理 portlet 的 portlet 容器、用于提供配置服务的专用门户应用程序 Portal Driver、模板框架和用于调用嵌入到容器内的各个 portlet 的框架。Pluto portlet 容器将管理 portlet 调用、portlet 上下文处理、portlet 部署描述符注册功能和 portlet 部署描述符服务。该容器还提供用于扩展自身附加功能的插件框架。
Pluto portlet 容器公开了一组辅助的强制性服务和可选服务,还有一点值得一提的就是 portlet 与调用方之间的通信。本文中稍后将介绍这些服务。
图 1 中的图表演示了 Apache Pluto 的主要组件。
Apache Geronimo 是完全兼容的 Java EE 平台,您可以使用它构建企业级应用程序和服务。Geronimo 基于使用控制反转(Inversion of Control,IoC)技术将组件与服务解耦的架构。这种解耦将建立一个极具可配置性和模块化的运行时环境。Geronimo 还利用 Java Management xtensions (JMX) 和类似的专有受管 bean 框架,使 Geronimo 成为易于监视、配置和管理的平台。
Geronimo 使用给定的一系列汇编模块进行引导,这些模块通过一个轻量级内核组件进行内部连接和管理。Geronimo 模块是由一组类(依赖性、其他模块和序列化配置状态)组成的随机组件。Geronimo 内核将在 Geronimo 实例启动时装入并汇编模块。模块将决定运行时 Geronimo 子系统的功能和每个 Geronimo 子系统所需的依赖性。Geronimo 运行时中的所有核心服务都被部署为模块。
模块是使用称为部署计划 或计划 的 XML 文档描述的。Geronimo 中的最终部署计划是由初始部署计划、Maven Project Object Model (POM) 文件和 Maven project.properties 文件的组合组成。图 2 显示了如何处理这些文件来创建最终的部署计划。
计划的内容是由 XML 模式文档(XML Schema Document,XSD)约束的。值得一提的是,计划将定义模块 ID,模块的依赖性、模块的环境属性、模块所提供的服务和模块的 GBean。
清单 1 中的示例演示了一个简单的 Geronimo 部署计划。
< 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 >
当类似于清单 1 中的计划的部署计划被构建过程转换后,将用一个惟一名称创建配置归档(Configuration Archive,CAR)文件。为清单 1 中的配置生成的惟一名称是 geronimo/simple-1.0.0/car。
CAR 文件是自动生成的 Java Archive (JAR) 文件,其中包含部署计划和任何辅助资源的序列化状态。序列化部署计划包含在 CAR 的 META-INF 目录中名为 config.ser 的文件中。CAR 文件都是通过 Geronimo 的 Maven 打包插件由构建过程创建的。
Geronimo 存储库 存储了工件的数据和注册表,通常构建为文件系统中上的目录层次结构。二进制版本的 Geronimo 将提供名为 repository 的目录,该目录中包含组成核心 Geronimo 平台的模块的所有依赖性。
Geronimo 工件 是随机实体,例如 JAR 文件、Web Archive (WAR) 文件、CAR 文件等等,该工件被使用 Geronimo Web 控制台或命令行部署和带有 Geronimo 发行版的构建工具添加到 Geronimo 存储库中。
从 参考资料 部分列出的站点中下载 Geronimo 平台,并且将文件解压缩到称为 {GERONIMO_HOME} 的目录中。在下载并解压缩 Geronimo 发行版之后,请执行 Geronimo 安装的 {GERONIMO_HOME}/bin/ 目录中的启动脚本。您应当会看到类似图 3 所示的控制台窗口。
启动控制台将显示装入和启动的许多模块、连接器和应用程序并从中创建 Geronimo 运行时环境。您也可以使用 Geronimo 安装的 {GERONIMO_HOME}/bin/ 目录中的停止脚本来停止 Geronimo 运行时。
Geronimo 1.1.1 将使用 Pluto 1.0.1 作为其管理控制台的门户环境。在此门户环境中,当 Web 控制台初始化时,将定义并装入门户容器所需要的服务和门户驱动器所使用的服务。
下面是为 Geronimo 的启用了 Pluto 的 Web 控制台定义的标准服务列表:
- 配置服务 ——
ConfigService
接口表示关于 Geronimo 的 Pluto 门户配置的信息。 - 工厂管理器服务 ——
FactoryManagerService
接口表示用于管理在 Pluto 容器启动的过程中注册的工厂寿命的功能。 - 日志服务 ——
LogManagerService
接口表示定义 Pluto 门户驱动器的日志记录实现的功能。 - Portlet 定义注册服务 ——
PortletDefinitionRegistryService
接口表示 Web 控制台门户中可用的所有 portlet 和 portlet 应用程序。此服务将提供和管理关于 Web 控制台 portlet 和 portlet 应用程序的信息。 - Portlet 实体注册服务 ——
PortletEntityRegistryService
接口表示 Web 控制台门户中可用的所有 portlet 和 portlet 应用程序实例的存储库。 - 页面注册服务 ——
PageRegistryService
接口表示构成 Geronimo Web 控制台的页面、窗口和 portlet 条目的注册表。
在本文中,您将创建 GBean 和实用程序,用于向在 Geronimo 运行时环境中运行的管理框架公开这些 Pluto 服务。
在开始管理 Pluto 环境之前,您需要下载 Pluto 框架的源文件(有关链接,请参阅 参考资料 部分)。将文件下载并解压缩到引用为 {PLUTO_HOME} 的目录。
表示前面提及的 Pluto 服务的对象实例可以被在同一个 servlet 上下文内作为 Web 控制台 Web 应用程序的组件检索。这将允许访问能够被 Geronimo GBean 包装的配置信息。
Pluto 门户环境的配置信息将被 org.apache.pluto.portalImpl.services.ServiceManager
类中存储的对象引用并被使用 ServiceManager
类的 getService
方法检索。必须将对 org.apache.pluto.portalImpl.services.config.ConfigService
类的引用作为参数传递给 ServiceManager
类的 getService
方法才能检索 ConfigService
组件的实例。
ConfigService
组件的实例可用后,您可以将此组件打包成一个标准的 Geronimo GBean 并使其可用于 Pluto 管理环境。清单 2 演示了如何由 Geronimo GBean 表示 ConfigService
信息。
清单 2. 作为 Geronimo GBean 的 ConfigService
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());
}
}
在为 ConfigService
组件创建了标准 Geronimo GBean 后,必须由 Geronimo 内核装入和启动它。您可以使用 org.apache.geronimo.kernel.KernelRegistry
类的 getSingleKernel
方法检索 Geronimo 内核。
通过对内核的引用,可以使用 GBeanData
实例描述 GBean。该 GBean 随后被内核装入和启动,如清单 3 中所示:
清单 3. 使用 GBeanManager 装入和启动 GBean
... {
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);
}
}
在将 ConfigService
组件打包到 Geronimo GBean 中并由内核装入和启动之后,JavaServer Page (JSP) 组件或 servlet 可以使用 GBean 来访问 ConfigService
组件所管理的信息。
清单 4 中的 JSP 示例演示了如何检索 ConfigService
GBean 以及如何使用它获得和设定 ConfigService
组件所管理的信息。
清单 4. ConfigService GBean 的管理页面
<%
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);
}
%>
您可以访问其他服务所管理的信息,例如 portlet 定义注册服务或 portlet 实体注册服务,使用相同的技术把每个组件打包成 GBean。这些 GBean 随后可以被内核装入并启动并被诸如 JSP 或 servlet 之类的管理组件引用(要获得演示这些概念的源代码,请参阅 参考资料 部分)。
安全角色引用(由 org.apache.pluto.om.common.SecurityRoleRef
实例表示)将决定是否为每个 portlet 请求把用户映射为指定角色。采取标准 Java 2 Platform, Enterprise Edition (J2EE) 和 Java EE 安全措施,通过应用每个 portlet 定义内存储的安全角色引用集内配置的安全信息,确定在特殊 portlet 的上下文中提供给验证用户的权限。
portlet 实体注册服务 GBean 用于为给定 portlet 定义检索和修改安全角色引用。与 ConfigService
GBean 一样,将创建静态 GBeanInfo
对象并使其可用于静态 getGBeanInfo
方法,如清单 5 中所示:
清单 5. portlet 实体注册服务 GBean 的 GBeanInfo
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;
}
GBeanInfo
对象所定义的每项操作是使用 org.apache.pluto.portalImpl.services.ServiceManager
类中存储的对象实例实现的,并且是使用 ServiceManager
类的 getService
方法检索的。在类似于 ConfigService
GBean 的方式中,必须把对 org.apache.pluto.portalImpl.services.portletentityregistry.PortletEntityRegistryService
类的引用作为参数传递给 ServiceManager
类的 getService
方法才能检索 PortletEntityRegistryService
组件的实例。
当 PortletEntityRegistryService
组件的实例可用并且公开为标准 Geronimo GBean 后,可以使 portlet 的安全角色信息可用于 Pluto 管理环境,如清单 6 中的 GBean 方法所示:
清单 6. portlet 实体注册服务 GBean 所提供的安全角色信息
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);
}
当把所需的服务打包成 GBean 并使其可用于内核后,您可以使用它们监视和管理门户应用程序,请看下一部分的介绍。
要使用前述 GBean,必须在 Web 控制台应用程序所在的上下文中使用这些 GBean。您将通过把 JSP、servlet 和/或 Java 类添加到 Web 控制台 CAR 文件中来完成操作。对于 Jetty Web 控制台,您可以在位于 Geronimo/webconsole-jetty/1.1.1/car 目录的 Geronimo 存储库中找到 CAR 文件。Web 控制台的 Web 应用程序位于名为 framework.war 的 .war 文件中,该文件位于 CAR 目录中。
要使用先前定义的 GBean 把 Pluto 管理功能添加到 Geronimo 中,请创建名为 plutoadmin 的 framework.war 的新子目录。在 plutoadmin 目录中,放置可在样例代码中找到的 JSP(请参阅 下载 部分)。这些 JSP 提供了 GBeanManager
类来访问 GBean。
在用所需的 JSP 和其他 Web 资源(以及每次对 plutoadmin 资源所做的修改)填充了 plutoadmin 目录后,您必须使用 Geronimo deployer 实用程序重新启动 Web 控制台 CAR 文件,如清单 7 中所示:
C:/<GERONIMO_HOME>/bin>deploy --user system --password manager restart / geronimo/webconsole-jetty/1.1.1/car |
清单 8 中显示了此命令行的结果。
Restarted geronimo/webconsole-jetty/1.1.1/car `-> standard.war `-> framework.war |
现在把 Web 浏览器指向 http://localhost:8080/console/plutoadmin/ 以访问 Pluto 管理页面。提供了本文中所述的每项主要服务的链接。您可以研究每个链接及其关联的 GBean。
结束语Apache Geronimo 将使用 Apache Pluto 作为其管理控制台的门户环境。使用 Geronimo 的受管 bean 框架,可以把 Pluto 服务打包并提供给组件和服务,以允许提供灵活且功能强大的环境来管理 Pluto 组件和服务。
描述 | 名字 | 大小 | 下载方法 |
---|---|---|---|
本文的样例代码 | os-ag-geronpluto.zip | 104KB | HTTP |
关于下载方法的信息 |
学习
- 您可以参阅本文在 developerWorks 全球站点上的 英文原文。
- 浏览并研究 Apache Pluto 项目。
- 研究 JSR-000168 Portlet Specification。
- 访问 developerWorks Apache Geronimo 项目区,以获取文档、教程和其他资源以帮助您开始使用 Geronimo 进行开发。
- 访问 developerWorks 的 Get started now with Apache Geronimo 部分,查找对于初学者和有经验的用户都有帮助的参考资料。
- 查阅 IBM® Support for Apache Geronimo 提供的参考资料,让您能够在世界级的 IBM 支持下开发 Geronimo 应用程序。
- 访问 developerWorks 开放源码专区,获得丰富的 how-to 信息、工具和项目更新,帮助您使用开放源码技术进行开发,并与 IBM 产品结合使用。
- 随时关注 developerWorks 的 技术事件和网络广播。
- 浏览在 developerWorks Open source 专区中可获取的所有 Apache 文章 和 Apache 免费教程。
- 浏览 Safari 书店 中关于这些内容及其他技术主题的书籍