Multi project build test dependencies

I have a multi-project build where project A depends on project B. In my root project’s build.gradle I am doing this:

project(':A') {
  dependencies {
    compile project(':B')
  }
}

This all seems to work fine when compiling (project A imports and uses classes that are in project B), but when I try to have gradle execute the test task on project A it seems that the compiled classes/jar file of project B aren’t on project A’s classpath because I get all kinds of exceptions.

I’ve even tried to put the dependency in project A’s build.gradle instead of the root project but that doesn’t seem to work either:

dependencies {
  compile project(':B')
}

Can anyone offer any help?

Is it working if you define this dependency in project A instead? You can run “gradle tasks --all” and see whether your ‘A:test’ task depends on ‘B:jar’ task. If that is the case then you could try “gradle test --debug” and examine the classpath used to run A’s tests - whether it contains B’s jar.

Yes I do see the A:test task does depend on the B:jar task

Verification tasks
------------------
test - Runs the unit tests. [classes, testClasses, :B:jar, :B:testClasses]

And I do see it on the classpath (notice the last entry):

15:29:42.409 [DEBUG] [org.gradle.process.internal.DefaultWorkerProcessFactory] Using application classpath [c:\Projects\A\target\classes\test, c:\Projects\A\target\resources\test, c:\Projects\A\target\classes\main, c:\Projects\A\target\resources\main, c:\Projects\A\lib\testRuntime\jcl-over-slf4j-1.7.1.jar, c:\Projects\A\lib\testRuntime\logback-classic-1.0.7.jar, c:\Projects\A\lib\testRuntime\logback-core-1.0.7.jar, c:\Projects\A\lib\testCompile\junit-4.10.jar, c:\Projects\A\lib\testCompile\mockito-all-1.9.0.jar, c:\Projects\A\lib\testCompile\org.springframework.oxm-3.1.1.RELEASE.jar, c:\Projects\A\lib\testCompile\org.springframework.test-3.1.1.RELEASE.jar, c:\Projects\A\lib\plugin\jaxb-impl.jar, c:\Projects\A\lib\plugin\jaxb-xjc.jar, c:\Projects\A\lib\compile\aopalliance.jar, c:\Projects\A\lib\compile\commons-httpclient-3.1.jar, c:\Projects\A\lib\compile\commons-io-1.3.2.jar, c:\Projects\A\lib\compile\jaxb-api.jar, c:\Projects\A\lib\compile\org.springframework.aop-3.1.1.RELEASE.jar, c:\Projects\A\lib\compile\org.springframework.asm-3.1.1.RELEASE.jar, c:\Projects\A\lib\compile\org.springframework.beans-3.1.1.RELEASE.jar, c:\Projects\A\lib\compile\org.springframework.context-3.1.1.RELEASE.jar, c:\Projects\A\lib\compile\org.springframework.core-3.1.1.RELEASE.jar, c:\Projects\A\lib\compile\org.springframework.expression-3.1.1.RELEASE.jar, c:\Projects\A\lib\compile\org.springframework.web-3.1.1.RELEASE.jar, c:\Projects\A\lib\compile\slf4j-api-1.7.1.jar, c:\Projects\B\lib\plugin\jaxb-impl.jar, c:\Projects\B\lib\plugin\jaxb-xjc.jar, c:\Projects\B\lib\compile\commons-codec-1.4.jar, c:\Projects\B\lib\compile\commons-httpclient-3.1.jar, c:\Projects\B\lib\compile\commons-io-2.0.1.jar, c:\Projects\B\lib\compile\jaxb-api.jar, c:\Projects\B\lib\compile\logback-classic-1.0.7.jar, c:\Projects\B\lib\compile\logback-core-1.0.7.jar, c:\Projects\B\lib\compile\org.springframework.aop-3.1.1.RELEASE.jar, c:\Projects\B\lib\compile\org.springframework.asm-3.1.1.RELEASE.jar, c:\Projects\B\lib\compile\org.springframework.beans-3.1.1.RELEASE.jar, c:\Projects\B\lib\compile\org.springframework.context-3.1.1.RELEASE.jar, c:\Projects\B\lib\compile\org.springframework.context.support-3.1.1.RELEASE.jar, c:\Projects\B\lib\compile\org.springframework.core-3.1.1.RELEASE.jar, c:\Projects\B\lib\compile\org.springframework.expression-3.1.1.RELEASE.jar, c:\Projects\B\lib\compile\org.springframework.jms-3.1.1.RELEASE.jar, c:\Projects\B\lib\compile\org.springframework.oxm-3.1.1.RELEASE.jar, c:\Projects\B\lib\compile\org.springframework.web-3.1.1.RELEASE.jar, c:\Projects\B\lib\compile\slf4j-api-1.7.1.jar, c:\Projects\B\lib\compile\spring-ws-2.0.5.RELEASE-all.jar, c:\Projects\B\lib\compile\spring-ws-core-2.0.5.RELEASE.jar, c:\Projects\B\lib\compile\spring-ws-security-2.0.5.RELEASE.jar, c:\Projects\B\lib\compile\spring-ws-support-2.0.5.RELEASE.jar, c:\Projects\B\lib\provided\javaee.jar, c:\Projects\B\lib\provided\p13n_system.jar, c:\Projects\B\lib\provided\wls-api.jar, c:\Projects\A\lib\provided\coherence.jar, c:\Projects\A\lib\provided\oracle-ridc-client-10g.jar, c:\Projects\A\lib\runtime\commons-codec-1.4.jar, c:\Projects\B\target\libs\b.jar]

