SeamFramework.orgCommunity Documentation

Chapter 43. Seam for Apache Wicket Features

43.1. Injection
43.2. Conversation Control
43.3. Conversation Propagation

Seam's integration with Wicket is focused on two tasks: conversation propagation through Wicket page metadata and contextual injection of Wicket components.

Any object that extends org.apache.wicket.Component or one of its subclasses is eligible for injection with CDI beans. This is accomplished by annotating fields of the component with the @javax.inject.Inject annotation:

public class MyPage extends WebPage { 

   @Inject SomeDependency dependency;
   public MyPage() 

Note that since Wicket components must be serializable, any non-transient field of a Wicket component must be serializable. In the case of injected dependencies, the injected object itself will be serializable if the scope of the dependency is not @Dependent, because the object injected will be a serializable proxy, as required by the CDI specification. For injections of non-serializable @Dependent objects, the field should be marked transient and the injection should be looked up again in a component-specific attach() override, using the BeanManager API.

Upon startup, the CDI container will examine your component classes to ensure that the injections you use are resolvable and unambiguous, as per the CDI specification. If any injections fail this check, your application will fail to bootstrap.

The scopes available are similar to those in a JSF application, as descibed in the CDI reference. The container, in an JavaEE environment, or the servlet listeners, in a servlet environment, will set up the application, session, and request scopes. The conversation scope is set up by the SeamWebRequestCycle as outlined in the next two sections.

Application conversation control is accomplished as per the CDI specification. By default, like JSF/CDI, each Wicket HTTP request (whether AJAX or not) has a transient conversation, which is destroyed at the end of the request. A conversation is marked long-running by injecting the javax.enterprise.context.Conversation bean and calling its begin() method.

public class MyPage extends WebPage { 

   @Inject Conversation conversation;
   public MyPage() 
      //set up components here

Similarly, a conversation is ended with the Conversation bean's end() method.

A transient conversation is created when the first Wicket IRequestTarget is set during a request. If the request target is an IPageRequestTarget for a page which has previously marked a conversation as non-transient, or if the cid parameter is present in the request, the specified conversation will be activated. If the conversation is missing (i.e. has timed out and been destroyed), SeamRequestCycle.handleMissingConversation() will be invoked. By default this does nothing, and your conversation will be new and transient. You can however override this, for example to throw a PageExpiredException or something similar. Upon the end of a response, SeamRequestCycleProcessor will store the cid of a long running conversation, if one exists, to the current page's metadata map, if there is a current page. The key for the cid in the metadata map is the singleton SeamMetaData.CID. Finally, upon detach(), the SeamRequestCycle will invalidate and deactive the conversation context.

Note that the above process indicates that after a conversation is marked long-running by a page, requests back to that page (whether ajax or not) will activate that conversation. It also means that new Pages set as RequestTargets, if created directly with setResponsePage(somePageInstance) or with setResponsePage(SomePage.class,pageParameters), will have the conversation propagated to them. This can be avoided by (a) ending the conversation before the call to setResponsePage, (b) using a BookmarkablePageLink rather than directly instantiating the response page, or (c) specifying an empty cid parameter in PageParameters when using setResponsePage(). (Note that the final case also provides a mechanism for switching conversations: if a cid is specified in PageParameters, it will be used by bookmarkable pages, rather than the current conversation.)