Ignore to load XML file from SpringBootApplication - spring-boot

I have a Spring Boot application structure like this:
src/main/java
/main/Application.java
src/main/resource/
/application-context.xml
src/test/java
/main/TestApplication.java
src/test/resource/
/application-context-test.xml
When I start application by Run As Spring Boot Application or Run as Junit
Both application-context.xml and application-context-test.xml were loaded.
But I only want to load application-context.xml in running mode, and application-context-test.xml in testing mode.
The initialisers look like:
#ImportResource("classpath:application-context.xml")
public class Application{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
#ImportResource("classpath:application-context-test.xml")
public class TestApplication{
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}
but they do not work.
Both the XMLs are loaded. How can I resolve this?

Annotate TestApplication with :
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = TestApplication.class)

Related

Why is my Spring application run from my spring boot unit test

I have a basic spring data application and I have written a unit test. What appears to happen is that when I run the Spring test my application run method gets called as well. I would like to know why this is and how to stop it please.
I have tried using active profiles but that doesnt fix the problem
#SpringBootApplication
#EntityScan({ "com.demo" })
public class Application implements ApplicationRunner {
#Autowired
private IncrementalLoadRepository repo;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
public void run(ApplicationArguments args) throws Exception {
IncrementalLoad incrementalLoad = new IncrementalLoad("fred", Instant.now(), Instant.now(), Instant.now());
repo.save(incrementalLoad);
}
and the unit test........
#RunWith(SpringRunner.class)
#SpringBootTest(classes = { Application.class })
#ActiveProfiles("test")
public class IncrementalLoadServiceTest {
#Autowired
private IncrementalLoadService incrementalLoadService;
#Test
public void checkInitialRecords_incrementalLoad() {
List<IncrementalLoad> incrementalLoads = incrementalLoadService.list();
assertEquals(3, incrementalLoads.size());
}
So I think I found the solution. I created another #SpringBootApplication class in my test folders. Initially that failed but I believe thats because the entity scan annotation pointed to packages where my "production" #SpringBootApplication was. I moved that class up a level and it all seems to work ok now.

Replace Beans.xml configuration in Spring

How can I replace beans.xml file for testing purposes?
I use
#SpringBootApplication
#ImportResource("classpath:Beans.xml")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
to init class, but in my testing class
#RunWith(SpringRunner.class)
#SpringBootTest
public class ArrayCointainerTest {
I'd like to use another one.
Any idea for this?
Define a separate configuration class which has you beans xml imported and annotate that with #TestConfiguration. Spring boot automatically pick this up as your test configuration
Detecting test configuration

Spring Boot not using application.properties for spring.groovy.template.cache

I have a very simple Spring Boot application with classes detailed below.
My problem is with the application.properties file and how they get auto-configured. I'm trying to get Groovy Templates to update in dev by setting 'spring.groovy.template.cache: false', however this is not working. I added two more properties to see if the application.properties file was being read. The 'logging.level.org.springframework.web: ERROR' still results in INFO level messages printed to the console. However, some.prop is read correctly into the MyBean class on application start.
Is there a configuration declaration I'm missing for these properties?
src/main/resources/application.properties:
spring.groovy.template.cache: false
logging.level.org.springframework.web: ERROR
some.prop: bob
src/main/java/sample/MyBean.java:
#Component
public class MyBean {
#Value("${some.prop}")
private String prop;
public MyBean() {}
#PostConstruct
public void init() {
System.out.println("================== " + prop + "================== ");
}
}
and src/main/java/sample/Application.java:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
and src/main/java/sample/com/example/MainController.java
#Controller
public class MainController {
#RequestMapping(value="/login", method = RequestMethod.GET)
public ModelAndView risk(#RequestParam Optional<String> error) {
return new ModelAndView("views/login", "error", error);
}
}
It seems you missing scanned your package "sample". Please make sure that you have scanned it.
#ComponentScan({
"sample" })
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Also, your application.properties is right. No problem with it.
It appears the solution was much simpler than I thought:
gradle bootRun
should be used to hot reload templates
gradle run does not work (all compiled classes are just built in build/ )

Run another project's web service before start tests

IntelliJ project has two modules: Spring Data Rest app and client. Both apps are Spring bootable apps. I made a lot of tests at client and now before every test iteration I have to run the rest service manually.
Test class looks like that:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {BusinessRepositoryImpl.class})
public class BusinessLogoRepositoryTest {
..
}
Here is the service:
#EnableAutoConfiguration
#ImportResource({
"classpath:spring/persistenceContext.xml"
})
#Import(DataServiceConfiguration.class)
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
So the question is if it's possible somehow to add the context of service to test class and run the service before test's start.
You can create a TestSuite with 2 methods annotated with #BeforeClass and #AfterClass to start the service before the tests and stop it after the tests are done.
Draft code to visualize :) what I mean is below.
#RunWith(SpringJUnit4ClassRunner.class)
#SuiteClasses({UnitTest1.class, UnitTest2.class, ... })
#EnableAutoConfiguration
#ImportResource({
"classpath:spring/persistenceContext.xml"
})
#Import(DataServiceConfiguration.class)
public class TestSuite {
#BeforeClass
public void start() throws Exception {
SpringApplication.run(Application.class, args);
}
#AfterClass
public void start() throws Exception {
SpringApplication.shutdown();
}
}

