Spring 3 #value annotation with maven profile properties - java

I have a bunch of properties defined in pom.xml for different profiles. I would like to use #value annotation to inject the property values. It is enough to get the values set at build time.
What kind of options I have with this #value annotation? Do I have to have a separate property file or can I utilize applicationContext.xml?

What I'd do is use the properties maven plugin to write the project properties to a file and then reference that file from Spring via the PropertyPlaceHolderConfigurer mechanism

The Maven filtering works as a simple textual substitution, it doesn't know anything about spring and annotations. Not sure which way is better for you, if you describe your problem (but not one of yours possible solutions), I could try to suggest more constructive solution.

Related

How does the spring framework map properties to a Java Object?

I am trying to do something very similar to what spring #ConfigurationProperties does to map properties to a Java POJO, but at runtime. I am hoping to be able to reuse the spring framework code that does this for spring properties.
I looked through a bunch of spring's code but I am having trouble isolating the code that does this specific functionality. I can write my own algorithm to do this, but it feels like a waste since I know this is existing functionality in the spring framework and I have spring dependencies in my project already.
After some more digging, I found the following class: ConfigurationPropertiesBinder, which binds properties from various PropertySources to a Bindable object. I was able to extract enough information from this bean to create my own version to do the conversion I was looking for.

Easier way to customize Spring Boot properties for a particular context

I have a project that uses a YAML with all default Boot properties with prefix spring.jms.*, spring.activemq.*... I'm moving it to a starter, so I need to isolate the needed configuration for my internal component from the defaults of the importer application.
Is there any way to nicely deal with this need? Ideally I can take profit transparently of the very same properties classes (JmsConfiguration, etc...) since they include the nested configurations. Perhaps in a way I have 2 blocks with spring.jms and such, and marking my properties as from a particular block.
I know profiles exist, but It feels weird to drive them from an optional component via starter.
Found it!
In the #Configuration:
#Bean
#ConfigurationProperties("custom.jms")
public JmsProperties customJmsProperties(){
return new JmsProperties();
}
Anyway, after some discussions with Pivotal people, it seems like my need is probably a sign of a bad design

Best Practice Changing Spring Implementation Object in JUnit Test

I have a Spring-enabled JUnit Test. It loads my default applicationContext.
Now I want to replace a single bean for my test, i.e. entityManager with testEntityManager.
I can imagine three possible ways, which don't seem very elegant:
split the context (defaultContext, emContext) and override context file by test context file (emContext in test resources)
use factory and choose testEntityManager (in production code)
not to use Spring, but build the object hierarchy myself (least feasible solution)
Is there a best practice how to do it right?
Background to this question is: I really only want to replace the objects close at the boundary (DB, Webservices, etc)
Yours Sincerely
EDIT: I have solved it this way now:
I added a properties file to my classpath and test classpath and used a Spring alias in conjunction with a property placeholder.
This way I was able to wire my beans to a different implementation in the tests.
Spring allows you to override bean definitions, when you are loading contexts from multiple locations.
So you don't necessarily need to to split the context "/applicationContext.xml".
Instead have an additional application context for test "/applicationContext-test.xml", where you override the bean you need.
Then pull in both configurations and have the bean in the test configuration override the bean in the production configuration.
#ContextConfiguration({"/applicationContext.xml", "/applicationContext-test.xml"})
The best practise IMHO would be to use spring bean definition profiles. My documentation link will lead you to other readable resources. Google will also provide useful links like Gordon Dickens: Spring 3.1 Environment Profiles.

Setting class properties in Java, Spring config Vs System Properties file

We can use both Spring config file OR a .properties file to store and retrieve some properties, like for a database connection. (db url, db password and etc)
We can also use Spring config file and a .properties file together, where we reference the property from a .property file (like in ant)
What would be the advantages or disadvantages for the following scenarios:
1 - Using only .properties file.
2 - Using only Spring config file.
3 - Using both together.
Would any of the scenarios be better when it comes to maintenance?
I need to choose between the three, and I would like to have a better judgement before I go with any of the option!
Thanks in advance!
- Ivar
Both together. Use a properties file that's externalizable from your project to configure Spring. Spring then configures your project. Mostly, you don't write code to read from properties files. Let Spring manage that and inject your objects with the appropriate values. Then you have appropriate dependency injection and the artifact you build isn't environment-specific.
Disadvantages:
How does your code know what file to load the properties from? Isn't that a property? It also violated dependency injection by having code go find a resource rather than passively accepting one.
Configuration is tightly coupled to your artifact and can't change between environments without rebuilding (BAD).
The way you seem to think of it, this combines the disadvantages of the other two, but if you do it the way I described, it eliminates those disadvantages, which is an advantage.

Are properties read by a Spring Property Placeholder immediately available?

I am modifying code that uses a Spring PropertyPlaceholderConfigurer in an application context file. The properties are successfully read and used in the application. However, if I follow the PropertyPlaceholderConfigurer declaration with an <import resource="classpath:/my/class/path/${my.file.name}" />, a "Could not resolve placeholder 'my.file.name'" error and a series of exceptions are thrown. Are properties immediately available after declaring the PropertyPlaceholderConfigurer? If not, at what point do they become available?
The import resources are resolved BEFORE the PropertyPlaceHolderConfigurer(a BeanFactoryPostProcessor) resolves the property place holders. You will have to put the resolved resource name in your imports.
Since PropertyPlaceHolderConfigurer is a BeanFactoryPostProcessor, it is called once the bean definitions have been loaded up from the Spring configuration files.
There's multiple passes done on a spring context file, so it's a question of at what pass are the properties available. Unfortunately, <import> tags are handled on an earlier pass than bean declarations (such as the one for your PropertyPlaceholderConfigurer), therefore it won't be available in the way you're trying to use it.
What you're (likely) trying to do is a common thing in Spring, with many various solutions. They often involve modifying your build to do the injection. Googling/Stack Overflowing for per-environment spring config should turn up something. I've read Spring 3.1 will provide a facility to allow per-environment configuration (so use "this" properties file if I'm doing a "test" build, this one if I'm doing a "dev" build etc.), but I don't know much about it at this point.

Categories