SeamFramework.org Community Documentation

- Prev
- Next

## Chapter 13. Writing your presentation layer using Apache Wicket

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.

## 13.1. Adding Seam to your wicket application

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.

### 13.1.1. Bijection

A Seam enabled Wicket application has full access to the all the standard Seam contexts ( `EVENT` , `CONVERSATION` , `SESSION` , `APPLICATION` and `BUSINESS_PROCESS` ).

To access Seam component's from Wicket, you just need to inject it using `@In` :

    @In(create=true)

    private HotelBooking hotelBooking;

## Tip

As your Wicket class isn't a full Seam component, there is no need to annotate it `@Name` .

You can also outject an object into the Seam contexts from a Wicket component:

    @Out(scope=ScopeType.EVENT, required=false)

    private String verify;

TODO Make this more use case driven

### 13.1.2. Orchestration

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` .

## 13.2. Setting up your project

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.

### 13.2.1. Runtime instrumentation

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.

#### 13.2.1.1. Location-specific instrumentation

Any classes placed in the `WEB-INF/wicket` folder within your WAR deployment will be automatically instrumented by the seam-wicket runtime. You can arrange to place your wicket pages and components here by specifying a separate output folder for those classes in your IDE, or through the use of ant scripts.

#### 13.2.1.2. Runtime instrumentation agent

The jar file `jboss-seam-wicket.jar` can be used as an instrumentation agent through the Java Instrumentation api. This is accomplished through the following steps:

- Arrange for the `jboss-seam-wicket.jar` file to live in a location for which you have an absolute path, as the Java Instrumentation API does not allow relative paths when specifying the location of an agent lib.

- Add `javaagent:/path/to/jboss-seam-wicket.jar` to the command line options when launching your webapp container:

- In addition, you will need to add an environment variable that specifies packages that the agent should instrument. This is accomplished by a comma separated list of package names:

      -Dorg.jboss.seam.wicket.instrumented-packages=my.package.one,my.other.package

  Note that if a package A is specified, classes in subpackages of A are also examined. The classes chosen for instrumentation can be further limited by specifying:

      -Dorg.jboss.seam.wicket.scanAnnotations=true

  and then marking instrumentable classes with the `@SeamWicketComponent` annotation, see Section 13.2.3, “ The @SeamWicketComponent annotation ” .

### 13.2.2. Compile-time instrumentation

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

#### 13.2.2.1. Instrumenting with ant

Seam provides an ant task in the `jboss-seam-wicket-ant.jar` . This is used in the following manner:

    <taskdef name="instrumentWicket"
       classname="org.jboss.seam.wicket.ioc.WicketInstrumentationTask">
      <classpath>
        <pathelement location="lib/jboss-seam-wicket-ant.jar"/>
        <pathelement location="web/WEB-INF/lib/jboss-seam-wicket.jar"/>
        <pathelement location="lib/javassist.jar"/>
        <pathelement location="lib/jboss-seam.jar"/>
      </classpath>
    </taskdef>

    <instrumentWicket outputDirectory="${build.instrumented}" useAnnotations="true">
      <classpath refid="build.classpath"/>
      <fileset dir="${build.classes}" includes="**/*.class"/>
    </instrumentWicket>

This results in the instrumented classes being placed in the directory specified by `${build.instrumented}` . You will then need to instruct ant to copy these classes into `WEB-INF/classes` . If you want to hot deploy the Wicket components, you can copy the instrumented classes to `WEB-INF/dev` ; if you use hot deploy, make sure that your `WicketApplication` class is also hot-deployed. Upon a reload of hot-deployed classes, the entire WicketApplication instance has to be re-initialized, in order to pick up new references to the classes of mounted pages.

The `useAnnotations` attribute is used to make the ant task only include classes that have been marked with the `@SeamWicketComponent` annotation, see Section 13.2.3, “ The @SeamWicketComponent annotation ” .

#### 13.2.2.2. Instrumenting with maven

The jboss maven repository `repository.jboss.org` provides a plugin named `seam-instrument-wicket` with a `process-classes` mojo. An example configuration in your pom.xml might look like:

    <build>
        <plugins>
             <plugin>
                <groupId>org.jboss.seam</groupId>
                <artifactId>seam-instrument-wicket</artifactId>
                <version>2.2.0</version>
                <configuration>
                    <scanAnnotations>true</scanAnnotations>
                    <includes>
                        <include>your.package.name</include>
                    </includes>
                </configuration>
                <executions>
                    <execution>
                        <id>instrument</id>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>instrument</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

The above example illustrates that the instrumentation is limited to classes specified by the `includes` element. In this example, the `scanAnnotations` is specified, see Section 13.2.3, “ The @SeamWicketComponent annotation ” .

### 13.2.3. The `@SeamWicketComponent` annotation

Classes placed in WEB-INF/wicket will unconditionally be instrumented. The other instrumentation mechanisms all allow you to specify that instrumentation should only be applied to classes annotated with the `@SeamWicketComponent` annotation. This annotation is inherited, which means all subclasses of an annotated class will also be instrumented. An example usage is:

    import org.jboss.seam.wicket.ioc.SeamWicketComponent;

    @SeamWicketComponent
    public class MyPage extends WebPage
    {
     ...
    }

### 13.2.4. Defining the Application

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

## Tip

Take a look at the Wicket documentation for more on authorization strategies and other methods you can override on the `Application` class.

- PrevChapter 12. Groovy integration
- Top of page
- Front page
- NextChapter 14. The Seam Application Framework