On Apr 7, 2007, at 10:48 AM, Richard Wallace wrote:
Hello,
In an application we are in the planning stages of we are trying to
figure out how to deploy it. We've all but officially said that we
are going to be using Geronimo for our application server. The
application will consist of many webapps that use Struts 2 and
Spring. There will be some shared components that all the webapps
will need access to like email services, persistence, and other
components. We've been exploring the idea of having a shared Spring
application context to achieve this. Most of our work so far has been
based on the architecture that Sakai uses.
The way Sakai works is that certain APIs and other jars are put in the
/shared/lib directory of Tomcat. When the first webapp loads up a
special extended Spring ContextListener starts up and initializes the
component manager. The component manager loads up a shared
ApplicationContext with components that are in the
${CATALINA_HOME}/components directory. This components directory
contains a directory for each component that should be started up.
The layout is similar to that of a webapp, except instead of a web.xml
there is a components.xml which is a standard Spring beans xml
descriptor. Each component is loaded in it's own separate classloader
so any versioning problems between jars they depend on will be
isolated and not cause issues. The components are put in the shared
ApplcationContext and available to all the webapps which have their
own ApplicationContexts which are children of the shared context.
This way, the shared components are available to the webapps and
Spring can do its dependency injection in the usual way.
So do the components implement interfaces that are in a shared
classloader, so any app with that classloader as parent (or
equivalent) can use the components? Or is there some other way of
using the components?
What I want to do is figure out a way to do the same thing in an EAR
file. I was thinking of just packaging up the components in jar files
and putting the components.xml files in their META-INF directories.
Then the component manager could scan the jars on the classpath and
look for these components.xml files and load the components into the
shared ApplicationContext that way. The problem is that then all the
jars that the components depend on would need to be in the EAR itself
and wouldn't be in separate classloaders, possibly causing versioning
conflicts.
I've seen some references to Geronimo and Spring integration, but I
haven't been able to find any documentation or examples showing how to
use it. I've seen some references to META-INF/spring.xml and
geronimo-spring.xml files, but nothing really describing how they work
or what they do. I saw the SpringGBean in the APIs, but there's not
much documentation to say what it does. Does this maybe already solve
my problem? Can anyone point me to more information about how to
use it?
Geronimo-spring integration is usually a bunch of half-tested
components from several years ago because no one has figured out what
it should actually do. Most people seem to want to start one
instance of spring from a web app and do nothing more complicated,
which doesn't require any extra integration. Eventually someone was
bound to have more interesting requirements.... and here you are :-)
If that's not going to help, I thought about maybe loading the
components the way Sakai used to do it, where the components are in
actual webapps and they are loaded before the other webapps. This
means that the order in which webapps are loaded is important,
something that couldn't be controlled in a cross-platform way which is
why they moved to the new "whichever webapp loads first causes the
shared context to be loaded" methodology. But I'm not sure if you can
control the order in which webapps are loaded in Geronimo, can you?
Even if you can, I'm not sure this is an ideal solution.
The final solution I thought of for creating this shared application
context and loading components with separate classloaders is to maybe
try and create some kind of custom package that I can put into the EAR
file and have the component loader look for and load it up that way.
Maybe just a .jar file with a META-INF/components.xml and a lib/
directory or something. But I'm not 100% sure of how I could get that
to work.
If anyone has any ideas or thoughts about creating this shared Spring
application context I'd love to hear them.
I'll describe the most geronimo centric way of doing this, and you
can tell us what is wrong with this plan :-)
So, in geronimo we have modules which are basically a classloader +
services. Each module can have multiple parent modules: in
particular this means each classloader can have multiple parents.
IIUC the requirements, you want one classloader/module that has the
shared component interfaces, and runs a single spring instance.
Then you have numerous component modules, each providing
implementations of services whose interfaces are in the shared module.
Finally you have numerous web apps all of which need access to the
services but which should not be able to access the service
implementation classes directly.
As far as modules/classloaders this is easy to set up in geronimo.
For each module you just need a plan that specifies the jars and
parents as dependencies. The geronimo-web plans for the web app
would include the shared module as a dependency.
I don't know enough about Spring to know how to set up the
implementation module registration with the spring instance. What I
would try to do is:
- write a spring "server" gbean that would be configured in the
shared module that would start the spring "server" and await
registrations from the implementation modules
- write a spring "plan registration" gbean that would be configured
in each of the implementation modules that would find the appropriate
spring plans for the module and register/start/whatever-the-correct-
word-is them with the spring "server"
Do you need to assure that particular services start before
particular web apps? This can be assured in one way by the order in
which the modules are started. If you need something more robust so
that startup will fail if someone tries to start things in the wrong
order we might have to add something to let you specify web app
dependencies directly.
I've been wanting something like this for relatively complicated
spring apps such as jetspeed2....
Hope this helps
thanks
david jencks
Thanks,
Rich