Differences between revisions 2 and 3
Revision 2 as of 2005-07-12 02:07:01
Size: 11469
Editor: DavidLeStrat
Comment:
Revision 3 as of 2009-09-20 23:46:37
Size: 11497
Editor: localhost
Comment: converted to 1.6 markup
Deletions are marked like this. Additions are marked like this.
Line 3: Line 3:
''by Michael N. Lipp'' [[MailTo(mnl AT mnl DOT de)]] ''by Michael N. Lipp'' <<MailTo(mnl AT mnl DOT de)>>
Line 5: Line 5:
In the past few weeks, I have [[#deploying bundled Jetspeed as an EAR]] and got it eventually running in JBoss 3.2.7. This documents what I have learned about Jetspeed2 and haven't found in the existing documentation. "Haven't found" implies both "isn't there" and "is well hidden". In the past few weeks, I have [[[#deploying|bundled Jetspeed as an EAR]]] and got it eventually running in JBoss 3.2.7. This documents what I have learned about Jetspeed2 and haven't found in the existing documentation. "Haven't found" implies both "isn't there" and "is well hidden".
Line 7: Line 7:
This page reflects the approach that I take trying to understand a project. There is some information about the [#projectOrganization the directory structure] that presents itself after unpacking the source. This is followed by an [#components outline of the major components], starting at something well known (the servlet, in my case), and eventually some information about the [#frameworks frameworks and libraries used] (this may be a "read first", depending on your approach). Finally there are some [#miscIssues miscellaneous issues] that didn't fit in the categories above. This page reflects the approach that I take trying to understand a project. There is some information about the [[#projectOrganization|the directory structure]] that presents itself after unpacking the source. This is followed by an [[#components|outline of the major components]], starting at something well known (the servlet, in my case), and eventually some information about the [[#frameworks|frameworks and libraries used]] (this may be a "read first", depending on your approach). Finally there are some [[#miscIssues|miscellaneous issues]] that didn't fit in the categories above.
Line 9: Line 9:
[[Anchor(projectOrganization)]] <<Anchor(projectOrganization)>>
Line 12: Line 12:
Jetspeed2 is a maven based project with several sub-projects, organized in subdirectores of the project tree[[FootNote(If --like me -- you don't use maven for your projects here's how it works in a nutshell: every "project.xml" in the tree defines a project. There isn't much information in these files. That's because maven takes "project.xml" mainly as a "sub-project tree marker". It then takes into consideration the layout of the subtree (e.g. if there is a "WEB-INF/" directory, the sub-project obviously results in a WAR) and acts accordingly. "project.properties" supplies some additional information (though I haven't understood yet why this information isn't put in project.xml as well) and "maven.xml" only provides invocable "goals". This approach is the reason why all maven based projects have this rigid, fancy layout.)]]. Jetspeed2 is a maven based project with several sub-projects, organized in subdirectores of the project tree<<FootNote(If --like me -- you don't use maven for your projects here's how it works in a nutshell: every "project.xml" in the tree defines a project. There isn't much information in these files. That's because maven takes "project.xml" mainly as a "sub-project tree marker". It then takes into consideration the layout of the subtree (e.g. if there is a "WEB-INF/" directory, the sub-project obviously results in a WAR) and acts accordingly. "project.properties" supplies some additional information (though I haven't understood yet why this information isn't put in project.xml as well) and "maven.xml" only provides invocable "goals". This approach is the reason why all maven based projects have this rigid, fancy layout.)>>.
Line 15: Line 15:
  This "main subproject" is the [#containerServlet Jetspeed2 container].   This "main subproject" is the [[#containerServlet|Jetspeed2 container]].
Line 17: Line 17:
  This directory contains several sub-projects that provide the more complex components used by the [#containerServlet Jetspeed2 servlet]. The components are used as Java``Beans in the [#spring Spring] application context configuration.   This directory contains several sub-projects that provide the more complex components used by the [[#containerServlet|Jetspeed2 servlet]]. The components are used as Java``Beans in the [[#spring|Spring]] application context configuration.
Line 25: Line 25:
[[Anchor(components)]] <<Anchor(components)>>
Line 28: Line 28:
[[Anchor(containerServlet)]] <<Anchor(containerServlet)>>
Line 31: Line 31:
The Jetspeed2 container is a servlet (org.apache.jetspeed.engine.Jetspeed``Servlet). The servlet uses three initialization parameters (defined in "web.xml") that point to more configuration information[[FootNote(IMHO this is a bit of over-configurability that makes things hard to use. The names of the configuration files could have been hard-coded.)]] The Jetspeed2 container is a servlet (org.apache.jetspeed.engine.Jetspeed``Servlet). The servlet uses three initialization parameters (defined in "web.xml") that point to more configuration information<<FootNote(IMHO this is a bit of over-configurability that makes things hard to use. The names of the configuration files could have been hard-coded.)>>
Line 37: Line 37:
The actual work is done by an [wiki:Jetspeed2/EngineOverview engine]. The default engine is based on the [#spring Spring Application Framework]. The available components are configured by the "*.xml" files in "WEB-INF/assembly". ComponentManager lists a subset of the components needed by the default engine. Some more components are described on the [wiki:Jetspeed2/PluggableEngineComponents pluggable engine components page]. The security service related component configuration files are described [http://portals.apache.org/jetspeed-2/multiproject/jetspeed-security/config.html in the official documentation]. The actual work is done by an [[Jetspeed2/EngineOverview|engine]]. The default engine is based on the [[#spring|Spring Application Framework]]. The available components are configured by the "*.xml" files in "WEB-INF/assembly". ComponentManager lists a subset of the components needed by the default engine. Some more components are described on the [[Jetspeed2/PluggableEngineComponents|pluggable engine components page]]. The security service related component configuration files are described [[http://portals.apache.org/jetspeed-2/multiproject/jetspeed-security/config.html|in the official documentation]].
Line 41: Line 41:
[[Anchor(frameworks)]] <<Anchor(frameworks)>>
Line 44: Line 44:
[[Anchor(spring)]] <<Anchor(spring)>>
Line 47: Line 47:
The [http://www.springframework.org/ Spring Application Framework] is based on the old concept of Java``Beans[[FootNote(Of course, there is no reason why "old" should be "bad". But sometimes I get the feeling that Java``Beans is the highest level of abstraction that has really been comprehended by the average developer. It's a bit like the saying that the telephone is the only technical equipement that truly everybody can operate -- so if you want your interface to be easily usable, make it look like a telephone.)]]. Roughly speaking, Spring provides a means to configure a bean factory, usually with an XML file. For every Java``Bean you can specify the properties, either as sacalars or by linking to other bean configurations. At runtime, the bean factory can be queried for instances of the configured Java``Beans, which are usually -- though not necessarily -- created by the framework as singletons (resolving all links to referenced Java``Beans). In addition, Spring provides AOP features that enable you to modify the behaviour of existing Java``Beans without writing code. The [[http://www.springframework.org/|Spring Application Framework]] is based on the old concept of Java``Beans<<FootNote(Of course, there is no reason why "old" should be "bad". But sometimes I get the feeling that Java``Beans is the highest level of abstraction that has really been comprehended by the average developer. It's a bit like the saying that the telephone is the only technical equipement that truly everybody can operate -- so if you want your interface to be easily usable, make it look like a telephone.)>>. Roughly speaking, Spring provides a means to configure a bean factory, usually with an XML file. For every Java``Bean you can specify the properties, either as sacalars or by linking to other bean configurations. At runtime, the bean factory can be queried for instances of the configured Java``Beans, which are usually -- though not necessarily -- created by the framework as singletons (resolving all links to referenced Java``Beans). In addition, Spring provides AOP features that enable you to modify the behaviour of existing Java``Beans without writing code.
Line 51: Line 51:
[[Anchor(persistenceLayer)]] <<Anchor(persistenceLayer)>>
Line 54: Line 54:
Persistence is provided by the [http://db.apache.org/ojb/ ObJectRelationalBridge] which is a lesser known alternative to [http://www.hibernate.org/ Hibernate] ([http://www.google.de/search?q=objectrelationalbridge+hibernate Google] provides some references to comparisons). The OJB framework is wrapped by some [#spring Spring] components. Regrettably these components have not been documented yet. Some [http://static.springframework.org/spring/docs/1.2/reference/orm.html general remarks about O/R wrappers] are applicable to OJB as well. Persistence is provided by the [[http://db.apache.org/ojb/|ObJectRelationalBridge]] which is a lesser known alternative to [[http://www.hibernate.org/|Hibernate]] ([[http://www.google.de/search?q=objectrelationalbridge+hibernate|Google]] provides some references to comparisons). The OJB framework is wrapped by some [[#spring|Spring]] components. Regrettably these components have not been documented yet. Some [[http://static.springframework.org/spring/docs/1.2/reference/orm.html|general remarks about O/R wrappers]] are applicable to OJB as well.
Line 67: Line 67:
[[Anchor(miscIssues)]] <<Anchor(miscIssues)>>
Line 70: Line 70:
[[Anchor(deploying)]] <<Anchor(deploying)>>
Line 77: Line 77:
The container nature implies the temptation to install the portal as an "extension" of the application server. Using JSR-168 portlets, this approach is backed by the fact that portlet applications are themselves web applications. And as you don't want to re-implement a web container as part of your portal implementation, you want the use the existing web container to run the portlet applications[[FootNote(Now this would be a good example for a re-usable component: a web container component that can be used to both implement a web applictaion container and a portlet container within a web application.)]]. The container nature implies the temptation to install the portal as an "extension" of the application server. Using JSR-168 portlets, this approach is backed by the fact that portlet applications are themselves web applications. And as you don't want to re-implement a web container as part of your portal implementation, you want the use the existing web container to run the portlet applications<<FootNote(Now this would be a good example for a re-usable component: a web container component that can be used to both implement a web applictaion container and a portlet container within a web application.)>>.
Line 79: Line 79:
Using the default web container to run the portlet application requires that different web applications (the portal and the portlet applications) interact[[FootNote(This is why the "crossContext" attribute in Tomcat must be set to run portals that use this approach.)]]. And it requires that the web application container and the portal (web) application exchange information about the portlet applications deployed. Using the default web container to run the portlet application requires that different web applications (the portal and the portlet applications) interact<<FootNote(This is why the "crossContext" attribute in Tomcat must be set to run portals that use this approach.)>>. And it requires that the web application container and the portal (web) application exchange information about the portlet applications deployed.
Line 83: Line 83:
It would be nice if you could rely on [http://www.jcp.org/en/jsr/detail?id=88 JSR-88] being implemented and use this API for deployment. Currently, however, Jetspeed2 has to resort to using an application server specific component that is configured as bean "org.apache.jetspeed.tools.pamanager.servletcontainer.Application``Server``Manager" in "jetspeed-spring.xml". It would be nice if you could rely on [[http://www.jcp.org/en/jsr/detail?id=88|JSR-88]] being implemented and use this API for deployment. Currently, however, Jetspeed2 has to resort to using an application server specific component that is configured as bean "org.apache.jetspeed.tools.pamanager.servletcontainer.Application``Server``Manager" in "jetspeed-spring.xml".
Line 93: Line 93:
While using a common repository has its advantages, it breaks Jetspeed2. There may be several problems, but I can only report about the first I have encountered (and that made me change the JBoss 3.2.7 behaviour to the "WAR first" behaviour). The problem is that Velocity uses a singleton pattern for its engine. This singleton is initially configured with the path information required to find the templates. And this is, of course, done by the first WAR that uses Velocity being deployed. Subsequently deployed WARs that also want to use Velocity find an already configured Velocity engine and skip the configuration, so the information about the additionally available templates is lost. Using individual classloaders for the WARs and putting the velocity.jar in each WAR/WEB-INF/lib fixes this because now every WAR gets its own singleton[[FootNote(Of course, this remains a nuicance because the velocity classes have to be deployed as many times as there are WARs that use Velocity. This requires both memory and startup time, but it can only be fixed by the velocity project.)]]. While using a common repository has its advantages, it breaks Jetspeed2. There may be several problems, but I can only report about the first I have encountered (and that made me change the JBoss 3.2.7 behaviour to the "WAR first" behaviour). The problem is that Velocity uses a singleton pattern for its engine. This singleton is initially configured with the path information required to find the templates. And this is, of course, done by the first WAR that uses Velocity being deployed. Subsequently deployed WARs that also want to use Velocity find an already configured Velocity engine and skip the configuration, so the information about the additionally available templates is lost. Using individual classloaders for the WARs and putting the velocity.jar in each WAR/WEB-INF/lib fixes this because now every WAR gets its own singleton<<FootNote(Of course, this remains a nuicance because the velocity classes have to be deployed as many times as there are WARs that use Velocity. This requires both memory and startup time, but it can only be fixed by the velocity project.)>>.

A walk through Jetspeed2

by Michael N. Lipp <mnl AT mnl DOT de>

In the past few weeks, I have bundled Jetspeed as an EAR] and got it eventually running in JBoss 3.2.7. This documents what I have learned about Jetspeed2 and haven't found in the existing documentation. "Haven't found" implies both "isn't there" and "is well hidden".

This page reflects the approach that I take trying to understand a project. There is some information about the the directory structure that presents itself after unpacking the source. This is followed by an outline of the major components, starting at something well known (the servlet, in my case), and eventually some information about the frameworks and libraries used (this may be a "read first", depending on your approach). Finally there are some miscellaneous issues that didn't fit in the categories above.

Project organization

Jetspeed2 is a maven based project with several sub-projects, organized in subdirectores of the project tree1.

  • portal-webapp/
  • components/...
    • This directory contains several sub-projects that provide the more complex components used by the Jetspeed2 servlet. The components are used as JavaBeans in the Spring application context configuration.

  • applications/...
    • This directory contains several sub-projects. Each sub-projects provides a portlet application that can be deployed in the Jetspeed2 portlet container. The more important (because tightly connected with Jetspeed2) portlets applications are
    • security/
      • This is a portlet application for managing the security component of Jetspeed2.

[And some more I haven't found out enough about yet to describe them.]

Components

The Jetspeed2 container

The Jetspeed2 container is a servlet (org.apache.jetspeed.engine.JetspeedServlet). The servlet uses three initialization parameters (defined in "web.xml") that point to more configuration information2

  • "properties" --> "WEB-INF/conf/jetspeed.properties"

  • "configuration" --> "WEB-INF/conf/jetspeed-configuration.xml"

  • "applicationRoot" --> "webContext" (reserved word, eventually maps to servlet context's real path)

  • "engine" --> "org.apache.jetspeed.engine.SpringEngine"

The actual work is done by an engine. The default engine is based on the Spring Application Framework. The available components are configured by the "*.xml" files in "WEB-INF/assembly". ComponentManager lists a subset of the components needed by the default engine. Some more components are described on the pluggable engine components page. The security service related component configuration files are described in the official documentation.

Requests are passed through a pipeline component ("jetspeed-pipeline" by default). Pipelines are defined in "WEB-INF/assembly/pipelines.xml". Pipelines consist of valves that process the request.

Frameworks and libraries

Spring Framework

The Spring Application Framework is based on the old concept of JavaBeans3. Roughly speaking, Spring provides a means to configure a bean factory, usually with an XML file. For every JavaBean you can specify the properties, either as sacalars or by linking to other bean configurations. At runtime, the bean factory can be queried for instances of the configured JavaBeans, which are usually -- though not necessarily -- created by the framework as singletons (resolving all links to referenced JavaBeans). In addition, Spring provides AOP features that enable you to modify the behaviour of existing JavaBeans without writing code.

This concept is complemented with a rich library of components, many of which provide "wrappers" around components from other frameworks.

Persistence Layer

Persistence is provided by the ObJectRelationalBridge which is a lesser known alternative to Hibernate (Google provides some references to comparisons). The OJB framework is wrapped by some Spring components. Regrettably these components have not been documented yet. Some general remarks about O/R wrappers are applicable to OJB as well.

The DAOs configured in Jetspeed are

  • <bean id="portletRegistryImpl" ... />

  • <bean id="portletEntityAccessImpl" ... />

  • <bean id="capabilitiesImpl" ... />

  • <bean id="PreferencesProviderImpl" ... />

  • <bean id="PropertyManagerImpl" ... />

Each DAO bean has a property that is set to the name of the file that specifies the O/R mapping.

The implementation classes of these beans implement the "top-level access" to the persistet objects (i.e. the queries). The DAOs are augmented with the transaction aspect, a proxy bean that monitors the access to the DAO's methods. Only the respective proxy (with a more intuitive name e.g. <bean name="portletRegistry" ... />) bean is used in the program.

Miscellaneous Issues

Deploying Jetspeed2

A portal that is designed to run in the J2EE environment and that supports portlets has an ambivalent nature. On the one hand side, it is a component in the J2EE environment. On the other hand side, it is a container for components (the portlets).

Deployment as "Container Extension"

The container nature implies the temptation to install the portal as an "extension" of the application server. Using JSR-168 portlets, this approach is backed by the fact that portlet applications are themselves web applications. And as you don't want to re-implement a web container as part of your portal implementation, you want the use the existing web container to run the portlet applications4.

Using the default web container to run the portlet application requires that different web applications (the portal and the portlet applications) interact5. And it requires that the web application container and the portal (web) application exchange information about the portlet applications deployed.

Jetspeed2's standard approach is to actively deploy the portlet applications. The "default" Jetspeed2 installation is an "exploded" war in the deployment directory of the Web server or application server (e.g. Tomcat ".../webapps/" and JBoss ".../server/default/deploy/"). Within its directory structure, Jetspeed2 has a "watched" directory for portlet applications. Whenever you drop a portlet application in the ".../jetspeed2.war/WEB-INF/deploy/" directory, it will be deployed in the web container and the portlets will be made available in the portal (this emphasizes the "container extension" character).

It would be nice if you could rely on JSR-88 being implemented and use this API for deployment. Currently, however, Jetspeed2 has to resort to using an application server specific component that is configured as bean "org.apache.jetspeed.tools.pamanager.servletcontainer.ApplicationServerManager" in "jetspeed-spring.xml".

The current (M3) Jetspeed2 binary distribution takes this deployment approach even further. It doesn't present Jetspeed2 portal as a component that you integrate. Rather it provides a fully configured, stand-alone portal application that you can use to run your portlet applications.

Deployment as Web Application within an EAR

I think you cannot be sure about the J2EE compliance of a module unless you have successfully packaged it as a module in an EAR -- and then you have to successfully deploy this EAR in at least two application servers. Jetspeed2 presents several challenges in this respect.

First, JBoss 3.2.x and 4.0.1 use by default a common repository for all classes loaded during the deployment of an EAR. This is not compliant with the servlet specification that prescribes individual classloaders for each WAR with libraries in WAR/WEB-INF/lib/ (and classes in WAR/WEB-INF/classes/) taking precedence over classes found elsewhere. Starting with JBoss 4.0.2 the specified behaviour has been made the default.

While using a common repository has its advantages, it breaks Jetspeed2. There may be several problems, but I can only report about the first I have encountered (and that made me change the JBoss 3.2.7 behaviour to the "WAR first" behaviour). The problem is that Velocity uses a singleton pattern for its engine. This singleton is initially configured with the path information required to find the templates. And this is, of course, done by the first WAR that uses Velocity being deployed. Subsequently deployed WARs that also want to use Velocity find an already configured Velocity engine and skip the configuration, so the information about the additionally available templates is lost. Using individual classloaders for the WARs and putting the velocity.jar in each WAR/WEB-INF/lib fixes this because now every WAR gets its own singleton6.

[To be continued.]

  1. If --like me -- you don't use maven for your projects here's how it works in a nutshell: every "project.xml" in the tree defines a project. There isn't much information in these files. That's because maven takes "project.xml" mainly as a "sub-project tree marker". It then takes into consideration the layout of the subtree (e.g. if there is a "WEB-INF/" directory, the sub-project obviously results in a WAR) and acts accordingly. "project.properties" supplies some additional information (though I haven't understood yet why this information isn't put in project.xml as well) and "maven.xml" only provides invocable "goals". This approach is the reason why all maven based projects have this rigid, fancy layout. (1)

  2. IMHO this is a bit of over-configurability that makes things hard to use. The names of the configuration files could have been hard-coded. (2)

  3. Of course, there is no reason why "old" should be "bad". But sometimes I get the feeling that JavaBeans is the highest level of abstraction that has really been comprehended by the average developer. It's a bit like the saying that the telephone is the only technical equipement that truly everybody can operate -- so if you want your interface to be easily usable, make it look like a telephone. (3)

  4. Now this would be a good example for a re-usable component: a web container component that can be used to both implement a web applictaion container and a portlet container within a web application. (4)

  5. This is why the "crossContext" attribute in Tomcat must be set to run portals that use this approach. (5)

  6. Of course, this remains a nuicance because the velocity classes have to be deployed as many times as there are WARs that use Velocity. This requires both memory and startup time, but it can only be fixed by the velocity project. (6)

Jetspeed2/DevelopersDocumentation/DevelopingJetspeedPlatformJ2ArchitectureWalkthrough (last edited 2009-09-20 23:46:37 by localhost)