SpringBoot projects properties not getting picked up by beans in XML Config - spring-boot

I have a SpringBoot Project and everything works fine locally. Now i have created a runnable jar and trying to execute it.
Project is failing to startup as the beans defined in Spring XML config are not picking up properties defined in property files.
These xml configs are not my own but imported from team libraries so i cannot edit them.
Can someone please advise on what can be done to make it work.
Following are the annotations used in Application.java file. I am not able to add #EnableAutoConfiguration as its implicit and i canot add it here.
#SpringBootApplication(exclude = {
JmxAutoConfiguration.class,
JmsAutoConfiguration.class,
ActiveMQAutoConfiguration.class,
HibernateJpaAutoConfiguration.class
})
#ComponentScan(excludeFilters={
#ComponentScan.Filter(type= FilterType.ASSIGNABLE_TYPE, value=RequestReducingAspect.class)})
#EnableScheduling
#EnableSwagger2
#EnableTransactionManagement(mode= AdviceMode.ASPECTJ)
#EnableLoadTimeWeaving(aspectjWeaving= EnableLoadTimeWeaving.AspectJWeaving.ENABLED)
#EnableAspectJAutoProxy
Edit:
#Configuration
#EnableAutoConfiguration
#ImportResource({"classpath:spring-valuation-operations.xml","classpath:spring-trade-info.xml","classpath:spring-ib-valuation-api-service.xml","classpath:caching.xml","classpath:applicationContext-valuations-addin.xml","classpath:regtest-common.xml"})
public class TradeSprayerContext {
}

Related

Does #SpringBootApplication scans test folder for configurations?

I've a #SpringBootApplication annotation in main class of my Spring Boot Application with ordinary folders structure (and #SpringBootApplication is one level package upper then beans in other packages)
I defined some #Configuration classes in some packages but under the test folder.
Will #SpringBootApplication autoconfigure it when start application?
Will #SpringBootApplication autoconfigure it when it will be finded by #SpringBootTest (it's also one level upper but in test folder) when test started?
I am not completely sure, but I would say no, #SpringBootApplication does not scan #Configuration classes in your test folder. What you should use instead is #TestConfiguration and then in your #SpringBootTest add #Import(YourTestConfiguration.class). Find an example below:
#TestConfiguration
public class YourTestConfiguration {
#Bean
(...)
}
#SpringBootTest
#Import(YourTestConfiguration.class)
class AppTests {
(...)
}
You can read more about this and check complete examples in the following online resources:
https://reflectoring.io/spring-boot-testconfiguration/
https://howtodoinjava.com/spring-boot2/testing/springboot-test-configuration/

How is #ConfigurationProperties-annotated classes detected automatically with #SpringBootApplication Annotation

I am learning Spring Boot and have a question with one example in the reference documentation.
Following section of the documentation mentions
6. Using the #SpringBootApplication Annotation
A single #SpringBootApplication annotation can be used to enable those
three features, that is:
#EnableAutoConfiguration: enable Spring Boot’s auto-configuration
mechanism
#ComponentScan: enable #Component scan on the package where the
application is located (see the best practices)
#Configuration: allow to register extra beans in the context or import
additional configuration classes
and the following example to replace this single annotation by any of the features that it enables is bit confusing for me . The example
package com.example.myapplication;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
#Configuration(proxyBeanMethods = false)
#EnableAutoConfiguration
#Import({ MyConfig.class, MyAnotherConfig.class })
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Explanation for the example
In this example, Application is just like any other Spring Boot
application except that #Component-annotated classes and
#ConfigurationProperties-annotated classes are not detected
automatically and the user-defined beans are imported explicitly (see
#Import).
The only major difference I see in the example code above is that it does not have #ComponentScan annotation. I also read in the comments section of an SO answer (Stephane Nicoll May 5 '17 at 11:07) that #Component annotation is not recommended officially to auto detect #ConfigurationProperties. So my assumption is that Spring framework classes with #ConfigurationProperties are not annotated with #Component.
Also I checked the #SpringBootApplication annotation source and couldn't identify anything that should enable the automatic detection of #ConfigurationProperties annotated classes.
The reference document 2.8.3. Enabling #ConfigurationProperties-annotated types section shows the following way to scan and autodetect #ConfigurationProperties
#SpringBootApplication
#ConfigurationPropertiesScan({ "com.example.app", "org.acme.another" })
public class MyApplication {
}
With all these details , I would like to understand
Why is it explicitly mentioned for this example that #ConfigurationProperties-annotated classes are not detected automatically ? and How is #ConfigurationProperties annotated classes automatically detected when #SpringBootApplication is used.
Additional note : I saw a small difference between the prior version of the documentation and the current one. The following reference is missing the current one
Keep in mind that the #EnableConfigurationProperties annotation is
also automatically applied to your project so that any existing bean
annotated with #ConfigurationProperties is configured from the
Environment
Following is what I understand from my analysis.
#ConfigurationProperties annotated types can be registered to the ApplicationContext by
Annotating the class with #ConfigurationProperties with an
annotation that falls in the scope of #ComponentScan (
#Component, #Service and the like ) . Not recommended as per the comment from Stephane Nicoll , which makes sense to me now.
Using annotation
#EnableConfigurationProperties . For this to
work the class annotated with #EnableConfigurationProperties
should be annotated with an annotation that falls in the scope of
#ComponentScan ( #Component, #Service and the like )
Using annotation #ConfigurationPropertiesScan and by making sure
the classes annotated with #ConfigurationProperties is placed
under its radar. The usage is similar to #ComponentScan .
Now , when we replace #SpringBootApplication with individual annotations that it enables and omit #ComponentScan (as in example) , the #EnableConfigurationProperties way (Point 2) of registering the types with #ConfigurationProperties will not work. This probably answers both my questions on why and how .
This was explicitly mentioned probably because the connection between #EnableConfigurationProperties and #ComponentScan is not that obvious for people like me.
Additional details.
The registration of #ConfigurationProperties annotated types when we use #EnableConfigurationProperties happens through of the EnableConfigurationPropertiesRegistrar class that is imported by the annotation
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Import(EnableConfigurationPropertiesRegistrar.class)
public #interface EnableConfigurationProperties {..}

Spring #Configuration annotation with interfaces

We used #Configuration Spring annotation on an interface used as a root for other configurations (linked with the root via #Import annotation). Like this
#Configuration
#Import({
DatabaseConfituration.class,
JmsConfiguration.class,
FlowConfiguration.class,
SchedulerConfiguration.class
})
public interface RootConfiguration {
}
We specify in this way that RootConfiguration isn't a place for any bean definitions and the such approach worked well.
However, I've just realized that IntelliJ IDEA doesn't recognize RootConfiguration as a Sprint Java configuration. In Configuration annotation JavaDoc there is no any mentions about interfaces but only about classes.
So are there any prohibitions to use interfaces with #Configuration in Java configurations in Spring? Or is the issue actually IntelliJ IDEA problem?

