开发者

How to make Spring play nice with Wicket? (ContextLoaderListener problem)

To my knowledge, and according to instructions I've found (like this and this too), I need this in web.xml for Spring to work:

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

In my Wicket application class, I'd have:

public class MyApplication extends WebApplication {

    @Override
    protected void init() {
        super.init();    
        addComponentInstantiationListener(new SpringComponentInjector(this));
    }

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

Problem is, whenever I have ContextLoaderListener in web.xml, Wicket doesn't start. I just get 404 errors (or blank page), and console output like:

SEVERE: Error listenerStart
Jun 28, 2011 12:49:04 PM org.apache.catalina.util.SessionIdGenerator createSecureRandom
INFO: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [1,973] milliseconds.
Jun 28, 2011 12:49:04 PM org.apache.catalina.core.StandardContext startInternal
SEVERE: Context [] startup failed due to previous errors
Jun 28, 2011 12:49:04 PM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: The web application [] registered the JDBC driver [org.hsqldb.jdbc.JDBCDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
Jun 28, 2011 12:49:04 PM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: The web application [] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
Jun 28, 2011 12:49:04 PM org.apache.catalina.startup.HostConfig deployDirectory

I'm using latest releases of both frameworks (Wicket 1.4.17 & Spring 3.0.5), and Tomcat 7 to run them on (the same thing happens with Tomcat 6). Also, I have the following jars in WEB-INF/lib. Something missing or too much?

antlr-2.7.6.jar                        log4j-1.2.16.jar              spring-web-3.0.5.jar
commons-collections-3.1.jar            mysql-connector-5.1.10.jar    slf4j-api-1.6.1.jar
dom4j-1.6.1.jar                        spring-beans-3.0.5.jar        slf4j-log4j12-1.6.1.jar
guava-r09.jar                          spring-context-3.0.5.jar      wicket-1.4.17.jar
hibernate-3.6.5.jar                    spring-core-3.0.5.jar         wicket-auth-roles-1.4.17.jar
hibernate-jpa-2.0-api-1.0.0.Final.jar  spring-jdbc-3.0.5.jar         wicket-datetime-1.4.17.jar
hsqldb.jar                             spring-orm-3.0.5.jar          wicket-ioc-1.4.17.jar
javassist-3.12.0.GA.jar                spring-test-3.0.5.jar         wicket-spring-1.4.17.jar
jta-1.1.jar                            spring-transaction-3.0.5.jar  wicketstuff-annotation-1.4.17.2.jar

The rest of the web.xml (I've tried setting up Wicket with both servlet and filter; makes no difference):

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">

    <display-name>My App</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>

    <context-param>
        <param-name>configuration</param-name>
        <param-value>development</param-value>
    </context-param>

    <filter>
        <filter-name>MyApp</filter-name>
        <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
        <init-param>
            <param-name>applicationClassName</param-name>
            <param-value>com.acme.MyApplication</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>MyApp</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

     <listener>
开发者_StackOverflow        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

</web-app>

Googling around I found someone with the same problem, but no solutions.

Funny thing is, I've had Spring and Wicket working together nicely before, with pretty much identical setup. Any ideas?


This is a configuration of my project:

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">

    <!-- Spring context config location(s) -->
    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/applicationContext.xml
    </param-value>
    </context-param>  

    <display-name>afrodite</display-name>

    <!-- used by Log4jConfigListener -->
    <context-param>
    <param-name>webAppRootKey</param-name>
    <param-value>afrodite.root</param-value>
    </context-param>     

    <context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>/WEB-INF/log4j.properties</param-value>
    </context-param>   

    <filter>
    <filter-name>openSessionInView</filter-name>
    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
    </filter>

    <filter>
    <filter-name>afrodite-app</filter-name>
    <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
    <init-param>
        <param-name>applicationClassName</param-name>
        <param-value>info.afrodite.wicket.AfroditeApplication</param-value>
    </init-param>
    <init-param>
        <param-name>configuration</param-name>
        <param-value>DEPLOYMENT</param-value>
    </init-param>
    </filter>    

    <!-- open session should be above the wicket filter -->
    <filter-mapping>
    <filter-name>openSessionInView</filter-name>
    <url-pattern>/app/*</url-pattern>
    </filter-mapping>     

    <filter-mapping>
    <filter-name>afrodite-app</filter-name>
    <url-pattern>/app/*</url-pattern>
    </filter-mapping>           

    <listener>
    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>

    <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
    <servlet-name>afrodite-api</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>2</load-on-startup>
    </servlet>

    <servlet-mapping>
    <servlet-name>afrodite-api</servlet-name>
    <url-pattern>/api/*</url-pattern>
    </servlet-mapping>    

    <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    </welcome-file-list>

</web-app>

Hope this will help.


Please check contextConfigLocation. The param-value should be classpath*:applicationContext.xml. Please check the listeners configuration also in my example. Hope I helped!

This is my web.xml configuration which nicely works:

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
     version="2.4">

    <display-name>mywebapp</display-name>

    <filter>
        <filter-name>springRequestContextFilter</filter-name>
        <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
    </filter>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath*:applicationContext.xml
        </param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

    <filter>
        <filter-name>wicket.mywebapp</filter-name>
        <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
        <init-param>
            <param-name>applicationClassName</param-name>
            <param-value>com.company.example.web.MyApplication</param-value>
        </init-param>
    </filter>

        <!-- Enables Spring Security -->
    <filter>
        <filter-name>filterChainProxy</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
      <filter-name>filterChainProxy</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>

 <filter-mapping>
  <filter-name>wicket.mywebapp</filter-name>
    <url-pattern>/*</url-pattern>
 </filter-mapping>

</web-app>


Edit: Later on I realised the root problem here most likely was missing log configuration. In our case (using SLF4J with log4j), after adding proper configuration in log4j.properties all kinds of warnings & errors logged by libraries became visible, even with Tomcat.


I tried Jetty instead of Tomcat, and started getting better error messages. Turns out there were several libraries missing — stuff needed by some of the libraries I already used.

2011-06-28 15:57:01.879:WARN::Unable to reach node goal: started
java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:184)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
    at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:640)

Some of the libs apparently require commons-logging, which I added. Next:

java.lang.NoClassDefFoundError: org/springframework/asm/ClassVisitor
    at org.springframework.context.support.AbstractRefreshableApplicationContext.customizeBeanFactory(AbstractRefreshableApplicationContext.java:218)

Added spring-asm. Next:

org.springframework.beans.factory.BeanDefinitionStoreException: 
  Unexpected exception parsing XML document from class path resource [applicationContext.xml]; 
  nested exception is java.lang.NoClassDefFoundError: org/springframework/aop/config/AopNamespaceUtils

Added spring-aop. Next something a little less straight-forward:

org.springframework.beans.factory.BeanDefinitionStoreException: 
  Unexpected exception parsing XML document from class path resource [applicationContext.xml]; 
  nested exception is java.lang.NoClassDefFoundError: org/aopalliance/intercept/MethodInterceptor

Found discussion about aopalliance missing in Spring blog comments. Apparently it has been completely removed from spring-aop, and you need to get aopalliance.jar from sourceforge.

(I think this kind of swamp is Java EE at its worst: I don't know what spring-asm or spring-aop let alone aopalliance do, but apparently I need them. :-P)

So, added aopalliance.jar. Later I still needed to add spring-expression and cglib-2.2 (which comes with Hibernate).

After that, some problems with my Spring/Hibernate persistence layer configuration remain, but they are out of scope for this question. Otherwise Wicket & Spring now work nicely (e.g. for injecting service layer objects on Wicket pages).

I guess one moral of this is that in some cases Tomcat eats useful error messages and Jetty might be better for debugging. Also, using Maven would have probably helped with the dependency hell somewhat (but it's not free of problems either).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