Spring Boot read values from application properties - java

I'm not sure if I understand it correctly, but from what I got, is that I can use #Value annotations to read values from my application.properties.
As I figured out this works only for Beans.
I defined such a bean like this
#Service
public class DBConfigBean {
#Value("${spring.datasource.username}")
private String userName;
#Bean
public String getName() {
return this.userName;
}
}
When the application starts I'm able to retrieve the username, however - how can I access this value at runtime?
Whenever I do
DBConfigBean conf = new DBConfigBean()
conf.getName();
* EDIT *
Due to the comments I'm able to use this config DBConfigBean - but my initial problem still remains, when I want to use it in another class
#Configurable
public SomeOtherClass {
#Autowired
private DBConfigBean dbConfig; // IS NULL
public void DoStuff() {
// read the config value from dbConfig
}
}
How can I read the DBConfig in a some helper class which I can define as a bean
Thanks

As Eirini already mentioned you must inject your beans.
The #Value annotation only works on Spring beans.
There is another way of accessing configuration with #ConfigurationProperties.
There you define a class that holds the configuration.
The main advantage is, that this is typesafe and the configuration is in one place.
Read more about this:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-vs-value

You shouldn't instantiate your service with the new operator. You should inject it, for example
#Autowired
private DBConfigBean dbConfig;
and then dbConfig.getName();
Also you don't need any #Bean decorator in your getName() method
You just need to tell spring where to search for your annotated beans. So in your configuration you could add the following:
#ComponentScan(basePackages = {"a.package.containing.the.service",
"another.package.containing.the.service"})
EDIT
The #Value, #Autowired etc annotations can only work with beans, that spring is aware of.
Declare your SomeOtherClass as a bean and add the package config in your #Configuration class
#Bean
private SomeOtherClass someOtherClass;
and then
#Configuration
#ComponentScan(basePackages = {"a.package.containing.the.service"
"some.other.class.package"})
public class AppConfiguration {
//By the way you can also define beans like:
#Bean
public AwesomeService service() {
return new AwesomeService();
}
}

Wrap your DBConfig with #Component annotation and inject it using #Autowired :
#Autowired
private DBConfig dbConfig;

Just add below annotation to your DBConfigBean class:
#PropertySource(value = {"classpath:application.properties"})

Related

Spring Boot read application.properties / .yml variable without annotations

I want to create a class using new operator and in that class I want to read a property from application.yml file, how to do that in Spring Boot application ?
In other words I cannot use #Value, #Autowire, #Component annotations.
You need to do something like this:
#Configuration
#ConfigurationProperties(prefix = "test")
public class TestProperties{
private String testProperty1;
public String getTestProperty1() {
return testProperty1;
}
public void setTestProperty1(String testProperty1) {
this.testProperty1= testProperty1;
}
}
next in Your application.properties:
test.testPropety1 = yourProperty
You can implement this properties class as bean because of #Configuration annotation. Hope that helps in Your problem :)

Eliminating Spring.xml from Spring Framework

In Spring Framework is it possible to eliminate the entire Spring.xml and use a configuration class with #Configuration and #Bean annotation for creating bean, and for all other purpose use a spring.xml?
Yes, you can have pure java configuration in Spring. You have to create a class and annotate it with #Configuration. We annotate methods with #Bean and instantiate the Spring bean and return it from that method.
#Configuration
public class SomeClass {
#Bean
public SomeBean someBean() {
return new SomeBean();
}
}
If you want to enable component scanning, then you can give #ComponentScan(basePackages="specify_your_package") under the #Configuration. Also the method name as someBean serves as bean id. Also if you have to inject a dependency, you can use constructor injection and do as following:
#Configuration
public class SomeClass {
#Bean
public SomeDependency someDependency() {
return new SomeDependency();
}
#Bean
public SomeBean someBean() {
return new SomeBean(someDependency());
}
}
Yes,most of (maybe all of)official guides uses absolutely no xml configuration file,just annotations.

Registering #Component annotated class programmatically

