Am 28.06.2011 10:08, schrieb Daniël van 't Ooster:
- This implementation assumes the web bundle knows about all bundles
providing services;
wicket-osgi currently assumes that the web application bundle (WAB)
explicitly imports all packages or bundles which contribute Wicket
components used by the application.
Otherwise, for the injection stuff, the WAB only needs to import the
service interface packages, but not the implementation packages or bundles.
in our case (the case attached to WICKET-3737 is a
stripped down version), we have one 'web bundle', which hosts the Wicket
application; individual bundles provide pages and their mount points (in the
example case, bundles provide some panels).
Yes, I had a look at that example - it's a rather advanced scenario and
far more than what I'm currently aiming at with wicket-osgi.
The first major goal I would like to achieve is support for the
following scenario:
- OSGi Web Container and Web Application Bundles according to OSGi
Enterprise Spec 4.2.
- Wicket is deployed as a plain old OSGi bundle.
- One or more WABs are deployed as separate bundles. Each WAB provides a
Web Application according to the Servlet Spec. The WABs are completely
isolated from each other, just like plain old WARs.
I don't think that your scenario with other bundles contributing new
pages or resources to a running web application is currently covered by
the OSGi Enterprise Spec. A WAB is always a single bundle, which may of
course import packages and use services from other bundles, but for
anything related to the Web Context Path, there is a one-to-one relation
between context paths and bundles. At least that's my understanding, but
I'm not in any of the Java EE or OSGi expert groups...
Of course you can attach OSGi fragments to your WAB as bundle host, but
an independent bundle registering services that contribute to a web
context owned by some other bundle is currently out of scope, I'd say.
Mind you, I'm not saying that your scenario doesn't make sense or cannot
be done, but it sounds like the second or third step to me.
Do you have examples of any OSGi Web containers supports your flavour of
multi-bundle WABs? So far, I've looked at Pax Web, Eclipse Gemini Web
and Glassfish, and my impression is they all follow the rule "one web
context, one bundle".
In cases like that, there is no
single class loader which knows all classes, so you need one bundle with a
DynamicImport-Package: *.
I'd say your assumption is right, but your conclusion is not... Let's
say your WAB retrieves WebPages from the service registry and mounts
them. To do so, it only needs to load the WebPage base class from
Wicket, but not the implementation class from some other bundle.
In this situation, page deserialization will fail, because neither the
Wicket bundle class loader nor your WAB nor the ThreadContextClassLoader
can load the class from the contributor bundle.
But even then, there are other and better solutions than
DynamicImport-Package, which I think is something like an emergency
amputation when you have to save your application's life and need to use
some third-party lib that simply doesn't play by OSGi rules.
> To reduce the number of bundle refreshes we
delegate this job to a tiny 'class resolver bundle', which exposes an
IClassResolver instance as OSGi service.
And this class resolver bundle still uses dynamic imports, right?
I'd suggest one of the following options:
1) Your contributor bundles provide an IContributor service for an
interface exported by your WAB. Your WAB tracks all implementations,
builds a composite ClassResolver from all their classloaders and
registers the ClassResolver with Wicket.
2) Extender Pattern: You define a special manifest header that all your
contributors need to include, then your WAB tracks bundle events,
identifies its contributors from the manifest header and builds a
composite ClassResolver as in 1).
In any case, I would leave wicket-bundle and wicket-osgi out of the
game. There may be more than one WAB, each with a number of contributor
bundles, and the Wicket bundle cannot decide how to match them up.
While generating JDK / CGLib proxies, you need a class loader which can
access all proxied classes, one way to solve this is a minor change to the
IClassResolver interface to get access to the almightly class loader. I have
added a method getClassLoader(), which is used in the DefaultClassResolver
to load classes. This simple change will save some code duplication in OSGi
compatible classResolvers.
What's your use case for these proxies? Do you create them at
application level, or is this something that Spring DM does at framework
level.
- Another difference is how OSGi services are used; we are using Spring DM,
which creates one applicationContext per bundle. Fields annotated with
@SpringBean will be injected with beans (imported OSGi reference is also a
bean) from the applicationContext of the bundle in which the component is
created.
The wicket-osgi test bundles uses OSGi Blueprint. And Blueprint is
nothing but Spring DM standardized. However, wicket-osgi does NOT depend
on Blueprint.
wicket-osgi supports injection of OSGI service references via @Inject.
(This does not currently cover other Blueprint beans.)
I'm all in favour of injection by annotation - XML is not type safe and
violates the DRY principle. The problem is, there are too many competing
sets of annotations that all basically to the same thing:
- @Inject (JSR-330 and JSR-299 (CDI))
- @Autowired (Spring)
- @SpringBean (wicket-spring)
- @Inject + @OSGiService qualifier (Glassfish)
- @Reference, @Bean, @Service (Apache Aries)
I would love to see standardized annotations in the next version of the
OSGi Blueprint specification. Until then, I think the most portable
approach that does not tie you to any given implementation is @Inject +
@Qualifier (JSR-330).
In my opinion, the advantage of this is that each bundle has to be
explicit about the services it depends on, spring beans do not have to be
unique, not all beans have to be exported as OSGi service and there is need
to register ServiceTracker instances (Spring DM solves this problem).
Replace Spring DM by Blueprint and you're portable. And you can move
from Spring DM/Eclipse Gemini to Apache Aries which is the more solid
and innovative implementation, IMHO.
[This is an Apache mailing list, so I had to say that ;-) ]
- Is it an idea to extend the wicket-osgi project with some classes which
support this pattern?
Absolutely.
So wicket-osgi will become the toolkit you need when
combining OSGi and Wicket? I think it would be nice when it has injectors
for services from the OSGi service registry, as well as the pattern in which
spring beans from the bundle application context are used (more similar to
wicket-spring, the only difference is you have multiple, small application
contexts). One attachment to WICKET-3737 contains the injector stack
required for wiring spring beans from the bundle application context into
wicket components (not completely finished).
The first step is already made with the current @Inject support. This is
rather basic at the moment because it does not allow you to choose the
one you need when there's more than one service for a given interface.
Second step: support a JSR-330 qualifier (e.g. @OSGiService) that wraps
a filter and/or some service properties for service disambiguation.
Third step: additionally support injection of Blueprint Beans.
Any supporting framework classes for step 3 might have to move to a
separate bundle wicket-blueprint, because step 1 and 2 do not depend on
Blueprint. Service injection should work independent of the service
registration method (programmatically, DS, Blueprint, whatever...)
Cheers,
Harald
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org
For additional commands, e-mail: users-h...@wicket.apache.org