1

I am currently trying to set up a sample Spring project with both Gradle and IntelliJ IDEA (14.1.7). Spring configuration is done via a classpath XML file, which is located in the default folder at src/main/resources/.

The Gradle build and test is working just fine (from command line). However, I can't manage to properly set up run configurations for testing and running within IntelliJ: I'll always get error messages complaining the XML file can't be found.

Directory structure:

(Project root)
+- build
  +- classes
    +- main
      +- (.class files)
    +- test
      +- (.class files)
  +- resources
    +- main
      +- spring-config.xml (copied from /src/main/resources by Gradle)
  +- ...
+- src
  +- main
    +- java
      +- test
        +- sia
          +- HelloApp.java
          +- HelloService.java
    +- resources
      +- spring-config.xml
  +- test
    +- java
      +- test
        +- sia
          +- SpringAppTests.java
    +- resources
      +- (empty directory)
+- ...

HelloApp.java:

package test.sia;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class HelloApp {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        HelloService helloService = context.getBean(HelloService.class);
        System.out.println(helloService.sayHello());
    }
}

SpringAppTests.java:

package test.sia;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static junit.framework.Assert.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-config.xml")
public class SpringAppTests {
    @Autowired
    private HelloService helloService;

    @Test
    public void testSayHello() {
        assertEquals("Hello world!", helloService.sayHello());
    }
}

The run configurations within IntelliJ run the classes and testClasses Gradle tasks respectively before launch. Classpath is inherited from the IntelliJ module for the project. While the module configuration GUI doesn't offer something to directly set the classpath, you can only set the paths for compiler output - which have been properly set to /build/classes/main and /build/classes/test. All the sources+resources folders are properly marked within the project.

When trying to run tests:

java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.junit.runners.Suite.runChild(Suite.java:128)
    at org.junit.runners.Suite.runChild(Suite.java:27)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [spring-config.xml]; nested exception is java.io.FileNotFoundException: class path resource [spring-config.xml] cannot be opened because it does not exist
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:344)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:181)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:217)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:188)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:252)
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadBeanDefinitions(AbstractGenericContextLoader.java:257)
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:124)
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:108)
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:251)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
    ... 36 more
Caused by: java.io.FileNotFoundException: class path resource [spring-config.xml] cannot be opened because it does not exist
    at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:172)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:330)
    ... 48 more

When trying to run the application itself:

20.08.2016 20:54:11 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@6037fb1e: startup date [Sat Aug 20 20:54:11 CEST 2016]; root of context hierarchy
20.08.2016 20:54:11 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-config.xml]
Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [spring-config.xml]; nested exception is java.io.FileNotFoundException: class path resource [spring-config.xml] cannot be opened because it does not exist
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:344)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:181)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:217)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:188)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:252)
    at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:127)
    at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:93)
    at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:129)
    at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:612)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:513)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at de.julianrupp.sia.HelloApp.main(HelloApp.java:8)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.io.FileNotFoundException: class path resource [spring-config.xml] cannot be opened because it does not exist
    at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:172)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:330)
    ... 18 more

I've only found a single 2 years old question on a similar matter where it was suggested to change the file references to the XML config file within the .java files to include a wildcard. Apart from my stance that this is not a viable solution (I might work on projects where I can't change those paths), it also doesn't work for me. The error message then just changes, saying it can't find the bean.

Does anyone know how to set this up properly?

Julian
  • 757
  • 1
  • 6
  • 21
  • Grab yourself an up-to-date version of IntelliJ, choose File - Open... and select the build.gradle file, click Next a few times, and you should be done. – JB Nizet Aug 20 '16 at 21:37
  • @JBNizet 1) The version of IntelliJ is fixed. 14.1.7 is the latest from the v14 release as well. 2) Getting Gradle tasks to run in IntelliJ is not the problem I have. It's running the application and its tests. – Julian Aug 20 '16 at 21:41
  • perhaps try building it without intellij https://www.mkyong.com/gradle/gradle-create-java-project-structure-automatically/ – Robbo_UK Aug 20 '16 at 21:42
  • @Robbo_UK This is no help. Building without IntelliJ, with Gradle on the command line, works fine. I want to get things to run within IntelliJ as well. – Julian Aug 20 '16 at 21:43
  • Gradle 14 is obsolete. Many improvements have been made regarding gradle support in subsequent versions. Why stick with an old, obsolete version? Especially when the community version is free. – JB Nizet Aug 20 '16 at 21:45
  • @JBNizet because v15 dropped support for my operating system. And why should I use a crippled community version when I have a license for the paid version? – Julian Aug 20 '16 at 21:52
  • Because a recent version of a free product supporting all you need (jUnit, gradle) is better than an old paying version supporting things you don't need. But you could also pay for the up-to-date version, of course. What kind of OS are you running that wouldn't support IntelliJ? Note that v15 is obsolete, too. Current version is 2016.2. – JB Nizet Aug 20 '16 at 21:55
  • @JBNizet The last acceptable version of OS X before it went total downhill, 10.6. JB cut support for it with some later update of v15. Also the free version doesn't natively support Spring according to the feature comparison sheet, neither does it offer various other features I'm using which only the paid version has. Can we please get back to solving the problem at hand and stop trying to get me to update my OS and IDE? Obviously developers did successfully get this set up back when IJ 14 was the most recent version too, so please. – Julian Aug 20 '16 at 22:13

1 Answers1

0

It looks like I found the solution myself, at last.

For anyone else stuck with the same problem --

I had to explicitly add the Resources and Test Resources folder as "libraries with java classes" in the project settings, as described here (it's for IntelliJ v13, but it works the same in v14)

See attached screenshots for the configuration in project settings.

Project Settings configuration

Community
  • 1
  • 1
Julian
  • 757
  • 1
  • 6
  • 21