FileNotFoundException in test case run with maven using Spring resource loader - java

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

Related

Unable to load Ignite config spring bean definition from non default location in spring boot application

I am trying to externalize my ignite configuration in my spring boot application so the configuration can be changed without rebuilding the jar.
Previously the file resided in src/main/resrouces and was loaded via annotations.
#ImportResource("IgniteConfig.xml") and
#Autowired
private IgniteConfiguration cfg;
When I moved the IgniteConfig.xml to the config folder that resides next to the excutable jar the above stopped working and I have tried the following without success:
use --spring.config.location argument. I can tell this is picked up during run time as other configurations work but the above ImportResource annotation says the file IgniteConfig.xml cannot be found.
use a relative path to (e.g. ./config.IgniteConfig.xml) to Ignition.start. I cause this relative path to print the file contents of the xml file in my logs but when I pass it to Ignition.start it says the file cannot be found. I have tried using relative and absolute paths to do this.
Manually create an ApplicationContext and get the configuration by bean name.
ApplicationContext context = new ClassPathXmlApplicationContext("./config/IgniteConfig.xml");
This again complains that the file does not exist even though I can see by opening the file directly:
File igniteConfigFile = new File("./config/IgniteConfig.xml");
The comment by konqi in this post answered my question:
"In case you want to import a resource that is outside the classpath the syntax would be:
#ImportResource( { "file:path/spring-context1.xml", "file:path/spring-context2.xml" } )
"
In my case I just needed to do:
#ImportResource( { "file:./config/IgniteConfig.xml" } )

Spring boot test: #Sql annotation Unable to locate sql files placed in src/test/resources

I didn't want to load the entire Spring Boot configuration for unit-testing my DAO layer, and therefore created a nested configuration class to suppress default configurations. But when I try to specify SQL scripts for it to run before tests, its unable to find them.
Here's the code:
package com.test.customer.controller;
..
#RunWith(SpringRunner.class)
#JdbcTest
#Sql({"data.sql"})
public class InterviewInformationControllerTest {
#Configuration
static class TestConfiguration{
}
#Test
public void testCustomer() {
// code
}
}
I get the error: Cannot read SQL script from class path resource [com/test/customer/controller/data.sql]; nested exception is java.io.FileNotFoundException: class path resource [com/test/customer/controller/data.sql] cannot be opened because it does not exist
I've tried placing the file at both src/main/resources (not preferred) as well as at src/test/resources (which I prefer)
Note: I'm running the Unit test from inside Eclipse by doing Run as -> JUnit test.
Edit: Added the static keyword to the configuration class
your inner configuration class will not work unless you add a static keyword before its definition. However you should know that for the #Sql annotation
Path Resource Semantics
Each path will be interpreted as a Spring Resource. A plain path — for
example, "schema.sql" — will be treated as a classpath resource that
is relative to the package in which the test class is defined. A path
starting with a slash will be treated as an absolute classpath
resource, for example: "/org/example/schema.sql". A path which
references a URL (e.g., a path prefixed with classpath:, file:, http:,
etc.) will be loaded using the specified resource protocol.
So try to prefix the value inside #Sql with classpath: like this :
#Sql(scripts={"classpath:data.sql"})
Good luck!
Check your out directory of the module. While creating directory in resources, if you have named it directly with the namespace like com.gakshintala.bookmybook, it takes that name completely as the directory name, so the out also contains this directory under resources with name com.gakshintala.bookmybook. PFB right vs wrong. The top is right and bottom is wrong.
Spring always looks for nested directory resources->com->gakshintala->bookmybook.
So create that directory structure.

access via spring injected property which references a directory to access its files

