Spring Environment Variable - java

I was planning to use #Value annotation to my service implementation class.
#Value("${some_property:default_value}")
private String key;
To use above annotation, I can use #Autowiredannotation.
#Autowird
Private Environment environment;
But, I am planning to use those setting in my applicationContext.xml file, which is something like following below.
<context: something missing here = "ENVIRONMENT"/>

Yes. You can do it in applicationContext.xml beans tag itself there is a property called profile So you can do profile="ENVIRONMENT" in latest spring version.

Related

What's the Spring way of accessing properties from an entity?

I'm new to Spring and I'm building an application where some entities (JPA/Hibernate) need access to a property from application.properties. I do have a configuration class in which this is trivial:
#Configuration
public class FactoryBeanAppConfig {
#Value("${aws.accessKeyId}")
private String awsAccessKeyId;
#Value("${aws.secretKey}")
private String awsSecretKey;
}
but since entities do not have and I think they should not have the annotations such as #Configuration or #Component, what's the Spring way for them to access the property?
Now, I know I can create my own class, my own bean, and make it as a simple wrapper around the properties; but is that the Spring way to do it or is there another way?
specify Property file location using #PropertySource
Something like below
#PropertySource("classpath:/application.proerties")
You also need to add below bean in your config
#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigIn() {
return new PropertySourcesPlaceholderConfigurer();
}
There is no "Spring way", since JPA entities and Spring have nothing to do with each other. Most importantly, JPA entities are not Spring beans, so Spring doesn't know or care about them as they're not managed by Spring.
You can try to hack around, trying in vain to access Spring's configuration from code that should not be trying to access it, or you can accept the truth that your design is broken and you're trying to do something that's not meant to be done.
As was proposed several times, use a service class for this. It's managed by Spring, so it can access the Spring config, and it can handle entities, so there's no crossing boundaries.
First create a public static variable in some bean managed by Spring, then make the following use of the #Value annotation.
public static String variable;
#Value("${variable}")
private void setVariable(String value) {
variable = value;
}
It will be set at runtime on startup, now you can access it from entities and everywhere else because it is just a public static var.
You can use #PropertySource to load the properties file as follows
#Configuration
#PropertySource("classpath:/com/organization/config/application.proerties")
public class FactoryBeanAppConfig {
...
}
Entities should not acces environment properties. If you are using your entity through a service, then the service can access the properties to act on the entity.

SpringCloudConfig When I use these annotations #RefreshScope #ConfigurationProperties ,I was in trouble

SpringCloudConfig trouble
When I use these annotations #RefreshScope #ConfigurationProperties, I was in trouble.
#Component
#RefreshScope
#ConfigurationProperties(prefix = "config.message")
public class MessageProperties {
private int max_num;
private boolean begin;
private String ding_department;
// getter, setter...
}
like this ! Config does not work;
but when I use only #ConfigurationProperties,it works. So What's the use of #RefreshScope. And how to fix it?
So when you use "I was in trouble" in stackoveflow you are in trouble that there is high probability no one to answer.
#ConfigurationProperties is used for mapping properties to a POJO, with prefix you start using hierarchical properties structure. SO for example based on your description your code will work if you have the following .yml
config:
message:
max_num:
begin:
ding_department:
If for example you use spring-cloud-config server to store the configuration properties and spring-boot and want on change on the file the corresponding Bean with injected conf file to be update you add #RefreshScope, but even if you do this the bean is not updated you have to call the /refresh url or to trigger event which will refresh it.

Library (JAR) default value for properties spring