Loading applicationcontext.xml when using SpringApplication

Could anyone provide an example of a SpringApplication that loads an applicationContext.xml file?
I'm attempting to move my GWT RPC application to a RESTful web service by using a Spring's Example (Gradle based). I have an applicationContext.xml but I do not see how to get SpringApplication to load it. Loading manually via
ApplicationContext context = new ClassPathXmlApplicationContext(args);
results in an empty context. ...and even if that worked it would be separate from the one returned from
SpringApplication.run(Application.class, args);
Or is there a way to get external beans into the app context created by SpringApplication.run?
If you'd like to use file from your classpath, you can always do this:
#SpringBootApplication
#ImportResource("classpath:applicationContext.xml")
public class ExampleApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(ExampleApplication.class, args);
}
}
Notice the classpath string in #ImportResource annotation.
You can use #ImportResource to import an XML configuration file into your Spring Boot application. For example:
#SpringBootApplication
#ImportResource("applicationContext.xml")
public class ExampleApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(ExampleApplication.class, args);
}
}
The annotation does not have to be (on the class) that (has the main method) that (has this below call):
SpringApplication.run(Application.class, args);
(in your case, what I am saying is that #ImportResource does NOT have to be on your class)
public class ExampleApplication {}
.........
You can have a different class
#Configuration
#ImportResource({"classpath*:applicationContext.xml"})
public class XmlConfiguration {
}
or for clarity
#Configuration
#ImportResource({"classpath*:applicationContext.xml"})
public class MyWhateverClassToProveTheImportResourceAnnotationCanBeElsewhere {
}
The above is mentioned in this article
http://www.springboottutorial.com/spring-boot-java-xml-context-configuration
.........
BONUS:
And just in case you may have thought "SpringApplication.run" was a void method.....that is NOT the case.
You can also do this:
public static void main(String[] args) {
org.springframework.context.ConfigurableApplicationContext applicationContext = SpringApplication.run(ExampleApplication.class, args);
String[] beanNames = applicationContext.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String name : beanNames) {
System.out.println(name);
}
This will also subtly clue you in to all the many, many, many (did I mention "many"?)....dependencies that spring boot is bringing in. Depending to whom you speak, this is a good thing (somebody else did all the nice figuring out for me) or an evil thing (whoah, that's a lot of dependencies that I don't control).
hashtag:sometimesLookBehindTheCurtain
Thanks Andy, that made it very concise. However, my main problem turned out to be getting applicationContext.xml into the classpath.
Apparently, putting files into src/main/resources is required to get them into the classpath (by placing them into the jar). I was attempting to set CLASSPATH which was just ignored. In my example above, the load seemed to fail silently. Using #ImportResource caused it to fail verbosely (which helped me track down the real cause).

Resources