Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [sisu-dev] Problem sharing method interceptors

Is your test code available online somewhere?

On 9 Apr 2014, at 11:34, gian.maria.romanato@xxxxxxxxxxxx wrote:

Hello,

I am using Sisu 0.2.0 in an OSGi container and I am trying to share the definition of an AOP method interceptor across multiple bundles.

According to https://bugs.eclipse.org/bugs/show_bug.cgi?id=403108 this should be done by listing the module that binds the method interceptor in the META-INF/sisu/com.google.inject.Module file of each bundle who wants to use the same interceptor.

Since I did not like the idea to declare the same module multiple times, following a suggestion by Stuart I customised the default extender and changed SisuTracker and SisuBundlePlan so that the extender creates a new instance of the shared module each time it creates a Guice Injector for a bundle. This was achieved by letting the shared module implement a custom marker interface (Shared), by making it bind itself under that marker interface in the configure() method,  and by using the bean locator to locate all shared modules so that they could be instantiated and passed to the bundle injector to be created. In other words, once the shared module is created by SisuExtensions, it is known to the bean locator and can be found and instantiated by the extender to extend bundles that are started later.

In practice, I overrode method compose() of SisuBundlePlan.

    @Override
    protected Module compose(Bundle bundle) {
        Key<Shared> key = Key.get(Shared.class);
        Iterable<? extends BeanEntry<Annotation, Shared>> result = locator.locate(key);

        List<Module> extraModules = new ArrayList<Module>(builtInModules);
        for (BeanEntry<Annotation, Shared> entry : result) {
            Shared value = entry.getValue();
            extraModules.add(value);
        }

        return new CustomModule(bundle, locator, extraModules);
    }

builtInModules is a class field holding list of modules that are passed to each BundleModule by my custom extender. It includes the LifeCycleModule and another module of mine, let's call it ModuleA. A new instance is created for every extended bundle.

Finally, CustomModule is an extension of BundleModule to change the way the BeanScanning strategy is selected and to override modules() method as follows:

 @Override
    protected List<Module> modules() {
        ArrayList<Module> all = new ArrayList<Module>();
        all.addAll(super.modules());
        all.addAll(builtInModules);
        return all;
    }

I created a singleton DefaultBeanLocator instance in my custom extender and use it at a later time to perform instantiation and injection in this way:

        Key<T> key = Key.get(type);
        Iterator<? extends Entry<?, T>> i = beanLocator.locate(key).iterator();
        if (i.hasNext()) {
            return i.next().getValue();
        }

Now, the problem is that when I request instantiation of a class that should be subject to the method interceptor, I am returned an instance of the plain class instead of the class enhanced by Guice to support the interceptor.

But, another method interceptor defined by my ModuleA works as expected.

Finally, I made the following test. I used the bean locator to locate all the Guice Injectors it knows, and tried instantiating my annotated class with any of those. Looks like more than one of them are capable of instantiating my annotated class, and only one of them is correctly returning the class enhanced by Guice, the one created for the bundle that  declares the annotated class, while the other Injector that shows up earlier in the list do not know the interceptor but still returns a not-enhanced instance of my annotated class:

Bundle1

Bundle2

  • depends on Bundle1
  • defines the shared module declaring the AOP interceptor
  • defines the annotated class that should be subject to AOP

When I ask the singleton bean locator to instantiate the annotated class, the class is found by the Injector created for Bundle1! and it is returned not enhanced.
If I iterate over all injectors known to the bean locator, I see that the injector for Bundle2 correctly returns the enhanced class.

So far I cound not figure out what the source of the problem could be, and why the injector for Bundle1 returns the instance of a class that is defined in another bundle that is started later. I thought I could have messed up with the BundleClassSpace in my extender, but that does not seem to be the case, as the BundleClassSpace is created using the right bundlecontext.

Any hint about a possible source of the problem?

Thanks in advance.
GianMaria.

_______________________________________________
sisu-dev mailing list
sisu-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/sisu-dev


Back to the top