Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't use JNDI test context (SimpleNamingContext) with Hibernate 5.2 #22732

Closed
edpichler opened this issue Apr 3, 2019 · 6 comments
Closed
Labels
in: test Issues in the test module status: declined A suggestion or change that we don't feel we should currently apply status: feedback-provided Feedback has been provided

Comments

@edpichler
Copy link

edpichler commented Apr 3, 2019

Affects: spring-test 5.1.6.RELEASE

I am trying to create datasources to bind them in JNDI to run my JUnit tests.

SimpleNamingContextBuilder jndiCtx = new SimpleNamingContextBuilder();
jndiCtx.bind(JNDI_TRANSACTION_MANAGER, createTransactionManager());
jndiCtx.bind(JNDI_DATASOURCE_NAME, createDataSource());
jndiCtx.activate();

When I do a lookup() it works, as the code bellow:

DataSource ds = new InitialContext().doLookup(JNDI_DATASOURCE_NAME);
System.out.println(ds); //it works

But when running Hibernate, it throws an exception:

Stack trace
16:31:47.619 [main] INFO org.springframework.mock.jndi.SimpleNamingContextBuilder - Static JNDI binding: [java:/TransactionManager] = [Transaction: unknown]
16:31:47.696 [main] INFO org.springframework.mock.jndi.SimpleNamingContextBuilder - Static JNDI binding: [my-datasource/datasource] = [org.apache.commons.dbcp2.BasicDataSource@ef9296d]
16:31:47.696 [main] INFO org.springframework.mock.jndi.SimpleNamingContextBuilder - Activating simple JNDI environment
16:31:47.701 [main] DEBUG org.springframework.mock.jndi.SimpleNamingContext - Static JNDI lookup: [my-datasource/datasource]
org.apache.commons.dbcp2.BasicDataSource@ef9296d
16:31:48.695 [main] INFO org.hibernate.validator.util.Version - Hibernate Validator 4.1.0.Final
16:31:48.699 [main] DEBUG org.hibernate.validator.engine.resolver.DefaultTraversableResolver - Found javax.persistence.PersistenceUtil on classpath.
16:31:48.699 [main] INFO org.hibernate.validator.engine.resolver.DefaultTraversableResolver - Instantiated an instance of org.hibernate.validator.engine.resolver.JPATraversableResolver.
16:31:48.701 [main] DEBUG org.hibernate.validator.xml.ValidationXmlParser - No META-INF/validation.xml found. Using annotation based configuration only

javax.persistence.PersistenceException: [PersistenceUnit: pu-coparticipacao] Unable to build Hibernate SessionFactory
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:967)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:892)
	at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:58)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
	at br.com.qualirede.coparticipacao.base.AbstractDaoCDITest.<init>(AbstractDaoCDITest.java:61)
	at br.com.qualirede.coparticipacao.cdi.LiquibaseProducerCDITest.<init>(LiquibaseProducerCDITest.java:15)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.junit.platform.commons.util.ReflectionUtils.newInstance(ReflectionUtils.java:352)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:60)
	at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.instantiateTestClass(ClassTestDescriptor.java:208)
	at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.instantiateAndPostProcessTestInstance(ClassTestDescriptor.java:195)
	at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$testInstanceProvider$0(ClassTestDescriptor.java:185)
	at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$testInstanceProvider$1(ClassTestDescriptor.java:189)
	at java.util.Optional.orElseGet(Optional.java:267)
	at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$testInstanceProvider$2(ClassTestDescriptor.java:188)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:81)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:58)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.prepare(HierarchicalTestExecutor.java:89)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:74)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:120)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
	at java.util.Iterator.forEachRemaining(Iterator.java:116)
	at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:120)
	at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:120)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
	at java.util.Iterator.forEachRemaining(Iterator.java:116)
	at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:120)
	at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:55)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.hibernate.engine.jndi.JndiException: Error parsing JNDI name [my-datasource/datasource]
	at org.hibernate.engine.jndi.internal.JndiServiceImpl.parseName(JndiServiceImpl.java:124)
	at org.hibernate.engine.jndi.internal.JndiServiceImpl.locate(JndiServiceImpl.java:95)
	at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.configure(DatasourceConnectionProviderImpl.java:98)
	at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94)
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:240)
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:210)
	at org.hibernate.service.internal.SessionFactoryServiceRegistryImpl.getService(SessionFactoryServiceRegistryImpl.java:77)
	at org.hibernate.internal.SessionFactoryImpl$1.obtainConnection(SessionFactoryImpl.java:419)
	at org.hibernate.hql.spi.id.IdTableHelper.executeIdTableCreationStatements(IdTableHelper.java:67)
	at org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy.finishPreparation(GlobalTemporaryTableBulkIdStrategy.java:125)
	at org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy.finishPreparation(GlobalTemporaryTableBulkIdStrategy.java:42)
	at org.hibernate.hql.spi.id.AbstractMultiTableBulkIdStrategyImpl.prepare(AbstractMultiTableBulkIdStrategyImpl.java:88)
	at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:302)
	at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:445)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:889)
	... 60 more