How to dynamically register the bean specific properties on bean initialization

I want to register the bean specific properties on bean creation if not exists in the application. For example
public class BeanOne {
#Value("${prop1}")
private String property1;
}
public class BeanTwo {
#Value("${prop2}")
private String property2;
}
I want to register the property 'prop1' and 'prop2' to instantiate the above two beans successfully.
My application is configured with spring-cloud-consul-config. By default consul is not configured with these properties in that time, application will automatically register these properties into consul through ecwid/consul-api
Currently the application throws "IllegalArgumentException" with message "Could not resolve placeholder 'prop1' in string value "${prop1}"
Any Suggestions to avoid the above error.
There are various ways you can do this.
My preferred approach is to set the properties in one or more files externally and then use the #PropertySource("file:///full-path-to-property-file") annotation in a #Configuration class.
This approach, combined with Spring Profiles is very powerful.
Example if you are not using profiles:
Create an application.properties file somewhere on your PC. A good
place to put this is ${user.home}/.somefolder/application.properties
Add the values for prop1 and prop2
Change the permissions on that folder and file. For example you can
run chmod u on .somefolder and chmod 600 on the properties file
Create a Spring Java Configuration class and annotate it with
#Configuration. For example you can create an ApplicationConfig
class in a sub package of your Spring Boot application and annotate
it with #Configuration
Add the #PropertySource annotations as follows:
#PropertySource("file:///${user.home}/.somefolder/application.properties")
An example from my course on Spring Boot, AWS, Bootstrap and Stripe:
#Configuration
#EnableJpaRepositories(basePackages = "com.devopsbuddy.backend.persistence.repositories")
#EntityScan(basePackages = "com.devopsbuddy.backend.persistence.domain.backend")
#EnableTransactionManagement
#PropertySource("file:///${user.home}/.devopsbuddy/application-common.properties")
public class ApplicationConfig {
}
That's it!

#ContextConfiguration how to use XML based config and Java-based at same time?

I'm writing integration tests with SpringJUnit4. I got question. How in #ContextConfiguration I can use XML based config and Java-based at same time. As I know I couldn't do it, but maybe there exist backdoor?
Thanks in advance!
You could create static inner #Configuration class in your test class and use #ContextConfiguration annotation on your class without any parameters. As stated in the article below, Spring will automatically look for static inner #Configuration class if no XML locations or config classes are passed to the annotation.
You can then import your XML config and Java config classes using #Import and #ImportResource annotations. So your base class for your Spring tests could look something like this:
#ContextConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
public class BaseSpringTest {
#Configuration
#Import(BaseConfig.class)
#ImportResource({ "classpath:applicationContext-hibernate.xml" })
public static class ContextConfig {}
}
Sources
Testing with #Configuration Classes and Profiles
Import annotation JavaDoc
ImportResource annotation JavaDoc
Use #ImportResource on #Configuration class to import XML based config.

Resources