Sunday, February 5, 2012

Integrating Wicket with Spring

In this short example I will show you how to integrate Wicket 1.5 with Spring 3. Wicket is a rich web framework that allows creating web applications using simple html and Java code. Wicket has its own IOC/DI engine, but Spring has become a de-facto standard for service layer.

Let's start with a new Maven project. First we need to setup dependencies to be loaded from repositories.

Wicket Framework:

  • wicket-core
  • wicket-util
  • wicket-ioc
  • wicket-request
 <dependency>
    <groupId>org.apache.wicket</groupId>
    <artifactId>wicket-core</artifactId>
    <version>${wicket.version}</version>
 </dependency>
 <dependency>
    <groupId>org.apache.wicket</groupId>
    <artifactId>wicket-util</artifactId>
    <version>${wicket.version}</version>
 </dependency>
 <dependency>
    <groupId>org.apache.wicket</groupId>
    <artifactId>wicket-ioc</artifactId>
    <version>${wicket.version}</version>
 </dependency>
 <dependency>
    <groupId>org.apache.wicket</groupId>
    <artifactId>wicket-request</artifactId>
    <version>${wicket.version}</version>
 </dependency>



 Spring Framework:
  • spring-context
  • spring-web
<dependency>            
  <groupId>org.springframework</groupId>            
  <artifactId>spring-context</artifactId>            
  <version>${spring.version}</version>            
  <exclusions>              
    <exclusion>                                    
      <groupId>commons-logging</groupId>               
      <artifactId>commons-logging</artifactId>                               
    </exclusion>                         
  </exclusions>                   
</dependency>                   
<dependency>                       
  <groupId>org.springframework</groupId>                       
  <artifactId>spring-context-support</artifactId>                       
  <version>${spring.version}</version>                   
</dependency>                   
<dependency>                       
  <groupId>org.springframework</groupId>                       
  <artifactId>spring-web</artifactId>                       
  <version>${spring.version}</version>               
</dependency>



Wicket-Spring Integration and Annotation Support:

<dependency>
  <groupId>org.apache.wicket</groupId>
  <artifactId>wicket-spring</artifactId>
  <version>${wicket.version}</version>
  <!-- exclude spring framework that wicket pulls in -->
  <exclusions>
    <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>spring</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>org.apache.wicket</groupId>
  <artifactId>wicket-spring-annot</artifactId>
  <version>${wicket-spring-annot.version}</version>
  <!-- exclude spring framework that wicket pulls in -->
  <exclusions>
    <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>spring</artifactId>
    </exclusion>
  </exclusions>
</dependency>



Add these version constants to your POM properties:

<properties>       
 <spring.version>3.0.6.RELEASE</spring.version>
 <wicket.version>1.5.4</wicket.version>
 <wicket-spring-annot.version>1.3.7</wicket-spring-annot.version>
</properties>



Then we need to register a listener that would load Spring context and a Wicket filter to process requests. Add the following lines to web.xml:

<context-param>          
  <param-name>contextConfigLocation</param-name>          
  <param-value>classpath:context.xml</param-value>    
</context-param>    
<servlet>          
  <servlet-name>wicket</servlet-name>          
  <servlet-class>org.apache.wicket.protocol.http.WicketServlet</servlet-class>          
  <init-param>                
    <param-name>applicationFactoryClassName</param-name>                
    <param-value>org.apache.wicket.spring.SpringWebApplicationFactory</param-value>          
  </init-param>          
  <init-param>                
    <param-name>applicationBean</param-name>                
    <param-value>wicketApplication</param-value>          
  </init-param>          
  <load-on-startup>1</load-on-startup>    
</servlet>    
<servlet-mapping>          
  <servlet-name>wicket</servlet-name>          
  <url-pattern>/*</url-pattern>    
</servlet-mapping>    
<listener>          
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>    
</listener>


Then we need to configure Spring Context, to turn on the annotation-driven configuration. Create a new file context.xml in your default package and put the following lines into it:

<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:annotation-config />
    <context:component-scan base-package="web"/>

</beans>

Then create a Java Class called WicketApplication in web package. This class will be our main Wicket Application class.

package web;

import org.apache.wicket.Page;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.spring.injection.annot.SpringComponentInjector;
import org.springframework.stereotype.Component;

/**
 * Wicket Application
 *
 * @author sergej.sizov
 */
@Component("wicketApplication")
public class WicketApplication extends WebApplication {

    @Override
    public Class<? extends Page> getHomePage() {
        return HomePage.class;
    }

    @Override
    protected void init() {
        // !!! - do not forget to call init on parent
        super.init();
        // initialize Spring
        getComponentInstantiationListeners().add(new SpringComponentInjector(this));
    }
}


Now lets create a Spring Service that would return a message to be shown on our page.

package web;

import org.springframework.stereotype.Component;
/**
 * Hello Service
 *
 * @author sergej.sizov
 */
@Component("helloService")
public class HelloService {

  public String getMessage() {
    return "Hello World!";
  }

}


Then we need to create a Home Page that will be shown as a default page. We need to create a HTML template and a Java class that would process actions and data binding.

web/HomePage.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html xmlns:wicket="http://wicket.apache.org">
    <wicket:head>
        <title>Home Page</title>
    </wicket:head>
    <body>
        <span wicket:id="msg" />
    </body>
</html>


web/HomePage.java

package web;

import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.spring.injection.annot.SpringBean;


/**
 * Home Page
 *
 * @author sergej.sizov
 */
public class HomePage extends WebPage {

    @SpringBean
    protected HelloService helloService;  
  
    public HomePage(final PageParameters parameters) {
        add(new Label("msg", helloService.getMessage());
    }

}


HelloService will be injected into Wicket Page using @SpringBean annotation.

Integration is done. To see if it works we need to run it in a web container e.g. tomcat or jetty.

If you want to test your Wicket application with Jetty, you can add the following lines into your build plugins:

<plugin>               
  <groupId>org.mortbay.jetty</groupId>               
  <artifactId>maven-jetty-plugin</artifactId>               
  <version>6.1.16</version>               
  <configuration>                   
    <contextPath>/</contextPath>                   
    <scanTargets>                       
      <scanTarget>target/classes/</scanTarget>                   
    </scanTargets>                   
    <scanIntervalSeconds>5</scanIntervalSeconds>               
  </configuration>           
</plugin>


Then just run Maven with jetty:run parameter:

mvn jetty:run

2 comments:

  1. Hi,

    You can reduce the Wicket dependencies just to:

    org.apache.wicket
    wicket-spring
    ${wicket.version}


    Maven will download all other as transitive dependencies.

    ReplyDelete
  2. Can you attach project so I can download and try. I am getting error while running in jetty.

    ReplyDelete