I have an application that need to send emails. I might need later to send emails in a second application so I try to do a library to re-use it.
My application is done with Spring-boot.
My library just include Spring-core, Spring-context and Spring-test.
This is my EmailUtils in my library :
#Named
public class EmailUtils {
#Value("${from}")
private String from;
#Value("${to}")
private String to;
...
}
I would like to have a default file application.properties with that in the library :
from=default-from
to=default-to
now I would like if my application spring boot does something like that :
#Service
public void EmailService {
#Inject
private EmailUtils emailUtils;
...
}
I would like if I don't define a new application.properties in my application to get the default value from the library but would be possible to override them by using an application.properties in my Spring-boot app.
Info : My Spring-boot app have ScanComponent package (just to mention it). But my library has nothing. I don't know if I have to use a beans.xml and define a ContextPlaceHolder ...
I am a little bit loss, maybe there is a better way to do it ?
Thank you.
If I am correctly understanding your question - you want to specify a default value for your #Value annotated properties. You can do this simply by simply using the format #Value("${property_key:default value}") so if you wished the default from value to be me#me.com and to to be you#you.com your code would read:
#Named
public class EmailUtils {
#Value("${from:me#me.com}")
private String from;
#Value("${to:you#you.com}")
private String to;
...
}

Spring: #Value vs. #Autowired

I'm having some issues with injection in the application I'm working on (using Spring Version 3.1.2). To start with, I'm seeing a lot of code like this:
#Value("#{searchRequestBean}")
private SearchRequest searchRequest;
#Value("#{searchResponseBean}")
private SearchResponse searchResponse;
#Autowired
private SavedSearchService service;
Each of these three appears to have the effect of autowiring the specified bean/service into the class. What I don't understand is, what's the difference between #Value and #Autowired in these cases? Every example I find online seems to use #Value to inject values from a properties file. In this case, SearchResponse and SearchRequest are abstract classes.
I'm hoping that a better understanding of this will help me solve some issues I'm having with my Session bean.
#Value can be used for injecting default values. A good example is to inject the default of a String to be the value of a property file. In your example, #Value is used to set the default value of a class to be a Spring managed bean.
#Autowired can't be used for the first example: It's not property file aware. #Autowired is only for DI of a bean. It is more specific than #Value, but you can use #Value to do the same thing.
Here is a good tutorial for #Value: http://www.mkyong.com/spring3/spring-value-default-value/

Using placeholders in Annotations on Spring Java Configurations

I'm a little bit lost in Spring's Property Replacement mechanism. Lets say I have this Java Config
#Configuration
#ComponentScan(basePackageClasses = Application.class)
#PropertySources({
#PropertySource("classpath:/config/default.properties")
})
public class ApplicationConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();
return pspc;
}
Now I want to add a Spring-Data Annotation #EnableMongoRepositories and define a custom basepackage for scanning, using a custom placeholder like follows
#EnableMongoRepositories("${my.custom.repobasepackage}"). The Placeholder is defined in my default.properties.
However, this property cannot be resolved here. When diving deeper into Spring's property replacement, I can see that it tries to resolve the property, so it is possible to do so.
However, the underlying Environment class which is used to replace the placeholder does not know about my PropertyPlaceholderConfigurer, but only know about my SystemProperties and my VM-Props. :-(
I can see that in org.springframework.context.annotation.ClassPathBeanDefinitionScanner#getOrCreateEnvironment.java#339 (I'm using Spring 4.0.1) my "PropertyPlaceholder" is already in place, so its not a question of ordering in initialization, but is not used, because the used BeanDefinitionRegistry does not implement the Interface EnvironmentCapable. Here, my understanding of the Spring App-Context Bootstrapping is at the end.
Can anybody help me out here? Is there a BeanDefinitionRegistry out there which is capable of providing the Environment Instance which uses my Property Placeholder?
Any help is highly appreciated!! I got cookies for you! :-))
Cheers, Stefan
I imagine that the #PropertySources (you only have one by the way so you don't need the wrapper) are added to the Environment after the config classes are processed, so it will be too late to resolve on one of the annotations of those classes themselves. You can verify this by setting my.custom.repobasepackage as a System property.
As an alternative I encourage you to try out Spring Boot (where application.properties is added to the Environment before any configuration is processed).

Categories