My comments below are based on not having looked at the pluto 1.1
implementation at all and the pluto 1.0.x implementation years ago.
On Feb 8, 2008, at 11:18 AM, Ate Douma wrote:
Dear committers, community,
Jetspeed-2 currently still uses Pluto 1.0.1 as its JSR-168
container, but we want and need to upgrade and migrate to the
latest Pluto container under
development, aka the not yet released Pluto 2.0 targeted as the
JSR-286 RI.
This however is currently impossible to do because of the
architectural changes Pluto underwent from version 1.0.x to 1.1.x.
Technically, viewed from the POV of an easy to embed container for
the Pluto Portal Driver, or environments which only need the out-of-
the-box features
provided, these architectural changes have resulted in a much
simpler and easier to understand and maintain model and API, and as
such these changes were great!
But... for a portal like Jetspeed-2, which provides a much enhanced
usage and feature list *on container level*, these architectural
changes have, simply put,
completely broken with the functional and technical "contract"
provided by Pluto 1.0.x and as such make it now impossible for us
to migrate to the current Pluto
container.
As it is the primary mission and goal of the Pluto project to
provide an embeddable portlet container for portals like its Apache
Portals sibling project
Jetspeed-2, it is our view (as Jetspeed-2 committers) that we need
to discuss what needs and can to be done, on both Jetspeed-2 and
Pluto side, to bring our
projects back together, and how to restore the original
*functional* contract Pluto provided with version 1.0.x.
To this end, we'll present our (short) assessment how the current
Pluto container API and implementation has changed and broken with
the old Pluto 1.0.x
features which Jetspeed-2 depends upon to be able to maintain our
current Jetspeed-2 features, as well as what we think needs to be
done *functionally* to
restore these features.
To be very clear: we're not asking nor suggesting to restore the
old Pluto 1.0.x API and SPI as is. We fully expect and are willing
to adapt Jetspeed-2 to the
new Pluto architecture as much as needed, even while that most
likely will now cause Jetspeed-2 itself to have to break with its
own public API and thus lose
(some) backwards compatibility. After all, Pluto now has had
several releases based on its new Pluto 1.1.x architecture and we
(as Apache Portals community)
have the obligation to maintain as much backwards compatibility for
the users of these versions as well.
So, what we will propose later on is to work towards a solution
which will restore the ability for Jetspeed to properly use and
embed the new Pluto 2.0
container but still maintain the lightweight and simple
configuration and usage of the container for portals like the Pluto
Portal Driver and other use-cases
without breaking its current "contract".
But first lets get down to some of the issues we have identified so
far. This is most likely not the complete list but covers the most
important ones.
The Pluto 1.0.x object model API (OM)
=====================================
Pluto 1.0.x provided a fully interface based object model to
represent the web and portlet deployment descriptors (web.xml and
portlet.xml).
Through factory methods, the Pluto 1.0.x container only used these
interfaces in its implementation. That allowed Jetspeed and other
portals to supply its own
implementation of the OM and use that to provide enhanced features
like database persistence, extended meta data, caching control, etc.
Of course, Pluto 1.0.x also provided its own implementation classes
of the OM and Jetspeed uses these as base classes but provides
extended implementations to
hook them up and into its own backend and management features.
Pluto 1.1.x completely dropped all of this. Instead, a new
descriptor API was provided with a complete new set of classes (no
interfaces!) which are used and
instantiated directly within the container with no factory support
or any other way of extending the current implementation.
As such, the current container only allows usage of the web.xml and
portlet.xml descriptors and features derived from them as provided
by the container.
Furthermore, as the loading and management of the descriptors is
now done directly (and only) by the container itself, there is no
way for Jetspeed to hook into
this process anymore.
Effectively, this means that descriptor persistence, caching,
custom extensions, *standard* support for custom portlet mode or
window-state mapping,
etc. all no longer are possible with the current Pluto container.
Not just for Jetspeed but any portal needing and depending on these
features.
I suggest that there be a very clear separation between deployment
code that might look at web.xml, portlet.xml, annotations, or some
other source and use these to construct objects describing the
portlets, and the "engine" that "runs" these objects. Rewriting the
deployment code to create your own objects is pretty simple and lets
you just use objects without needing the complexity of interfaces or
factories. Also, everyone has their favorite xml technology and this
lets you replace whatever pluto might choose with one you like
better. I've done this with the jetty integration in geronimo and
like the results.
The Pluto 1.1.x/2.0 PortletContextManager,
PortletDescriptorRegistry and PortletServlet
======================================================================
=================
With the switch to Pluto 1.1.x, the container added control and
management of the above mentioned deployment descriptors and fully
integrated them with the
container interaction which now depend on this management
*implementation*, and also hooked that up on the portlet
application context.
This means that now you need a separate container instance for each
portlet application and that the container itself loads and manages
the descriptors.
Also, interaction with the container now requires the use of the
Pluto provided PortletServlet (although that one possibly can be
extended) as it is tied to the
PortletContextManager directly (which in turn is tied to the
PortletDescriptorRegistry).
Besides the obvious problem that this effectively blocks delegating
management of the context and descriptors for the portal, it also
forces the usage and
interaction with portlets to the Pluto provided implementation.
For instance, Pluto delegates interaction to each portlet through a
separate instance of its PortletServlet, while Jetspeed currently
has its own more generic
JetspeedContainerServlet which is not tied to a single portlet. The
Jetspeed solution allows for dynamically enabling/adding portlets
(as defined in
portlet.xml) without any need to rewrite the web.xml. But using the
Pluto PortletServlet requires changing the web.xml (and thus
reloading the context) to do so.
I don't think I'll understand this issue without studying the code
extensively. However, from this description it looks like perhaps
the "deploy time" translation of xml/annotations to more descriptive
internally usable objects is too tied to the "execution" of these
objects? I'd expect there would be some kind of
"PortletApplicationContext" object that would have a collection of
Portlet objects and you could programatically add more Portlet
objects to it. If there is enough separation between the deploy time
and run time code this should not be a problem even if the Portlet
object didn't come from xml.
I don't see a necessary problem with the PortletApplicationContext
being the container instance if this simplifies the code. I don't
have a strong opinion on the servlet-per-portlet/servelt-per-portlet-
application question: it seems to me that with an appropriate servlet
container that allows adding servlets to a running web app they would
have the same capabilities and each would make some features easier
to implement. For instance adding a servlet to a running web app is
harder than not adding it, but implementing portlet role permissions
seems easier to me with a servlet-per-portlet approach.
The Pluto 1.1.x service provider interfaces (SPI)
=================================================
Although the new Pluto SPI (comprising of the
RequiredContainerServices and OptionalContainerServices) generally
provides a nice and simple interface to plugin
portal specific implementations, certain features available with
Pluto 1.0.x are no longer available.
With Pluto 1.0.x, critical components as the PortletContext and
PortletWindow were accessed by the container through factory classes.
These no longer exist and the pluto container directly instantiates
its own implementations for these components.
Jetspeed however very much depends on its own extensions of these
components to provide support for features like parallel rendering,
clustering and attaching
additional meta data (or even preferences) to a PortletWindow or
PortletEntity.
Additionally, while Pluto 1.0.x allowed managing multiple
PortletWindows for a PortletEntity, this *Portlet Spec* feature has
been removed from the current
Pluto 1.1.x/2.0 container.
Lastly, not all of services referenced through these SPI interfaces
are only accessed through it.
For instance, the OptionalContainerService.getPortletRegistryService
() is by default implemented by the PortletContextManager. But,
this implementation is very
much directly used (as static instance even) within the container.
Effectively, the interface is now only an API portals might use,
but it cannot be replaced
and thereby cannot be regarded as a proper SPI interface anymore.
Here the long time since I've studied this code is really hurting
me. IIRC this all relates to classes that describe a portlet's
environment at runtime that are populated by the portal (e.g.
jetspeed) and used by the portlet container (pluto) or populated by
both the portal and portlet container and used by both.
Basically what I'd like to see is a strongly typed system (no fishing
for services in 6 levels of nested hash maps) based entirely on
dependency injection.
Objects describing the portlet app injected into the portlet
container by some deployment system, either plutos or something else
Environment information supplied by the portal injected from the portal
Objects that need to be created by the portlet container that also
need to be customized for the portal environment created by factories
injected by the portal environment. (I don't really understand how
this can be necessary, but if it is then a factory seems like the way
to do it).
Solution
========
As indicated earlier, solving the above issues such that Pluto 2.0
can be made embeddable again, in Jetspeed or other portals, needs
to be done in a way which
maintains backwards compatibility for current Pluto 1.1.x users.
Is this really a requirement? If a substantial improvement can be
made in the design I wonder if backwards compatibility is essential.
Although we don't have a clear proposal for this, our current idea
is to:
- define new OM interfaces to be implemented by the current
descriptor api classes
- enhance the OptionalContainerServices SPI to provide additional
services for loading and managing the deployment descriptors
- enhance the OptionalContainerServices SPI to provide additional
services for accessing components like PortletContext,
PortletWindow etc.
- refactor the container implementation to only use the OM interfaces
- refactor the container implementation to only use the SPI
provided services and no longer directly binding to its service
implementations
When done properly, the above changes should still allow using the
current implementation without any functional or even technical
consequence.
Now, the above changes will mean a lot of work and lots of testing
as well to make sure everything remains working as expected.
We, as primary Jetspeed committers have much at stake here so we
are definitely willing to help out and do much of the grunt work.
And of course, we will have a large amount of work to do at
Jetspeed Portal side as well: all our Pluto Factory implementations
have become useless, all Pluto
OM packages (and some interfaces) have changed, and we will need to
provide new implementations for the Pluto SPI container services.
For our implementations of the Pluto SPI container services, we
will definitely look at the current Pluto provided implementations
and where possible try to
make use of them as much as possible. To that end, we will probably
also need to be able to hook in our own extensions which might
require some additional
refactoring but should not result in functional or technical
changes of the default Pluto services.
Note: we want to migrate to Pluto 2.0 for our next Jetspeed 2.2
release. But, for that release we'll stick to only using the
JSR-168 container features.
Then, for the following major release, version 2.3 which we
currently have scheduled sometime this summer, we will provide full
JSR-286 compliance.
So, our initial goal is to get Pluto 2.0 working again with
Jetspeed-2 but stick to our current features.
This all is clearly not something which can be done or will be
ready overnight, nor possible to do all by ourselves.
But we do need to start resolving this ASAP so it won't hold up the
release of both Pluto 2.0 and Jetspeed 2.2 longer than needed.
As said: the above proposal is still just an idea. And of course
how to do all this, is fully open for debate and we are very
interested in hearing the opinions
of other committers and community members (also from other portals
embedding Pluto 1.1.x).
So please, provide feedback and ideas how to solve these issues.
And suggestions for alternative solutions will very much
appreciated too
With kind regards,
Dennis Dam
David Sean Taylor
Ate Douma
I hope my partially-informed opinions are helpful and not overly
intrusive. Unfortunately I can't promise I'll have much time to
actually study the code soon, but I am certainly hoping to. I'll
certainly try to explain what I'm talking about more if anyone is
interested.
thanks
david jencks