I'm new to spring framework, my problem is to register spring component through the spring application context I tried it with many different ways but no luck yet.
#Configuration
#ComponentScan("com.example.app")
#EnableAutoConfiguration
public class ContextDataConfiguration
{
...
}
registered it with
#PostConstruct
public void initilize()
{
AutowireCapableBeanFactory beanFactory = context.getAutowireCapableBeanFactory();
beanFactory.initializeBean( new ContextDataConfiguration(), "contextDataConfiguration" );
}
but the other beans specified in the ContextDataConfiguration class are not getting initialized with this approach.
And if I specify the ContextDataConfiguration class in the component scan it is working but it is giving me an error like
not a managed type class
Is there any alternative way to do this?
You can use the #Bean annotation in a factory method to initialize your bean. So, lets say you have a MyBean component and wants to initialize it... You can do this inside your #Configuration class:
#Bean
public MyBean myBean() {
MyBean myBean = ... // initialize your bean here
return myBean;
}
How a about
#Bean
public ContextDataConfiguration contextDataConfiguration(){
return new ContextDataConfiguration();
}
This registers an instance of ContextDataConfiguration as a bean.

How to read properties file in Controller using annotations only? Spring MVC

How to read properties file in Controller using annotations only?
Properties file contains (env.properties):
document.portal.path=http://flana.gost.com/service
Spring Controller:
#Controller
#RequestMapping("/kap/*")
#SessionAttributes({"user", "KapForm", "activity"})
public class KapController {
#Value("${document.portal.path}")
private String URL;
}
Nothing else is done. In XML, we use to use placeholder, which i am not getting how to introduce in it. So I am getting exception.
Injection of autowired dependencies failed;
You can achieve it in two ways
Option 1
In config class put #PropertySource and define a bean for PropertySourcesPlaceholderConfigurer as below -
#Configuration
#PropertySource("classpath:someFile.properties")
public class SampleConfig {
// other configs...
#Bean
public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
Option 2
In config class directly specify the bean for PropertyPlaceholderConfigurer and supply the name of property file as ClassPathResource
#Configuration
public class SampleConfig {
// other configs...
#Bean
public static PropertyPlaceholderConfigurer placeHolderConfigurer(){
PropertyPlaceholderConfigurer placeHolderConfigurer = new PropertyPlaceholderConfigurer();
ClassPathResource[] cpResources = new ClassPathResource[]
{ new ClassPathResource( "someFile.properties" ) };
placeHolderConfigurer.setLocations(cpResources);
placeHolderConfigurer.setIgnoreUnresolvablePlaceholders(true);
return placeHolderConfigurer;
}
}
Do note that the bean definition for place holder need to be static as per java docs (excerpts below)
Special consideration must be taken for #Bean methods that return Spring BeanFactoryPostProcessor (BFPP) types. Because BFPP objects must be instantiated very early in the container lifecycle, they can interfere with processing of annotations such as #Autowired, #Value, and #PostConstruct within #Configuration classes. To avoid these lifecycle issues, mark BFPP-returning #Bean methods as static.
Another way out found is
import org.springframework.context.MessageSource;
#Autowired
private MessageSource messageSource;
cutiePie = messageSource.getMessage("cutie.pie.property", new Object[] {},"cutie.pie.property", LocaleContextHolder.getLocale());

What is Annotation counterpart for Spring <context:property-override>?

We can externalize properties using <context:property-placeholder> and we can override the Spring bean properties by configuring <context:property-override> as follows:
<context:property-placeholder location="classpath:application.properties"/>
<context:property-override location="classpath:override.properties"/>
I want to move my XML config to JavaConfig.
#Configuration
#ComponentScan
#PropertySource("classpath:application.properties")
public class AppConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
But how to configure my override properties using Annotation?
PS:
I have a bean say MyBean as follows:
#Component
public class MyBean {
#Value("${someProp}")
private String someProp;
}
In my application.properties I have
someProp=TestValue
and in my override.properties i am overriding someProp value as
myBean.someProp=RealValue
No, It isn't.
But you could create a bean of type PropertyOverrideConfigurer in the configuration class whit the same result.
Update
For example:
#Bean public static PropertyOverrideConfigurer propertyOverrideConfigurer() {
PropertyOverrideConfigurer overrideConfigurer = new PropertyOverrideConfigurer();
overrideConfigurer.setLocation(new ClassPathResource("override.properties"));
return overrideConfigurer;
}
Note the static modifier, this is because BFPP should be instantiated early in the container lifecycle.
see http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/Bean.html for more info.

Categories

Resources