Spring Maven unitTest applicationContext loading wrong file - java

.I have a project that has a spring-config.xml file in src/main/webapp/WEB-INF and an applicationContext.xml file in src/test/resources. I also have an abstract test base class for my unit tests in src/test/java looks something like:
#ContextConfiguration(locations = {"classpath:/applicationContext.xml"})
public abstract class AbstractTestBase extends AbstractTransactionalJUnit4SpringContextTests {
//Common code and fields
}
All my unit tests extends this AbstractTestBase which points to the context within the src/test/resources or should. The problem arises when running my unit tests it is pulling in the spring-config.xml file.
There are other projects my team is working on that have the same file structure, same app context setup, and run as intended, but even when I have each file in the project side by side I don't see where their file runs and this one doesn't.
I am new to spring so I don't know what it is I should be looking for.
Are there any situations where Spring or Maven would not take the app context I'm handing it given all files exist? Is there anything I might be missing?
EDIT: corrected to reflect that one file is a spring-config file.

"classpath:/applicationContext.xml" should look under src/test/resources.
But it should be noticed that using that syntax will load the first one it finds and then stop as mentioned by '#chrylis'.
I once had similar problem.
You must have been using an IDE. There must have been applicationContext.xml file in your target/test-classes/ (in Eclipse IDE) in your project directory that is a copy of your xml file under src/main/webapp/WEB-INF or xml file like it.

Related

Using Spring #PropertySource in a Maven submodule

In a Spring-boot application, I was having a single module and I was able to inject a configuration file, e.g. "my.properties", that was located in src/main/resources as follows:
#Configuration
#PropertySource("/my.properties")
public class MyConf{
}
Everything was ok, but then I created submodules and now I moved that configuration file in a submodule. When I start the main application I gedt the following exception:
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.myapp.MainApplication]; nested exception is java.io.FileNotFoundException: Could not open ServletContext resource [/home/jeanvaljean/workspace/mainmodule/secondarymodule/my.properties]
As I see, I can solve the issue by writing
#PropertySource("/src/main/resources/my.properties")
Doing this, the path is correct and the file can be loaded.
Anyway, that is an horrible solution, and I'm pretty sure that there is a more elegant and flexible alternative. Any solution?
Spring has a few different implementations of how to find a resource. By using the prefix classpath: you are telling Spring to search for the resource in all the classpath, rather than in the classes that are bundled with your application.
Depending on the ApplicationContenxt, Spring will use a different default Resource class. It looks like in your case, Spring was instantiating a FileSystemResource, which only finds files available on the filesystem with either relative or absolute paths (but not inside jars!). My rule of thumb is to never prefix something if it's in the same module/component/jar, and always prefix it with classpath: if I know it's in a different module/component/jar (some people get mad at this :).
You can read a more in the Spring Documentation - Resources

Loading the same properties(yml) files in testing enviornment?

I am trying to figure out whether I can load the same .yml property files in testing environment as I load in real.
For example I have a test:
\src\test\java\security\TokenTest.java
Annotated with:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
#ActiveProfiles("dev")
Then I have:
\src\main\resources\application.yml
When I run the application, the environment picks up property-source from the yml location.
Whenever I run my test, the environment does not see this file - i.e. property-source is not created/populated.
The obvious solution is to put duplicate file to the test location:
\src\test\resources\application.yml
And it will load, but that is bad - in terms that it raises unnecessary confusion when perceiving the difference between test and main resources.
This previous problem gets enhanced if you have configuration file per environment.
Is there a way to load resources from src/main/resources for tests?
This is probably some basic classpath scanning concept which I don't know.
My case is that I already faced the nightmare when you have 5 yml properties files per enviornment in src/main/resources and then you have 5 corresponding yml properties files in src/test/resources and someone from your team WILL 100 % at some point introduce discrepancy between them making everyone else bleed in the long term.
So by any means tests must refer to the same configuration files not to be the lost within its own void context.
Solution: Try to "rebuild" the project.
Is there a way to load resources from src/main/resources for tests?
It works for me. Maybe your IDE is not copying changes to the output directory on save or something (I have heard IntelliJ users have to switch that feature on)?
I had the same problem as you, but I figured out that it was a classpath problem in my run configuration in intellij, when setting that up like it should have been it worked as a charm loading application.yml from the main/resources.

how to load application-context.xml using #ContextConfiguration annotation

