Help

This is the second part in my short series on using Wicket with Seam.

In the first part we looked at how to create a project. Here, we'll get to the meat of how you can use Seam Security, conversations and bijection and more of Seam's goodies with Wicket. One of the primary goals of Seam is to allow you to use one kind of stuff when writing your project, so when integrating with Wicket with Seam we've tried, as far as possible, to allow you to use exactly the same annotations, with exactly the same meaning in your Wicket application.

Of course, some annotations and their results don't make sense when using Wicket, and some annotations just aren't supported yet - if you see an annotation you would like supported in Wicket, please let us know.

Security

First, let's look at using Seam Security with Wicket. Both @Restrict and @RoleCheck are supported. You can read more about the use of these annotations and their attributes in the Seam Security chapter; but briefly

  • Applying @Restrict("#{identity.loggedIn}") to a Wicket component will require the user to be logged in to access that component. You can define the annotation on a page class to restrict access to the entire page, or on just a sub-component to restrict access to that sub component.

For example, here the user must be logged in to access the home page:

@Restrict("#{identity.loggedIn}")
public class HomePage extends WebPage {
  • Annotating a page or component with an annotation which has the @RoleCheck meta-annotation

For example, here only administrators can access the admin page:

@RoleCheck
@Target(TYPE)
@Retention(RUNTIME)
public @interface Admin {}
@Admin
public class AdminPage extends WebPage {

Finally, you can set the login page through your Application:

public class WicketBookingApplication extends SeamWebApplication {

   protected Class getLoginPage() {
      return Home.class;
   }

Conversations and Validation

Just as you can use @Begin and @End in a Seam component to start and end a conversation, you can do the same in your Wicket component. For example, to start a long running conversation as we click on the link to create a new user. We can even enable manual flush mode to start an atomic conversation:

public class HomePage extends WebPage {

   public HomePage(PageParameters parameters) {
      add(new Link("createUser") {

         @Begin(flushMode=MANUAL)
         public void onClick() {
            setResponsePage(com.mydomain.wicket_tutorial.web.CreateUser.class);
         }
      });
   }

The User entity probably has some Hibernate Validator constraints which we want to apply. Seam provides a Wicket validator, org.jboss.seam.wicket.ModelValidator which will apply the constraints to the Wicket input component:

public class CreateUser extends WebPage {

   @In UserManager userManager;
   
   public CreateUser(PageParameters parameters) {
      super(parameters);
      add(new CreateUserForm("userForm"));
   }

   public class CreateUserForm extends Form {
      
      public CreateUserForm(String id) {
         super(id);
         // Add a field label
         add(new Label("usernameLabel", "Username:"));

         TextField username = new TextField("username");

         // Attach the field to the Entity
         username.setModel(new PropertyModel(userManager.getUser(), "username"));

         // Attach the Seam model based validator
         username.addValidator(new ModelValidator(User.class, "username"));
         add(username);

         // Give feedback to the user if there is an error
         add(new FeedbackPanel("message", new ContainerFeedbackMessageFilter(username)));
      }

Of course, you can easily wrap this behaviour up in a Wicket border (take a look at FormInputBorder.java and FormInputBorder.html in the Wicket example).

Finally, we want to end the conversation when the user submits the form:

     @End 
      protected void onSubmit() {
         userManager.createUser();
      }
   }
}

You could even start a conversation on a regular Seam component, and end it in Wicket!

Sometimes, you might want to ensure that a Wicket page can only be accessed inside a long running conversation; you can do this using the @NoConversationPage annotation:

@NoConversationPage(HomePage.class)
public class CreateUser extends WebPage {

Bijection

In part 1 we showed some basic injection, and it really doesn't get any harder! Let's say the User entity was a Seam component as well, we could just biject it into the Wicket component:

public class CreateUser extends WebPage {

   // You can even use the Seam logger!
   @Logger static Log log;

   @In UserManager userManager;
   @In @Out User user;

And more!

Seam's event bus is a simple way to write a very loosely coupled application. You might want to use events from Wicket; of course, you can raise an event programatically:

     @End 
      protected void onSubmit() {
         userManager.createUser();
         Events.instance.raiseEvent("userCreated");
      }
   }
}

But you might want to do it declaratively:

     @End
      @RaiseEvent("userCreated")
      protected void onSubmit() {
         userManager.createUser();
      }
   }
}

And finally, Seam provides a simple way to add messages to display to the user in the business layer:

@Name("userManager")
public class UserManager {

   @In EntityManager entityManager;
   @In StatusMessages statusMessages;

   User user = new User();

   public User getUser() {
      return user;
   }

   public void createUser() {
      entityManager.persist(user);
      statusMessages.add("User " + user.getName() + " created!");
   }
}

So, armed with this toolkit, you should be able to create powerful Wicket applications with Seam!

2 comments:
 
21. Oct 2008, 03:28 CET | Link
Oncle Zebulon

Hi, The setValidator is not available on TextField. I think you mean add whereas setValidator... Oncle Zebulon

 
13. Nov 2008, 16:25 CET | Link
Gandalf

I just had a look at the seam/wicket integration replacing the jsf ui-layer of seam which is really well done :)

For a new project I like to use seam once again because it's simplicity and transparent use of j2ee features is unreached. But what we also really need to shorten development time is an ui-framework that allows us to complete work using java without breaking the possibility to build a smooth ui experience with customizable look. In short: We are just building a little test app using the echo3 framework.

Do you think echo3 and seam can be integrated in a similar manner as wicket and seam? Do you see any problems? Would an integration like that be reasonable?

Gandalf