SeamFramework.orgCommunity Documentation
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.
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.
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;
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
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
{
...
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.
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.
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.
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
”
.
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:
<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
”
.
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
”
.
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 { ... }
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
Take a look at the Wicket documentation for more on
authorization
strategies and other methods you can override on the
Application
class.