0

私が作成したデータベース用の小さな Web インターフェイスを作成しています。データベースへのアクセスは Hibernate を介して行われますが、Spring を使用して DAO のインスタンスを注入します (さらに、SessionFactory が注入されます)。組み込みの Jetty サーバーで Web インターフェイスをテストします。独立して使用すると、すべてが正常に機能します。データベース プロジェクトからデータベースからデータを取得できます。Jetty サーバーで Wicket を使用して Web ページを実行できます。Spring を WicketTester で動作させることさえできましたが、これは少し面倒でした。お尻で。しかし、データベースから何かを取得しようとすると (Web ページのボタンをクリックして)、次のようなエラーが表示されます。

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 ファイルが表示されると想定していましたが、そうではないようです。動作中の個々のパーツを示すために、いくつかのコードを以下に示します。

ウィケットアプリケーション:

@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モジュールとデータベースモジュールの両方で、すべてが確実に注入されるようにする方法を知っている人はいますか?

4

0 に答える 0