Caused by: javax.naming.OperationNotSupportedException: SimpleNamingContext does not support [javax.naming.Name]
	at org.springframework.mock.jndi.SimpleNamingContext.getNameParser(SimpleNamingContext.java:291)
	at javax.naming.InitialContext.getNameParser(InitialContext.java:505)
	at org.hibernate.engine.jndi.internal.JndiServiceImpl.parseName(JndiServiceImpl.java:118)
	... 74 more

This happens because the mock is incomplete. SimpleNamingContext class has unimplemented methods, so we can't use it with Hibernate 5.2.

public class SimpleNamingContext implements Context {

    // ...
    public NameParser getNameParser(Name name) throws NamingException {
        throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
    }

    public NameParser getNameParser(String name) throws NamingException {
        throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
    }

    public Name composeName(Name name, Name prefix) throws NamingException {
        throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
    }
    // ...
}
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Apr 3, 2019
@edpichler edpichler changed the title Can't use JNDI test context (SimpleNamingContext) with Hibernate class Can't use JNDI test context (SimpleNamingContext) with Hibernate 5.2 Apr 3, 2019
@sbrannen sbrannen added the in: test Issues in the test module label Apr 10, 2019
@sbrannen
Copy link
Member

This is to be expected, since the Javadoc for SimpleNamingContext states that it:

Only supports binding plain Objects to String names.

Thus, any of the methods related to javax.naming.Name are not supported in the implementation.

Does Simple-JNDI work for you?

@sbrannen sbrannen added status: waiting-for-feedback We need additional information before we can continue and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Apr 10, 2019
@edpichler
Copy link
Author

edpichler commented Apr 10, 2019

This is to be expected, since the Javadoc for SimpleNamingContext states that it:

Only supports binding plain Objects to String names.

Thus, any of the methods related to javax.naming.Name are not supported in the implementation.

Does Simple-JNDI work for you?

Yes I used Simple-JNDI now. But don't you think this feature would be useful and suitable in Spring? It could be implemented based on the Simple-JNDI NameParser.

@edpichler edpichler reopened this Apr 10, 2019
@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Apr 10, 2019
@jhoeller
Copy link
Contributor

Frankly, I'd rather deprecate SimpleNamingContextBuilder at this point. It's an old helper for the 2004 days where JNDI bindings were much more common than today. Our Hibernate support provides DI-style DataSource configuration, so in a typical Spring application, you'd rather externalize the DataSource definition into its own bean (that you can then either fetch from JNDI or locally define in a test setup).

And for any JNDI needs, there are projects such as Simple-JNDI indeed. Nothing wrong with using those.

@edpichler
Copy link
Author

If the project maintainer don't want, who am I to disagree. Thank you.

@sbrannen sbrannen added the status: declined A suggestion or change that we don't feel we should currently apply label Apr 10, 2019
@sbrannen
Copy link
Member

Please note that the mock JNDI support will be officially deprecated in Spring Framework 5.2 (see #22779).

@edpichler
Copy link
Author

Got it. I am using JNDI to create unit tests for legacy J2EE apps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: test Issues in the test module status: declined A suggestion or change that we don't feel we should currently apply status: feedback-provided Feedback has been provided
Projects
None yet
Development

No branches or pull requests

4 participants