在Wicket中使用Hibernate和Spring的问题

时间:2012-08-10 11:50:28

标签: java spring hibernate dependency-injection wicket

我正在为我创建的数据库编写一个小的Web界面。数据库访问是通过Hibernate完成的,但它也使用Spring注入DAO实例(后者又注入了SessionFactory)。我在嵌入式Jetty服务器上测试Web界面。独立使用时一切正常:我可以从数据库项目中获取数据库中的东西,我可以在Jetty服务器上使用Wicket运行网页,我甚至设法让Spring为WicketTester工作,这有点痛苦在屁股。但是现在当我尝试从数据库中取出某些东西时(通过点击网页上的某个按钮),我收到一条错误消息:

java.lang.NullPointerException
     at nl.ru.cmbi.pdbeter.core.controller.DAO.GenericDAO.getCurrentSession(GenericDAO.java:37)

不知何故,应该在DAO中注入的sessionFactory没有被注入。我在Wicket模块的applicationContext.xml中定义了DAO bean,但是我认为只要它看到SessionFactory的@Autowired,它就会查看该项目的spring.xml文件,但显然它没有。我将在下面放一些代码来显示工作中的各个部分。

WicketApplication:

@Service
public class WicketApplication extends WebApplication {
    @SpringBean
    private IPDBEntryDAO    pdbEntryDAO;

    public IPDBEntryDAO getPdbEntryDAO() {
        return pdbEntryDAO;
    }

    public void setPdbEntryDAO(IPDBEntryDAO pdbEntryDAO) {
        this.pdbEntryDAO = pdbEntryDAO;
    }

    /**
     * @see org.apache.wicket.Application#getHomePage()
     */
    @Override
    public Class<HomePage> getHomePage() {
        return HomePage.class;
    }

    /**
     * @see org.apache.wicket.Application#init()
     */
    @Override
    public void init() {
        super.init();

        new ClassPathXmlApplicationContext("applicationContext.xml").getAutowireCapableBeanFactory().autowireBean(this);
    }

    public void setupInjector() {
        getComponentInstantiationListeners().add(new SpringComponentInjector(this));
    }
}

启动嵌入式Jetty服务器的类(从Wicket快速入门复制):

public class Start {
    public static void main(String[] args) throws Exception {
        int timeout = (int) Duration.ONE_HOUR.getMilliseconds();

        Server server = new Server();
        SocketConnector connector = new SocketConnector();

        // Set some timeout options to make debugging easier.
        connector.setMaxIdleTime(timeout);
        connector.setSoLingerTime(-1);
        connector.setPort(8080);
        server.addConnector(connector);

        // check if a keystore for a SSL certificate is available, and
        // if so, start a SSL connector on port 8443. By default, the
        // quickstart comes with a Apache Wicket Quickstart Certificate
        // that expires about half way september 2021. Do not use this
        // certificate anywhere important as the passwords are available
        // in the source.

        Resource keystore = Resource.newClassPathResource("/keystore");
        if (keystore != null && keystore.exists()) {
            connector.setConfidentialPort(8443);

            SslContextFactory factory = new SslContextFactory();
            factory.setKeyStoreResource(keystore);
            factory.setKeyStorePassword("wicket");
            factory.setTrustStoreResource(keystore);
            factory.setKeyManagerPassword("wicket");
            SslSocketConnector sslConnector = new SslSocketConnector(factory);
            sslConnector.setMaxIdleTime(timeout);
            sslConnector.setPort(8443);
            sslConnector.setAcceptors(4);
            server.addConnector(sslConnector);

            System.out.println("SSL access to the quickstart has been enabled on port 8443");
            System.out.println("You can access the application using SSL on https://localhost:8443");
            System.out.println();
        }

        WebAppContext bb = new WebAppContext();
        bb.setServer(server);
        bb.setContextPath("/");
        bb.setWar("src/main/webapp");

        // START JMX SERVER
        // MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
        // MBeanContainer mBeanContainer = new MBeanContainer(mBeanServer);
        // server.getContainer().addEventListener(mBeanContainer);
        // mBeanContainer.start();

        server.setHandler(bb);

        try {
            System.out.println(">>> STARTING EMBEDDED JETTY SERVER, PRESS ANY KEY TO STOP");
            server.start();
            System.in.read();
            System.out.println(">>> STOPPING EMBEDDED JETTY SERVER");
            server.stop();
            server.join();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }
}

web.xml文件:

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

    <display-name>web-interface</display-name>

    <!--
        There are three means to configure Wickets configuration mode and they 
        are tested in the order given.

        1) A system property: -Dwicket.configuration 
        2) servlet specific <init-param> 
        3) context specific <context-param>

        The value might be either "development" (reloading when templates change) or 
        "deployment". If no configuration is found, "development" is the default. -->

    <filter>
        <filter-name>wicket.web-interface</filter-name>
        <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
        <init-param>
            <param-name>applicationClassName</param-name>
            <param-value>nl.ru.cmbi.pdbeter.WicketApplication</param-value>
        </init-param>
        <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>
    </filter>

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

    <!-- The SpringWebApplicationFactory will need access to a Spring Application context, configured like this... -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>

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

applicationContext.xml文件:

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

    <!--
    <context:component-scan base-package="nl.ru.cmbi.pdbeter" />
    -->

    <!-- setup wicket application -->
    <bean id="wicketApplication" class="nl.ru.cmbi.pdbeter.WicketApplication">
        <property name="pdbEntryDAO" ref="pdbEntryDAO"/>
    </bean>

    <bean id="pdbEntryDAO" class="nl.ru.cmbi.pdbeter.core.controller.DAO.PDBEntryDAO" />
</beans>

数据库模块中DAO类的一部分:

public class GenericDAO<I> implements IGenericDAO<I> {
    private Class<I>        persistentClass;

    @Autowired
    private SessionFactory  sessionFactory;

    @SuppressWarnings("unchecked")
    public GenericDAO() {
        persistentClass = (Class<I>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }


    protected Session getCurrentSession() {
        return sessionFactory.getCurrentSession();
    }

数据库模块使用的spring.xml文件:

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" 
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:task="http://www.springframework.org/schema/task"
    xsi:schemaLocation="
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        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
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">


    <context:component-scan base-package="nl.ru.cmbi.pdbeter" />

    <!-- Transaction Manager -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <tx:annotation-driven />

    <!-- Session Factory -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="configLocation" value="hibernate.cfg.xml" />
        <property name="packagesToScan" value="nl.ru.cmbi.pdbeter.core.model.domain" />
    </bean>
</beans>

很抱歉发布了这么多代码,但我想如果不这样做,我可能会把重要的东西拿出来。

有没有人知道如何为Wicket模块和数据库模块注入所有内容?

0 个答案:

没有答案