Seam FrameworkCommunity Documentation

Chapter 13. Writing your presentation layer using Apache Wicket

13.1. Adding Seam to your wicket application
13.1.1. Bijection
13.1.2. Orchestration
13.2. Setting up your project
13.2.1. Runtime instrumentation
13.2.2. Compile-time instrumentation
13.2.3. The @SeamWicketComponent annotation
13.2.4. Defining the Application

Seam supports Wicket as an alternative presentation layer to JSF. Take a look at the wicket example in Seam which shows the Booking Example ported to Wicket.

Note

Wicket support is new to Seam, so some features which are available in JSF are not yet available when you use Wicket (e.g. pageflow). You'll also notice that the documentation is very JSF-centric and needs reorganization to reflect the first class support for Wicket.

The features added to your Wicket application can be split into two categories: bijection and orchestration; these are discussed in detail below.

Extensive use of inner classes is common when building Wicket applications, with the component tree being built in the constructor. Seam fully supports the use of annotation based control in inner classes and constructors (unlike regular Seam components).

Annotations are processed after any call to a superclass. This mean's that any injected attributes cannot be passed as an argument in a call to this() or super() .

When a method is called in an inner class, bijection occurs for any class which encloses it. This allows you to place your bijected variables in the outer class, and refer to them in any inner class.

You can secure a Wicket component by using the @Restrict annotation. This can be placed on the outer component or any inner components. If @Restrict is specified, the component will automatically be restricted to logged in users. You can optionally use an EL expression in the value attribute to specify a restriction to be applied. For more refer to the Chapter 16, Security .

For example:

@Restrict

public class Main extends WebPage
{
   ...

Tip

Seam will automatically apply the restriction to any nested classes.

You can demarcate conversations from within a Wicket component through the use of @Begin and @End . The semantics for these annotations are the same as when used in a Seam component. You can place @Begin and @End on any method.

Note

The deprecated ifOutcome attribute is not supported.

For example:

item.add(new Link("viewHotel") {


   @Override
   @Begin
   public void onClick() {
      hotelBooking.selectHotel(hotel);
      setResponsePage(org.jboss.seam.example.wicket.Hotel.class);
   }
};

You may have pages in your application which can only be accessed when the user has a long-running conversation active. To enforce this you can use the @NoConversationPage annotation:

@Restrict

@NoConversationPage(Main.class)
public class Hotel extends WebPage 
{

If you want to further decouple your application classes, you can use Seam events. Of course, you can raise an event using Events.instance().raiseEvent("foo") . Alternatively, you can annotate a method @RaiseEvent("foo") ; if the method returns a non-null outcome without exception, the event will be raised.

You can also control tasks and processes in Wicket classes through the use of @CreateProcess , @ResumeTask , @BeginTask , @EndTask , @StartTask and @Transition .

Seam needs to instrument the bytecode of your Wicket classes to be able to intercept the annotations you use. The first decision to make is: do you want your code instrumented at runtime as your app is running, or at compile time? The former requires no integration with your build environment, but has a performance penalty when loading each instrumented class for the first time. The latter is faster, but requires you to integrate this instrumentation into your build environment.

There are two ways to achieve runtime instrumentation. One relies on placing wicket components to be instrumented in a special folder in your WAR deployment. If this is not acceptable or possible, you can also use an instrumentation "agent," which you specify in the command line for launching your container.

Seam supports instrumentation at compile time through either Apache Ant or Apache Maven.

A Wicket web application which uses Seam should use SeamWebApplication as the base class; this creates hooks into the Wicket lifecycle allowing Seam to automagically propagate the conversation as needed. It also adds status messages to the page.

For example:

The SeamAuthorizationStrategy delegates authorization to Seam Security, allowing the use of @Restrict on Wicket components. SeamWebApplication installs the authorization strategy for you. You can specify the login page by implementing the getLoginPage() method.

You'll also need to set the home page of the application by implementing the getHomePage() method.

public class WicketBookingApplication extends SeamWebApplication

{
   @Override
   public Class getHomePage() 
   {
      return Home.class;
   }
   @Override
   protected Class getLoginPage() 
   {
      return Home.class;
   }
}

Seam automatically installs the Wicket filter for you (ensuring that it is inserted in the correct place for you). But you still need to tell Wicket which WebApplication class to use.


<components xmlns="http://jboss.org/schema/seam/components"
 xmlns:wicket="http://jboss.org/schema/seam/wicket"
 xsi:schemaLocation=
  "http://jboss.org/schema/seam/wicket
   http://jboss.org/schema/seam/wicket-2.3.xsd">
   
  <wicket:web-application 
    application-class="org.jboss.seam.example.wicket.WicketBookingApplication" />
</components

In addition, if you plan to use JSF-based pages in the same application as wicket pages, you'll need to ensure that the jsf exception filter is only enabled for jsf urls:


<components xmlns="http://jboss.org/schema/seam/components"
 xmlns:web="http://jboss.org/schema/seam/web"
 xmlns:wicket="http://jboss.org/schema/seam/wicket"
 xsi:schemaLocation=
  "http://jboss.org/schema/seam/web
   http://jboss.org/schema/seam/web-2.3.xsd">
     
    <!-- Only map the seam jsf exception filter to jsf paths, which we identify with the *.seam path -->
    <web:exception-filter url-pattern="*.seam"/>
</components