I'm trying to access a property defined in a bean like this:
<bean id="reportdepositService" class="a.b.c.ServiceImpl">
<property name="reportDeposit" value="/WebContent/WEB-INF/dirName/" />
</bean>
ServiceImpl class looks like this:
public class ServiceImpl implements IService {
private Resource springResource;
public Resource getSpringResource() {
return springResource;
}
public void setSpringResource(Resource springResource) {
this.springResource = springResource;
}
private File getSpringResourceFile() throws IOException{
Resource r = getSpringResource();
URL url = FileLocator.resolve(r.getURL());
return FileUtils.toFile(url);
}
public void doSomething(){
.. some logic .
File f = getSpringResourceFile();
}
executing that code within eclipse on a ubuntu machine works fine, application build on a jenkins works fine as well on ubuntu. Running that application on a win7/64, the code throws the following exception:
OSGi resource[/WebContent/WEB-INF/springResource/|bnd.id=332|bnd.sym=a.b.server] cannot be resolved to URL because it does not exist
java.io.FileNotFoundException: OSGi resource[/WebContent/WEB-INF/springResource/|bnd.id=332|bnd.sym=a.b.server] cannot be resolved to URL because it does not exist
at org.springframework.osgi.io.OsgiBundleResource.getURL(OsgiBundleResource.java:228)
What is necessary to access the property on windows hosted system?
Any ideas?
Thanks in advance
I am not sure whether you are on the correct road with this:
The /WebContent/WEB-INF path suggests that you are writing a web application to be run in a web container. In that case you should never assume that your resource is a file. You should open the resource using Resource.getInputStream() in stead of using the URL/File. The reason is that the the application may well be run directly from the .war without a file system being available.
That may immediately answer the question: is the Windows 7 environment the same in relation to the run-enviroment? My impression is that it is not. If you bundled the project into a bundle jar while transporting it to the windows machine, I guess you should add a prefix to the path (but probably need to leave the WebContent off), like bundle:, classpath:, etc. See Spring OSGI reference. But you need to give a little more information to be sure.

Spring Maven unitTest applicationContext loading wrong file

.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.

Grails config of Spring beans in different files

Grails have cofig for spring bean called resources.groovy. And as i understand from docs it allows you to include another file, using loadBeans(%path%)
I'm tried with this:
println 'loading application config ...'
// Place your Spring DSL code here
beans = {
loadBeans("classpath:security") //i'm tried with "spring/security" and "spring/security.groovy" also
}
but when grails is running it log following error:
Caused by: org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Error evaluating bean definition script: class path resource [security] cannot be opened because it does not exist
Offending resource: class path resource [security]; nested exception is java.io.FileNotFoundException: class path resource [security] cannot be opened because it does not exist
at grails.spring.BeanBuilder.loadBeans(BeanBuilder.java:470)
at grails.spring.BeanBuilder.loadBeans(BeanBuilder.java:424)
at resources$_run_closure1.doCall(resources.groovy:13)
at resources$_run_closure1.doCall(resources.groovy)
... 45 more
Script security.groovy is exists at grails-app/conf/spring and compiled by grails maven plugin into target/classes/security.class.
Directory target/resources/spring is empty at this time
How i can configure Grails or grails-maven-plugin to copy this config files, not compile it into classes?
p.s. this problem also presents when i try to include config scripts using grails.config.locations = [ %path% ] inside conf/Config.groovy, my groovy scripts compiles into classes and because of it, grails config builder can't find them :(
Did you try:
println 'loading application config ...'
// Place your Spring DSL code here
beans = {
loadBeans("classpath:*security.groovy")
}
(this should load all Groovy files on the classpath ending with security.groovy and parse them into bean definitions).
Update: Found an interesting thread with this message as reference and my understanding is that one trick is to use ant in scripts/_Events.groovy to copy the .groovy file to the classesDirPath dir and then simply use:
beans = {
// load spring-beans for db-access via spring-jdbc-template
loadBeans('security.groovy')
// load some other spring-beans
...
}
This looks like a hack to get things working in both the war and when running run-app though. Not sure how things "should" be done (if this even makes sense).

Categories