I’m not sure why my tests won’t run. I am using spring-test and I’m getting errors about not being able to initialize the context. All I have tried to do was move a single class from project A to project B and then introduce the inter-project dependency - I also changed all of the imports to this class in project A to point to project B. If I revert my changes then everything is fine.

Well, then this is probably something specific to Spring’s test framework. I’m not familiar with it but if you provide more information maybe somebody will be able to help you.

It really comes down to that for whatever reason it can’t find the spring config xml file on the classpath, which I’m not sure why it can’t - its there in c:\Projects\A\target\resources\test

That path (‘c:\Projects\A\target\resources\test’) looks a bit strange. What is the ‘target’ dir?

It is buildDir. Our plugins change the gradle default. This makes it more maven-like.

And you’ve verified that this directory is indeed on the classpath?

Yes - in my above post I captured the output of running the build with debug turned on. You can see that project B’s jar file (c:\Projects\B\target\libs\b.jar) is there on the application classpath, along with all of project B’s dependencies. I do also see in the console output that project B’s tasks were executed before project A’s and I verified that project B’s jar file is there & exists in c:\Projects\B\target\libs\b.jar.

I’m not sure if this helps but in my root project’s build.gradle I do have this line:

evaluationDependsOnChildren()

So what exception do you get during Spring initialization? Could you share the changes you made (which class did you move from project A to project B) to get to this error?

I moved a single java source file from project A to project B and updated all of my package imports in project A to point to the new package structure which project B has. Everything compiles fine. Here is what happens when I run my JUnit tests (which we use spring-test for our dependency injection). One thing I do notice is that all of the dependencies of project B are added to the classpath as well - both project A & B do share some of the same dependencies (most of the spring dependencies). Not sure if this has anything to do with it or not. Here is the stack trace I get for each and every test execution that I run:

[11/26/2012 08:38:43 | ERROR | Test worker | TestContextManager.java:324]: Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@4c3212a8] to prepare test instance [org.tiaa.atom.content.fatwire.FatwireCoherenceSnippetCacheTester@6b66faac]

java.lang.IllegalStateException: Failed to load ApplicationContext

at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:157) ~[org.springframework.test-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109) ~[org.springframework.test-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75) ~[org.springframework.test-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321) ~[org.springframework.test-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211) [org.springframework.test-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288) [org.springframework.test-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) [junit-4.10.jar:na]

at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:290) [org.springframework.test-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) [org.springframework.test-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) [junit-4.10.jar:na]

at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) [junit-4.10.jar:na]

at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) [junit-4.10.jar:na]

at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) [junit-4.10.jar:na]

at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) [junit-4.10.jar:na]

at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) [junit-4.10.jar:na]

at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) [junit-4.10.jar:na]

at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [org.springframework.test-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30) [junit-4.10.jar:na]

at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) [org.springframework.test-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.junit.runners.ParentRunner.run(ParentRunner.java:300) [junit-4.10.jar:na]

at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) [org.springframework.test-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:55) [gradle-plugins-1.2.jar:1.2]

at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:42) [gradle-plugins-1.2.jar:1.2]

at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:75) [gradle-plugins-1.2.jar:1.2]

at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:49) [gradle-plugins-1.2.jar:1.2]

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.6.0_35]

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[na:1.6.0_35]

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.6.0_35]

at java.lang.reflect.Method.invoke(Method.java:597) ~[na:1.6.0_35]

at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) [gradle-messaging-1.2.jar:1.2]

at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) [gradle-messaging-1.2.jar:1.2]

at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32) [gradle-messaging-1.2.jar:1.2]

at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) [gradle-messaging-1.2.jar:1.2]

at $Proxy2.processTestClass(Unknown Source) [na:na]

at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:103) [gradle-plugins-1.2.jar:1.2]

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.6.0_35]

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[na:1.6.0_35]

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.6.0_35]

