SeamFramework.orgCommunity Documentation

Chapter 12. Writing your presentation layer using Apache Wicket

12.1. Adding Seam to your wicket application
12.1.1. Bijection
12.1.2. Orchestration
12.2. Setting up your project
12.2.1. Runtime instrumentation
12.2.2. Compile-time instrumentation
12.2.3. The @SeamWicketComponent annotation
12.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 15, 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.

TODO - Implement BPM control - JBSEAM-3194

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.

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

<!-- XML : generated by JHighlight v1.0 (http://jhighlight.dev.java.net) -->
<span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">taskdef</span><span class="xml_plain">&nbsp;</span><span class="xml_attribute_name">name</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">&quot;instrumentWicket&quot;</span><span class="xml_plain">&nbsp;</span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;</span><span class="xml_attribute_name">classname</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">&quot;org.jboss.seam.wicket.ioc.WicketInstrumentationTask&quot;</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">classpath</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">pathelement</span><span class="xml_plain">&nbsp;</span><span class="xml_attribute_name">location</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">&quot;lib/jboss-seam-wicket-ant.jar&quot;</span><span class="xml_tag_symbols">/&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">pathelement</span><span class="xml_plain">&nbsp;</span><span class="xml_attribute_name">location</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">&quot;web/WEB-INF/lib/jboss-seam-wicket.jar&quot;</span><span class="xml_tag_symbols">/&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">pathelement</span><span class="xml_plain">&nbsp;</span><span class="xml_attribute_name">location</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">&quot;lib/javassist.jar&quot;</span><span class="xml_tag_symbols">/&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">pathelement</span><span class="xml_plain">&nbsp;</span><span class="xml_attribute_name">location</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">&quot;lib/jboss-seam.jar&quot;</span><span class="xml_tag_symbols">/&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">classpath</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">taskdef</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain"></span><br />
<span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">instrumentWicket</span><span class="xml_plain">&nbsp;</span><span class="xml_attribute_name">outputDirectory</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">&quot;${build.instrumented}&quot;</span><span class="xml_plain">&nbsp;</span><span class="xml_attribute_name">useAnnotations</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">&quot;true&quot;</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">classpath</span><span class="xml_plain">&nbsp;</span><span class="xml_attribute_name">refid</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">&quot;build.classpath&quot;</span><span class="xml_tag_symbols">/&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">fileset</span><span class="xml_plain">&nbsp;</span><span class="xml_attribute_name">dir</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">&quot;${build.classes}&quot;</span><span class="xml_plain">&nbsp;</span><span class="xml_attribute_name">includes</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">&quot;**/*.class&quot;</span><span class="xml_tag_symbols">/&gt;</span><span class="xml_plain"></span><br />
<span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">instrumentWicket</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />

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 12.2.3, “The @SeamWicketComponent annotation”.

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:

<!-- XML : generated by JHighlight v1.0 (http://jhighlight.dev.java.net) -->
<span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">build</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">plugins</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">plugin</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">groupId</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain">org.jboss.seam</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">groupId</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">artifactId</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain">seam-instrument-wicket</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">artifactId</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">version</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain">2.2.0</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">version</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">configuration</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">scanAnnotations</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain">true</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">scanAnnotations</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">includes</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">include</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain">your.package.name</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">include</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">includes</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">configuration</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">executions</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">execution</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">id</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain">instrument</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">id</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">phase</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain">process-classes</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">phase</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">goals</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;</span><span class="xml_tag_name">goal</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain">instrument</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">goal</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">goals</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">execution</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">executions</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">plugin</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_plain">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">plugins</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />
<span class="xml_tag_symbols">&lt;/</span><span class="xml_tag_name">build</span><span class="xml_tag_symbols">&gt;</span><span class="xml_plain"></span><br />

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 12.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:

<!-- <br/> --><span class="java_keyword">import</span><!-- <br/> --><span class="java_plain">&nbsp;org</span><!-- <br/> --><span class="java_separator">.</span><!-- <br/> --><span class="java_plain">jboss</span><!-- <br/> --><span class="java_separator">.</span><!-- <br/> --><span class="java_plain">seam</span><!-- <br/> --><span class="java_separator">.</span><!-- <br/> --><span class="java_plain">wicket</span><!-- <br/> --><span class="java_separator">.</span><!-- <br/> --><span class="java_plain">ioc</span><!-- <br/> --><span class="java_separator">.</span><!-- <br/> --><span class="java_type">SeamWicketComponent</span><!-- <br/> --><span class="java_separator">;</span>
<!--  --><br/><span class="java_plain">@</span><span class="java_type">SeamWicketComponent</span>
<!--  --><br/><span class="java_keyword">public</span><span class="java_plain">&nbsp;</span><span class="java_keyword">class</span><span class="java_plain">&nbsp;</span><span class="java_type">MyPage</span><span class="java_plain">&nbsp;</span><span class="java_keyword">extends</span><span class="java_plain">&nbsp;</span><span class="java_type">WebPage</span><span class="java_separator">{</span>
<!--  --><br/><span class="java_plain">&nbsp;</span><span class="java_separator">...</span>
<!--  --><br/><span class="java_separator">}</span>

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.com/products/seam/components"
 xmlns:wicket="http://jboss.com/products/seam/wicket"
 xsi:schemaLocation=
  "http://jboss.com/products/seam/wicket
   http://jboss.com/products/seam/wicket-2.2.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.com/products/seam/components"
 xmlns:web="http://jboss.com/products/seam/web"
 xmlns:wicket="http://jboss.com/products/seam/wicket"
 xsi:schemaLocation=
  "http://jboss.com/products/seam/web
   http://jboss.com/products/seam/web-2.2.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