Injection

Injection

While the classical Apache Wicket implementation has the SpringBean annotation this does not work the same way for Pax-Wicket. First of all in Pax-Wicket we do not encounter one single ApplicationContext but rather an entire range of (more than one is possible per bundle). In addition Pax-Wicket should support Spring-Bean-Injection as well as Blueprint-Bean-Injection. And if possible without any change of configuration. Finally, compared to the classical Wicket approach in Pax-Wicket one class could be registered in even one Application for multible different points. So a one-to-one copy of the Wicket approach wont work and we had to think about something new.

The Annotation

For Pax Wicket the standard javax.inject annotations are used. @Inject, @Named, ...

Overwrites

Overwrites are a quite important concept in Pax-Wicket. With their help it is possible to define alternative beans to be injected.

For example you have one Tab implementation which you would like to provide multiple times. Each time only the domain object differs, but nothing else. Nevertheless, with the classical approach you can not define multiple bean names for the various instances. Using Pax-Wicket Spring or Blueprint factories you can define bean overwrites at each ContentProvider in a Map<String,String>. For example, you define a PaxWicketBean(name="test") and provide the overwrite "test","abc" Pax-Wicket will lookup the bean "abc" instead of "test".

Please be aware that this only works if you use the name attribute of the PaxWicketBean annotation. Otherwise it is not possible to lookup the correct bean.

Let's see how this will look in code. Assume you've a page with the following code:

public class MyPage extends WebPage { @Inject @Named("provider") private MyPanelProvider provider; ... }

Now you want to export this page two time with different provider beans. So export the page like:

<wicket:page id="newPage" pageId="pageId" applicationName="aApp" pageName="pageName" pageClass="MyPage"> <wicket:overwrites> <wicket:overwrite originalBeanId="provider" newBeanId="serviceProvider" /> </wicket:overwrites> </wicket:page> <wicket:page id="newPage" pageId="pageId" applicationName="anotherApp" pageName="pageName" pageClass="MyPage"> <wicket:overwrites> <wicket:overwrite originalBeanId="provider" newBeanId="anotherServiceProvider2" /> </wicket:overwrites> </wicket:page>

Future Injection

You can use the following block of code now...

@Inject private Future<MyService> myServiceToInject;

This allows you to explicitely check if a service is available already or if it still needs to get injected.

Injection Source

Pax Wicket supports various technologies for injection. Typically "SCAN" is the default resolve types which tries to find a blueprint container, a spring container, a DS container, or uses plain OSGi services if nothing of the previous can be found. BUT in some environments it's possible to support blueprint and plain injection side by side. To support this you need to make use of the @PaxWicketBeanInjectionSource(PaxWicketBeanInjectionSource.INJECTION_SOURCE_SERVICE_REGISTRY). The value of the PaxWicketBeanInjectionSource defines which source should be used to inject the bean. If the source isnt available an exception will be thrown.

InjectorHolder

Sometimes objects are not inherited from Component and therefore the constructor is not called. Therefore the annotated fields are not injected. Similar to Wicket you have the option in Pax-Wicket to use the static InjectorHolder to inject your bean. This could look like the following for an external instance...

InjectorHolder.getInjector().inject(objectToInject);

... or like the following if you like to inject into the bean executing right now:

@Inject private MyBean bean; public Constructor { // some general setup InjectorHolder.getInjector().inject(this); }

Nasty Imports

For pax-wicket we need a way to inject beans within the bundle from the bundles application context. Therefore it is required that we extend the bundles at some parts with CG enhanced classes. This on the other hand has the downside that the bundle itself requires those dependencies. But, since those classes are added at runtime to the bundles, e.g. the maven bundle plugin can not know that those are required. Therefore, the only possible way is to add "org.ops4j.pax.wicket.util.proxy" manually as dependency.