at java.lang.reflect.Method.invoke(Method.java:597) ~[na:1.6.0_35]

at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) [gradle-messaging-1.2.jar:1.2]

at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) [gradle-messaging-1.2.jar:1.2]

at org.gradle.messaging.remote.internal.TypeCastDispatch.dispatch(TypeCastDispatch.java:30) [gradle-messaging-1.2.jar:1.2]

at org.gradle.messaging.remote.internal.WorkerProtocol.handleIncoming(WorkerProtocol.java:53) [gradle-messaging-1.2.jar:1.2]

at org.gradle.messaging.remote.internal.WorkerProtocol.handleIncoming(WorkerProtocol.java:31) [gradle-messaging-1.2.jar:1.2]

at org.gradle.messaging.remote.internal.ProtocolStack$ProtocolStage.handleIncoming(ProtocolStack.java:167) [gradle-messaging-1.2.jar:1.2]

at org.gradle.messaging.remote.internal.ProtocolStack$BottomStage.handleIncoming(ProtocolStack.java:277) [gradle-messaging-1.2.jar:1.2]

at org.gradle.messaging.remote.internal.ProtocolStack$BottomConnection$1.run(ProtocolStack.java:299) [gradle-messaging-1.2.jar:1.2]

at org.gradle.messaging.remote.internal.ProtocolStack$ExecuteRunnable.dispatch(ProtocolStack.java:120) [gradle-messaging-1.2.jar:1.2]

at org.gradle.messaging.remote.internal.ProtocolStack$ExecuteRunnable.dispatch(ProtocolStack.java:116) [gradle-messaging-1.2.jar:1.2]

at org.gradle.messaging.dispatch.AsyncDispatch.dispatchMessages(AsyncDispatch.java:132) [gradle-messaging-1.2.jar:1.2]

at org.gradle.messaging.dispatch.AsyncDispatch.access$000(AsyncDispatch.java:33) [gradle-messaging-1.2.jar:1.2]

at org.gradle.messaging.dispatch.AsyncDispatch$1.run(AsyncDispatch.java:72) [gradle-messaging-1.2.jar:1.2]

at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:66) [gradle-base-services-1.2.jar:1.2]

at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [na:1.6.0_35]

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [na:1.6.0_35]

at java.lang.Thread.run(Thread.java:662) [na:1.6.0_35]

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘mbeanServer’: Invocation of init method failed; 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

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1455) ~[org.springframework.beans-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519) ~[org.springframework.beans-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) ~[org.springframework.beans-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294) ~[org.springframework.beans-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225) ~[org.springframework.beans-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291) ~[org.springframework.beans-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) ~[org.springframework.beans-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:567) ~[org.springframework.beans-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913) ~[org.springframework.context-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464) ~[org.springframework.context-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:103) ~[org.springframework.test-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1) ~[org.springframework.test-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.test.context.support.DelegatingSmartContextLoader.loadContext(DelegatingSmartContextLoader.java:228) ~[org.springframework.test-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124) ~[org.springframework.test-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148) ~[org.springframework.test-3.1.1.RELEASE.jar:3.1.1.RELEASE]

… 55 common frames omitted

Caused by: 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

at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:645) ~[na:1.6.0_35]

at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288) ~[na:1.6.0_35]

at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:325) ~[na:1.6.0_35]

at javax.naming.InitialContext.lookup(InitialContext.java:392) ~[na:1.6.0_35]

