【问题标题】:How to obtain JNDI data source for JPA/JTA DAO integration test?JPA/JTA DAO集成测试如何获取JNDI数据源?
【发布时间】:2010-06-09 17:59:11
【问题描述】:

我有一个 JPA 应用程序,它在 persistence.xml 中指定了 JTA 事务。无论出于何种原因,我发现在使用 JTA 时,您还必须在 persistence.xml 中指定一个 JNDI 数据源。这很好,除非您尝试在容器外进行集成测试并且 JNDI 不可用。

我的问题是:

a) 是否可以将 jdbc 数据源注入到我的 JTA 事务管理器中? b) 如果没有,在集成测试期间如何处理 JNDI 查找?

编辑:启动集成测试时出现的错误是:

 Caused by: org.springframework.......DataSourceLookupFailureException:
 Failed to look up JNDI DataSource with name 'java:comp/env/jdbc/myAppDataSource';
 nested exception is javax.naming.NoInitialContextException: Need to specify
 class name in environment or system property, or as an applet parameter,
 or in an application resource file:  java.naming.factory.initial

【问题讨论】:

    标签: jpa datasource integration-testing jndi jta


    【解决方案1】:

    我自己并没有对此进行试验,但它可以通过独立的事务管理器和符合 XA 的数据源来实现。在 Spring 2.5 中,大多数示例使用 JOTM 以及 JotmFactoryBeanXAPool。但是这些在 Spring 3.0 中不再支持,Atomikos 似乎是“替代品”(它提供了一个独立的事务管理器和一个 XA 数据源)。我在下面添加了一些配置示例。

    替代方法是运行容器内测试(使用嵌入式 Java EE 容器,例如 GlassFish v3 Embedded 或类似 Cargo 的 API)。

    资源

    【讨论】:

    • JotmFactoryBean 的链接已损坏。事实上,Spring-tx 3.0.1 中缺少该类。我正在尝试使用 Atomikos 作为独立的事务管理器。但是,Spring(或 JPA/Hibernate)继续尝试从 jndi 中查找 JTA 数据源,该数据源在 persistence.xml 中指定。
    • @HDave 确实,我没有注意到,但 JOTM 的东西已从 Spring 3.x 中删除(我猜这是有充分理由的)。我已经更新了我的答案。关于 JPA,我认为您将需要 blog post 中描述的技巧(我现在理解得更好了)。
    • 我已经非常仔细地阅读了资源。我看到重要的是通过 hibernate.transaction.factory_class 和 manager_lookup_class “告诉” Hibernate 关于 Atomikos 的信息——太棒了!但在所有情况下,我都看到 Entity Manager 配置提供了一个数据源。根据数据源上的 Spring javadocs “在 JPA 中,此处传递的数据源将用作传递给 PersistenceProvider 的 PersistenceUnitInfo 上的“nonJtaDataSource”,覆盖persistence.xml 中的数据源配置(如果有)。看来 EM 处于 RESOURCE_LOCAL 模式!!
    • @HDave 我稍后会更仔细地重新阅读此内容,但我认为这是使用来自erich.soomsam.net/2007/04/24/…JtaPersistenceUnitPostProcessor 的重点。
    • 我已经实现了该文档中概述的 JtaPersistenceUnitPostProcessor,并结合了 hibernate.transaction.factory_class 和 manager_lookup_class 它似乎正在工作。谁知道在容器外运行 JPA/JTA 是如此困难!!!
    【解决方案2】:

    我自己也遇到过类似的问题。我将 Spring 与 JPA 一起使用,并将我的数据库指定为 JNDI 名称。最终我决定使用 Mockito 来模拟 JNDI。这很容易。这是我的做法:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations={"classpath:spring-config.xml"})
    public class MyTestClass {
    
        private static final InitialContextFactoryBuilder contextFactoryBuilder = mock(InitialContextFactoryBuilder.class);
        private static final InitialContextFactory contextFactory = mock(InitialContextFactory.class);
        private static final Context context = mock(Context.class);
        private static final NameParser parser = mock(NameParser.class);
        private static final Name dbName = mock(Name.class);
        // This is the Datasource implementation from the H2 database
        private static final JdbcDataSource temporaryDbForTesting = new JdbcDataSource();
    
        @BeforeClass
        public static void setupMockJndi() throws NamingException {
            NamingManager.setInitialContextFactoryBuilder(contextFactoryBuilder);
            when(contextFactoryBuilder.createInitialContextFactory(any(Hashtable.class))).thenReturn(contextFactory);
            when(contextFactory.getInitialContext(any(Hashtable.class))).thenReturn(context);
            when(context.getNameParser(any(String.class))).thenReturn(parser);
            when(parser.parse("GatewayDbDataSource")).thenReturn(dbName);
            when(context.lookup(dbName)).thenReturn(temporaryDbForTesting);
    
            temporaryDbForTesting.setURL("jdbc:h2:~/test2");
            temporaryDbForTesting.setUser("sa");
            temporaryDbForTesting.setPassword("");
        }
    
        @Autowired
        private org.zzz.DomainObject toTest;
    
        @Test
        public void testPasswordChecking() {
            assertNotNull("There wasn't an object to test. Spring is broken!", toTest);
            // ... assertions and such ...
        }
    
    }
    

    【讨论】:

    • 在注意到 SimpleContextFactoryBuilder 不支持对名称的查询之后,我最终得到了非常相似的解决方案——这使得它无法用于我通过 persistence.xml 加载数据源的用例
    猜你喜欢
    • 2011-03-08
    • 2015-03-16
    • 1970-01-01
    • 1970-01-01
    • 2020-01-19
    • 2016-11-01
    • 1970-01-01
    • 2011-01-30
    • 2011-08-21
    相关资源
    最近更新 更多