Replace Beans.xml configuration in Spring - 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

Related

Spring boot #ConfigurationProperties not working

I'm using #ConfigurationProperties for auto configuration of properties. My code is working in IDE. But when I run the jar in command line, it is not working.
Configuration class:
#Configuration
#ConfigurationProperties(prefix="location")
public class Location {
private String base;
public String getBase() {
return base;
}
public void setBase(String base) {
this.base = base;
}
}
Main class:
#SpringBootApplication
#EnableConfigurationProperties(Location.class)
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
application.yml:
location:
base: c:\test
If I autowire Location class, I see an instance created. But there is not property set. The code is not entering setBase() method.
The application prints this in the console.
AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject'
annotation found and supported for autowiring
Make sure that application.yml file is in the root of your classpath, usually it's put in the resources folder.
The fact that the setBase() method is not called suggests that your application.yml file is not being found. Spring looks in the root of your classpath for the application.yml file.
The comment from M. Deinum is correct saying that your duplicated annotations will result in 2 spring beans for Location class. However, as you say you managed to autowire the bean without getting an error it suggests that your Location class isn't in a package that is found by spring when it's scanning for beans. If there were 2 beans then you'd get an error when you autowired it. By default spring will scan use the package where the #SpringBootApplication is as the base. It will then look in this package and all sub packages.
If your package structure is like this...
myapp.main
Application.java
myapp.config
Location.java
Then you need to add scanBasePackages="myapp" to the #SpringBootApplication annotation.
Also change your main class and remove the #Enable.. annotations. i.e.:
#SpringBootApplication(scanBasePackages="myapp")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
As nothing worked with yaml, I had to change to property file and use
#PropertySource({"classpath:application.properties"})
for the spring to identify the properties file

Identifying Start-Class during runtime in spring boot

I am trying to identify a way to know the name of the Main-Class that started SpringBoot.
e.g.
#SpringBootApplication
public class SampleApplication {
public static void main(String[] args) {
SpringApplication.run(SampleApplication.class, args);
}
#RestController
public class SampleController
{
#GetMapping("/hello")
pubic String sayHello()
{
System.out.println("Need start class name: "+System.getProperty("sun.java.command"));
return "hello";
}
}
}
When I run the springboot using java -jar myappname.jar ,the System.getProperty("sun.java.command") returns org.springframework.boot.loader.JarLauncher
Can anyone advise, how can I get the name of actual run class. I have tried specifying the start-class attribute in the manifest.mf. It still gave me org.springframework.boot.loader.JarLauncher as the start-class.
You should be able to #Autowire in the ApplicationContext and then do context.getBeansWithAnnotation(SpringBootApplication.class).values().toArray()[0].getClass().getName(), which will give you the first (and presumably only) bean in the context annotated with #SpringBootApplication

SpringBoot excludeFilter not working with multiple configuration classes

I am developing a springboot app that has dependency on another springboot application. I want to include Most beans in the parent springboot app but one.
How can I exclude one springboot bean that the parent package has scanned without touching the ParentApplication class?
Ways I have tried but doesn't work:
1: using exclude filtering in my application class to filter out the particular bean class.
2: I also tried to exclude both the bean class and the parent configuration class.
3: add DisposableBean interface to the bean class I want to exclude and destroy it in run time.
below are my application starter configuration class and parent one.
my MyApplication.class:
package com.myapp;
#ComponentScan(
basePackages = {"com.parent",{my own packages..}},
excludeFilters= {
#ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value= {TheClassToExclude.class}),
#ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value= {ParentApplication.class})}
)
#SpringBootApplication(exclude=ParentApplication.class)
public class MyApplication{
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
#PostConstruct
public void init() {
System.out.println("App is initialized.");
}
}
my ParentApplication.class
package com.parent;
#EnableRetry
#EnableScheduling
#SpringBootApplication(exclude = { HibernateJpaAutoConfiguration.class })
#ComponentScan(basePackages = {all the base package including the TheClassToExclude}
#PropertySource({all resources})
public class ParentApplication {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#PostConstruct
public void haha() {
System.out.println("configuration class created");
}
The console prints out: "configuration class created", so ParentApplication is initiated by springboot for some reason, so is the Class I want to exclude.
just for reference - I think that since both classes are annotated with #SpringBootApplication, thus are both #Configuration classes and will take part in the automatic Spring component scan - and it is not clear which of this classes will be scanned first in order to "exclude" the other one - unless... you explicitly specify the entry point, and thus, the first SpringBootApplication class to load like here
You can see which classes get instantiated by Spring component scanning and in what order by setting logging.level.org.springframework=DEBUG in application.properties

Ignore to load XML file from SpringBootApplication

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)

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