at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:154) ~[org.springframework.context-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:87) ~[org.springframework.context-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:152) ~[org.springframework.context-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:178) ~[org.springframework.context-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:95) ~[org.springframework.context-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.jndi.JndiObjectLocator.lookup(JndiObjectLocator.java:105) ~[org.springframework.context-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.jndi.JndiObjectFactoryBean.lookupWithFallback(JndiObjectFactoryBean.java:201) ~[org.springframework.context-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.jndi.JndiObjectFactoryBean.afterPropertiesSet(JndiObjectFactoryBean.java:187) ~[org.springframework.context-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514) ~[org.springframework.beans-3.1.1.RELEASE.jar:3.1.1.RELEASE]

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452) ~[org.springframework.beans-3.1.1.RELEASE.jar:3.1.1.RELEASE]

… 69 common frames omitted

org.tiaa.atom.content.fatwire.FatwireCoherenceSnippetCacheTester > testSettingCacheRefreshIntervalTwice FAILED

java.lang.IllegalStateException: Failed to load ApplicationContext

Caused by:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘mbeanServer’: Invocation of init method failed; 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

Caused by:

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

This is too Spring specific for me to answer, probably you could check with Spring forum. But still answering to these questions might be a good start: - does the ‘FatwireCoherenceSnippetCacheTester’ test run fine without your refactoring changes (I assume this test is part of Project A) - What is this ‘mbeanServer’ bean - does it require any special configuration and how is it normally configured? - Are you import any other Spring context xml files that could fail to resolve (not sure how Spring behaves in such case)? - How do you configure JNDI - do you confgure a custom initial context factory - if so, is it possible that the configuration does not take place? - Does the order of JUnit test exection matter (it should not but who knows) - did the order change after you did the refactoring?

On Gradle’s side you might try:

  • to use Spring 3.1.2 instead of 3.1.1 - to eliminate duplicate dependencies by excluding them

Before I moved the single source file from project A to project B everything ran fine - all 125+ JUnit tests run successfully. All I have done was move a single java source file from one project to another as part of the same multi-project build and re-factor existing classes in project A to use the newly-refactored class. No other changes were introduced.

-mBeanServer is for JMX - its a spring bean for exposing your own beans through JMX. This works fine before refactoring -No other changes were made other than moving a single source file from one project to the other and introducing the cross-project dependency. -We don’t configure JNDI at all - spring takes care of it. -JUnit test execution order does not matter - all of the tests are independent of each other - in fact I use spring’s @DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD) annotation so that the spring context is destroyed & re-created after each test executes - that way each test method gets its own “clean” context to work with, since most of the tests involve dirty-ing the context in some way.

So what does this ‘single source file’ contain? Is this a single test that fails or all tests fail with this error? Could you share your Spring context xml file, it could contain some pointers why JNDI might fail to initialize.

This single source file is a class that just contains a bunch of static helper methods…validating that collections aren’t null and contain at least 1 element, etc.

I think the spring piece of this is really irrelevant, since before moving the class across projects everything is fine and once I introduce the cross-project dependency then everything goes to hell. It has to be some kind of classpath/classloading issue. Spring-test is used as a runner (using junit’s @RunWith annotation) - @RunWith(SpringJUnit4ClassRunner.class) in this case.

Well if it is only a static helper then why don’t you move it to a standalone project or at least to a standalone source set, rather than pulling the rest of B’s sources and a whole lot of dependencies:

c:\Projects\B\lib\compile\org.springframework.context.support-3.1.1.RELEASE.jar,

c:\Projects\B\lib\compile\org.springframework.jms-3.1.1.RELEASE.jar,

c:\Projects\B\lib\compile\org.springframework.oxm-3.1.1.RELEASE.jar,

c:\Projects\B\lib\compile\spring-ws-2.0.5.RELEASE-all.jar,

c:\Projects\B\lib\compile\spring-ws-core-2.0.5.RELEASE.jar,

c:\Projects\B\lib\compile\spring-ws-security-2.0.5.RELEASE.jar,

c:\Projects\B\lib\compile\spring-ws-support-2.0.5.RELEASE.jar,

c:\Projects\B\lib\provided\javaee.jar,

c:\Projects\B\lib\provided\p13n_system.jar,

c:\Projects\B\lib\provided\wls-api.jar

What about this ‘javaee.jar’ - could it be that having it on the classpath somehow breaks Spring, what version of Java EE apis are contained in it?

You could start excluding these from your project B dependency (see this comment for an example) and see whether this has any effect.

Edit: Also ‘wls-api.jar’ - what does it contain, what happens if you remove it?

I want to move it to the other project because that other project is a “Core” project, which contains classes & libraries that are going to be re-used across lots of other projects. This “core” project has lots of other utility classes and whatnot as well. This core project will also be put into our artifact repository that other projects (outside of this one) can use as well. Otherwise I would have just left this one alone :slight_smile:

The class that i moved - the only dependencies that class has is

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

The javaee.jar file is Java EE 5. The “Core” project needs it (notice it is scoped as “provided” - a scope Maven has that we’ve introduced). This core project also has utility classes that deal with servlets, so the javaee.jar needs to be there at compile time - but it should be packaged/deployed with the project.

Hmm, from the above stacktrace I was under the impression that you are running with Java 1.6.0_35, why do you put Java EE 5 Apis on the classpath at all - you could remove this jar from the runtime classpath and see what happens (same for the wls-api.jar).

The contents of javaee.jar are not included in Java SE (HttpServletRequest, HttpSession, etc). If javaee.jar (and wls-api.jar) are not on the classpath then other classes in the “Core” project will not compile. They are required for compilation, as well as for running junit tests.

I understand that, but you mentioned that you use only a single utility class from the “Core” (B) project in your tests, so I assume that since the same code was part of the A project and it did not require the javaee and wsl-api jars, then as far as your tests use the same methods, they should not require them as well. In general ‘provided’ dependencies should not be required during unit testing - those are usually provided by a container while unit tests do not execute in a container. So could you try excluding them from testRuntime classpath and see what happens?