-
Notifications
You must be signed in to change notification settings - Fork 298
SpringReference
The wicketstuff-springreference module can be used to integrate a wicket web application with spring. It is independent from wicket-spring and can be used for cases where @SpringBean is not an option. With wicketstuff-springreference is it also possible to use spring annotation driven injection (for example @Autowired, @Qualifier).
From wicket-spring the @SpringBean annotation together with the SpringComponentInjector class give a slick way to inject spring beans into components. However it is using a technology called "dynamic proxy" and this is not always working. This limits the usability of @SpringBean in some cases. When you hit these limitations you probably see strange exceptions like these:
Caused by: java.lang.IllegalArgumentException: Protected method: fooMethod()V
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:196)
at org.apache.wicket.proxy.LazyInitProxyFactory$CGLibInterceptor.intercept(LazyInitProxyFactory.java:320)
or
Caused by: java.lang.IllegalArgumentException: No visible constructors in class FooClass
at net.sf.cglib.proxy.Enhancer.filterConstructors(Enhancer.java:531)
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:448)
The SpringReference and AbstractSpringDependencies class from wicketstuff-springreference are not annotation/dynamic proxy based so they work in all cases (but using them does not look that cool as an annotation). Both can be used independently or together for spring - wicket integration.
Because SpringReference does not depend on IComponentInstantiationListener-s and looks up beans lazily it could also be slightly faster than @SpringBean.
AbstractSpringDependencies makes spring annotation driven injection possible in wicket apps.
Add this to your pom.xml:
<dependency>
<groupId>org.wicketstuff</groupId>
<artifactId>wicketstuff-springreference</artifactId>
<version>[some-version]</version>
</dependency>
To enable SpringReference or AbstractSpringDependencies support you have to register a SpringReferenceSupporter with your WebApplication. This can be done in the init() method:
public class App extends WebApplication {
@Override
public Class<? extends Page> getHomePage() {
return HomePage.class;
}
@Override
protected void init() {
super.init();
getMarkupSettings().setDefaultMarkupEncoding(CharEncoding.UTF_8);
/* --> */ SpringReferenceSupporter.register(this); /* <-- */
}
}
Now you can refer spring beans in your wicket components, models, etc. and in your custom classes too:
Declaring SpringReference is simple enough:
// reference by type and bean id
private final SpringReference<AuthenticationManager> authenticationManagerRef =
SpringReference.of(AuthenticationManager.class, "authenticationManager");
// reference by type only
private final SpringReference<AbstractRememberMeServices> rememberMeServicesRef =
SpringReference.of(AbstractRememberMeServices.class);
And to access the beans you can use the get() method of the SpringReference objects:
authenticationManagerRef.get().authenticate(token);
AbstractRememberMeServices rememberMeServices = rememberMeServicesRef.get();
This is a bit trickier. You have to define a subclass to encapsulate the spring dependencies. Note the Deps class in the example below. Also note that the dependencies are marked as transient so they are not serialized by wicket. They are reinjected by Deps (AbstractSpringDependencies) during deserialization.
public class MySession extends AuthenticatedWebSession
{
private static final long serialVersionUID = 1L;
// This nested class holds all our spring dependencies. Annotated in spring style.
static class Deps extends AbstractSpringDependencies
{
private static final long serialVersionUID = 1L;
@Autowired
@Qualifier("authenticationManager")
transient AuthenticationManager authenticationManager;
@Autowired
transient AbstractRememberMeServices abstractRememberMeServices;
}
private final Deps deps = new Deps();
// ...
public boolean authenticate(String username, String password)
{
// ...
deps.authenticationManager.authenticate(token);
AbstractRememberMeServices rememberMeServices = deps.abstractRememberMeServices;
// ...
}
}
Wicketstuff-springreference depends on wicket 1.5-RC7<= and spring-web 3.0<=.
For more info see the javadoc of SpringReference, AbstractSpringDependencies and SpringReferenceSupporter classes. For a complete @SpringBean - SpringReference - AbstractSpringDependencies example see the wicketstuff-springreference-examples web application.