I am learning Spring and am working on a unit test, with the beans being specified in an XML config file. I am wondering how I tell it to use a file on the file system.
The following code* will run:
import static org.junit.Assert.*;
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;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("beans.xml")
public class CDPlayerTest {
...
}
The beans.xml file is in the same package as the test class.
But when using
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("/Users/pabernathy/pworkspace/springtraining/beans.xml")
public class CDPlayerTest {
...
}
It gives me this error message:
org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [Users/pabernathy/pworkspace/springtraining/beans.xml]; nested exception is java.io.FileNotFoundException: class path resource [Users/pabernathy/pworkspace/springtraining/beans.xml] cannot be opened because it does not exist
I can assure you, the file does exist.
Does anyone know how to specify an arbitrary XML file for the Spring beans?
*based on the example in chapter 2 of Spring in Action
If you look at the error message closely, you'll see that spring stripped away the leading slash on the file path. By default, spring assumes the file exists in the class path somewhere. Try this:
#ContextConfiguration("file:/Users/pabernathy/pworkspace/springtraining/beans.xml")
file: overrides the default spring behavior and informs spring that it is an absolute path.
try annotating like this
#ContextConfiguration(locations={"file://beans.xml"}). if that wont work just specify the whole path as #ContextConfiguration(locations={"file://users/blah/blah/beans.xml"}) and you should be good.
Related
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class SpringBootEdurekaTrialApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootEdurekaTrialApplication.class, args);
}
}
[1]: https://i.stack.imgur.com/78XDP.png
I have shared the screenshot of project package in above image. I have created the class under same package but I don't know why I am getting error. please guide.
Check your directory structure once in the file system. It should contain these three folders com/example/demo and under demo the file should be present. Sometimes folder structure is created as a single folder com.example.demo instead of the com/example/demo(3 folders). This should be the root cause of the issue.
For me I got the same error. The first time around I put the "demo" folder inside another folder that I called "Spring Web". I deleted everything and unzipped "demo" directly to C: and after importing it into Eclipse the error did not appear again.
In my case, the directory structure is fine. It could be that the source path of the main application is pointing to a different directory than the default path such as "src/main/java". Since this file was automatically created by Spring Boot, there seemed to be no way to fix it.
The way I resolved this compiler error was to add a new class using a different name from scratch and then copy the original content into the new class before removing the old one. You can then rename the class afterward.
I have had this problem for a few days, checked similar questions on this forum and Googled in various ways but could not find an answer.
This is a Spring Boot starter project: I have a class Graphs which is annotated by #Component in a package under "src/main/java":
#Component
public class Graphs {
}
Then, I created test classes under "src/test/java". One of them (to test Graphs):
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.example.demo.Graphs;
#RunWith(SpringRunner.class)
#SpringBootTest
public class GraphsTest {
#Test
public void testRun () {
Graphs graph = new Graphs();
}
}
Then I ran testRun in Eclipse (right-click on "testRun"--> Run As --> Junit Test). The result I got was:
initializationError [Runner: Junit 4] (0.0001s)
The Failure Trace in Eclipse shows the following:
java.lang.Exception: No tests found matching [{ExactMatcher:fDisplayName=testRun], {ExactMatcher:fDisplayName=testRun(com.example.demoTest.GraphsTest)], {LeadingIdentifierMatcher:fClassName=com.example.demoTest.GraphsTest,fLeadingIdentifier=testRun]] from org.junit.internal.requests.ClassRequest#1f7030a6
at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:40)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createFilteredTest(JUnit4TestLoader.java:83)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:74)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:49)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:525)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
I made a few tweaks without any luck:
I bought my Eclipse Oxygen up-to-date, also tried in Eclipse 2018-12 edition, the same result.
If I remove #RunWith annotation and run testRun, it produced expected results.
I added a Public static void main and ran it as "Java Application", it produced expect results. I guess running it as a Java app bypassed #RunWith(SpringRunner.class).
Where did I do wrong?
I have one class:
package com.example.propertyorder;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
#SpringBootApplication
#PropertySource(value="file:C:\\TEMP\\property-order.properties", ignoreResourceNotFound = true)
public class PropertyOrderApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(PropertyOrderApplication.class, args);
Environment env = (Environment) run.getBean("environment");
System.out.println(env.getProperty("my.value"));
System.out.println(env.getProperty("my.value2"));
}
}
and I have one application.properties file:
my.value=application.properties
and I have my external properties file C:\\TEMP\\property-order.properties:
my.value=property-order.properties
my.value2=gotcha
but the result is always:
application.properties
gotcha
instead of:
property-order.properties
gotcha
So it looks like, that spring-boot's application.properties overrules all.
Is there a way to fix it.
The only solution that i found is to not use the application.properties, but a my-app.properties instead and place that one before my external file in the ProperySource-tree:
#PropertySource(value="classpath:my-app.properties")
#PropertySource(value="file:C:\\TEMP\\property-order.properties", ignoreResourceNotFound = true)
Is there a better way, so that I can stay with the application.properties ?
edit:
added missing value2 to the property file
The actual behavior is conform to the Spring Boot documentation :
Spring Boot uses a very particular PropertySource order that is
designed to allow sensible overriding of values. Properties are
considered in the following order:
....
14.Application properties outside of your packaged jar (application.properties and YAML variants).
15.Application properties packaged inside your jar (application.properties and YAML variants).
16.#PropertySource annotations on your #Configuration classes.
The application.properties (inside or outside the jar) have a higher priority (14 and 15 respectively) than any #PropertySource annotations added in #Configuration class (16).
Is there a better way, so that I can stay with the
application.properties ?
Of course you can use any of the 13 higher priority ways :
1.Devtools global settings properties on your home directory
(~/.spring-boot-devtools.properties when devtools is active).
2.#TestPropertySource annotations on your tests.
3.#SpringBootTest#properties annotation attribute on your tests. Command
line arguments.
4.Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an
environment variable or system property).
5.ServletConfig init parameters.
6.ServletContext init parameters.
7.JNDI attributes from java:comp/env.
8.Java System properties (System.getProperties()).
9.OS environment variables.
10.A RandomValuePropertySource that has properties only in random.*.
11.Profile-specific application properties outside of your packaged jar
(application-{profile}.properties and YAML variants).
12.Profile-specific application properties packaged inside your jar
(application-{profile}.properties and YAML variants).
13.Application properties outside of your packaged jar
(application.properties and YAML variants).
For example renaming property-order.properties to application-order.properties to make it a Spring Boot profile properties and run your application with order as active profile would give it a higher priority and so it should be enough :
#SpringBootApplication
public class PropertyOrderApplication {...}
If you want to override the property defined int the application.properties, you can use the below approach.
#PropertySources({
#PropertySource(value = "classpath:application.properties"),
#PropertySource(value = "file:/user/home/external.properties", ignoreResourceNotFound = true)
})
public class Application {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
}
}
I am getting the following error:
Caused by: java.io.FileNotFoundException: class path resource [request-
ws/src/main/resources/application.yml] cannot be opened because it does
not exist
Class with the issue:
#Configuration
#PropertySource("classpath:request-ws/src/main/resources/application.yml")
public class RequestDataSource {
Now I am trying to access the yml file in from a different module. The module name is request-ws. The goal to to create two data sources. Any advice would be greatly appreciated.
The classpath for application.yml should be under: src/main/resources
according to: classpath:request-ws/src/main/resources/application.yml
you obviously don't have that yml file under:
src/main/resources/request-ws/src/main/resources/application.yml
Try to create your custom folder under: src/main/resources
Since my project is broken down into modules when the war file is made my application.yml file ends up in WEB-INF Put this on on your class:
#Configuration
#EnableConfigurationProperties
#PropertySource("classpath:WEB-INF/classes/application.yml")
public class DataSourceConfig {
Using Helios, spring 3.0.5 (TestContext Framework) and JUnit 4.7. I am getting an initialization error indicating that it cannot find the ContextConfiguration. I ran ProcMon in the background and determined it is not apparently looking at all. I have tried the logical locations for the xml file to no avail. I am unclear of what I am doing incorrectly. Here is the code:
package com.hwcs.veri.agg.dao;
import static org.junit.Assert.assertEquals;
import java.util.List;
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.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;
import com.hwcs.veri.jpa.License;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "/JpaIntegrationTests-context.xml" })
#TransactionConfiguration( transactionManager = "transactionManager",
defaultRollback = true )
#Transactional
public class JpaIntegrationTests
extends AbstractTransactionalJUnit4SpringContextTests
{
#Autowired
protected LicenseDao licenseDao;
#Test
public void getLicenses()
{
List<License> licenses = this.licenseDao.getLicenses();
assertEquals( "Expecting 1 license from the query",
super.countRowsInTable( "product_schema.license" ),
licenses.size() );
}
}
Is there some particular step that needs to be done to run this as a JUnit test inside Eclipse?
First and foremost, set the log level for org.springframework.test.context to DEBUG. That should tell you everything that the Spring TestContext Framework (TCF) is doing.
Note that with your above configuration, the TCF will attempt to load your application context from classpath:/JpaIntegrationTests-context.xml (i.e., in the root of your classpath). So make sure that the JpaIntegrationTests-context.xml file in fact exists in the root of the classpath (e.g., /src/test/resources/JpaIntegrationTests-context.xml for a Maven project layout). For the Maven project layout, you need to make sure that /src/test/resources is configured as a source folder in your IDE.
If this doesn't help you solve your problem, post the DEBUG output from the log.
Regards,
Sam (author of the Spring TestContext Framework)
Quoting Java Project: Failed to load ApplicationContext
"From the Sping-Documentation: A plain path, for example "context.xml", will be treated as a classpath resource from the same package in which the test class is defined. A path starting with a slash is treated as a fully qualified classpath location, for example "/org/example/config.xml".