My project structure is as below:
src/main/java -> contains java classes
src/main/resources/spring/context/application-context.xml
src/test/java -> contains J-unit test
I would like to use #ContextConfiguration annotation to load my application-context.xml
How can I load this file and how can I make sure that all beans are loaded?
I tried it using classpath and file. But nothing works for me.
I am confused when to use classpath and file. Some one please help me with this.
Thanks in advance.
#ContextConfiguration("classpath:/spring/context/application-context.xml") should work.
In conventional Maven project layout, src/main/resources contains classpath resources, therefore you should use classpath: or no prefix at all, because classpath: should be a default one in this case.
If it still doesn't work, perhaps something is wrong with your project configuration and files from src/main/resources doesn't appear in the classpath.
If context loads successfully, all beans in it should be loaded as well, otherwise context will fail to load.
Try with:
ApplicationContext APPLICATION_CONTEXT = new ClassPathXmlApplicationContext("/spring/context/application-context.xml");
If it does not work, try putting application-context.xml directly in src/main/resources and then load it with
ApplicationContext APPLICATION_CONTEXT = new ClassPathXmlApplicationContext("application-context.xml");

FileNotFoundException in test case run with maven using Spring resource loader

Our program is sending mails. For sending mails it includes an attachment.
The project is set up with maven. The JUnit test case loads the spring configuration first. Spring is loading the File with its DefaultResourceLoader. When running this directly within the workspace its running fine, however as a maven test it fails.
Spring Configuration for resource loader:
<property name="defaultResourceLoader">
<bean class="org.springframework.core.io.DefaultResourceLoader" />
</property>
ImplementingClass:
#Service
public class SomeClassA {
#Autowired
private DefaultResourceLoader defaultResourceLoader;
#Value("${mailLogoPath}")
private String mailLogo;
public void someMethod(){
String filePath = defaultResourceLoader.getResource(mailLogo).getFile().getAbsolutePath();
}
}
The exception points to the actual problem and difference:
java.io.FileNotFoundException: class path resource [templates/efmaillogo.jpg] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/C:/IBM/workspace/efMy10/ef-mvxsrv-reactor/ef-mvxsrv-service-resources/target/ef-mvxsrv-service-resources-1.5.23-SNAPSHOT.jar!/templates/efmaillogo.jpg
at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:204)
at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:52)
at SomeClassA.someMethod(SomeClassA.java:9)
Spring tries to look the file up within the jar. When running it as a junit test within eclipse, everything is working, because spring finds the file directly within the workspace. However when running the same unit test with maven it fails, because it doesn't find the file, because its in a jar in a different module. The file in the other module is needed by different modules, so I don't want to move it. On the application server where everything is deployed its working as well, because the .ear file is expanded.
I'm wondering if there is a different way to access the file with Spring, so that I don't have to skip this test case with maven.
Update
Tried doing a lookup for the file with:
String filePath = defaultResourceLoader.getResource(mailLogo).getURL.getFile();
However it now fails when actually sending the mail with Transport.send(msg).
java.io.FileNotFoundException: file:\C:\Users\uhe.m2\repository\com\clavisit\ef\mvxsrv\ef-mvxsrv-service-resources\1.5.23-SNAPSHOT\ef-mvxsrv-service-resources-1.5.23-SNAPSHOT.jar!\templates\efmaillogo.jpg (The filename, directory name, or volume label syntax is incorrect.)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1141)
at javax.mail.Transport.send0(Transport.java:195)
at javax.mail.Transport.send(Transport.java:124)
at com.clavisit.ef.ep.service.integration.handler.mail.SendMail.sendMessage(SendMail.java:153)
String filePath = defaultResourceLoader.getResource(mailLogo).getURL().getFile();
The above code change must work as per the discussion in this thread http://www.coderanch.com/t/474047/Spring/Spring-cannot-find-file-classpath

Load test resources within other module?

I'm using a abstract class in another module for reading and input for my testdata with:
package src/main/java/path/to/my/base/testclass;
InputStream stream = getClass().getResourceAsStream(filename);
filename is eg "test.txt", located in src/main/resources/path/to/my/base/testclass
As long as I put this abstract class into the same module as my testclasses are in, everything works fine.
Then i extract the acstract class (as well as the resources) to other module, compile, add to pom etc.
Result: My test implementation runs fine, but: I'm getting IO exception as the file could not be found.
What am I missing here? Why does the abstract class work within the same module, but not within another?
Test resources are for this artifact's tests only, they don't get deployed.
There are two possible ways around this:
Dirty: Make your app deploy a test jar along with the main jar,
and add that as a dependency with scope TEST to the second artifact.
Clean: Create a separate test artifact for base test classes and
common test resources. Important: in this artifact, nothing goes in src/test and everything goes in src/main. Reference this test artifact from both other
artifacts with scope TEST.

Categories