Overriding spring properties in test with computed values - java

I know I can use #TestPropertySource. But annotations accept only literals. what if i want to compute the values or even if i want to compute which properties i want to override. is it doable in spring? how can i register arbitrary properties in spring's Environment in tests?

You can use spring profiles to load up a configuration object. By encapsulating the configuration you can compute the values to use in test profile.

Related

Spring boot: create configuration properties bean in runtime

Is there a way to create #ConfigurationProperties beans in runtime using spring's functionality?
Let's say I want to state the prefixes in my custom annotation and create beans for them in runtime because creating them manually seems like a boiler-plate to me.
Something like this:
#MyAnnotation({
#CustomProps(prefix="foo"),
#CustomProps(prefix="bar")
})
And then in runtime, I want to have two config beans of the specified type created from properties with these prefixes.
I know I can generate code for them using an annotation processor, but maybe it's easier to achieve by spring's bean processors or something like this?
Yes! you can achieve it but you can't have class fields for each property. So, easy approach is use spring annotation processor and for fields you can use map which you could map using Environment bean.
https://www.baeldung.com/spring-annotation-bean-pre-processor blog would be helpful in understanding how it works with annotation processor.
(Here)[Spring: access all Environment properties as a Map or Properties object you can see how to get map of properties.

Dynamically selecting data sources in Spring Hibernate - approaches

Is there a simple way to Choose the datasource by reading from UI or a properties file using Spring and Hibernate, if for eg. the Datasources are X and Y. ?
One approach would be to have dual configuration of sessionfactory, datasource and transaction manager. Then, based on the selection of datasource, the DAO is injected with the appropriate sessionfactory. Is there a better option?
My scenario is that I should be able to switch between two databases on the fly as and when client requires a change in DB for the same application.
Is it a good approach to have DAO with DB compatible methods for eg. a method to retrieve data from DB X and another method to retrieve Data from DB Y as data retrieval varies from one DB to another and calling the methods dynamically at run-time.
or
Is it a better approach to have different versions of same application altogether for X and Y databases for the sake of Database compatibility with java ? If this is the right approach I would like to understand why ?
In addition to Spring profiles you can also consider Spring's AbstractRoutingDataSource
The general idea is that a routing DataSource acts as an intermediary
- while the ‘real’ DataSource can be determined dynamically at runtime based upon a lookup key.
You can find more info in this blog and a somewhat newer post, giving an exemplary use with hibernate.
The AbstractRoutingDataSource is easy to use and will support your scenario where you need to switch the DBs on the fly based on some parameter. The later post gives you an example where the switch is made on the fly based on the user selected locale
I have used option one with success: property file, people can change it even by themselves. If you manage to make two implementations of a Dao interface that behave in the same way then go for it, I don't see any reason to do two different applications.
Define config.dao.id with value daoOracle or daoMySql
<bean id='daoOracle' abstract='true' class='...'/>
<bean id='daoMySql' abstract='true' class='...'/>
<bean id='dao' parent='${config.dao.id}'/>
<bean id='myService' class='...'>
<property name='dao' ref='dao'>
</bean>

Is it possible to add values to a Hazelcast distributed map from the xml configuration?

I would like to add few values on startup to my map in Hazelcast before start using it. I would think that, if possible, it is done in the configuration xml.
My question is the following: is it possible to load values into the map before using it?
Afaik there is no direct way to do that from the XML.
But what you could do is to create a MapLoader implementation that will load your predefined values and configure the map to use that maploader.

PropertyPlaceholderConfigurer to look for DB values and use properties file as fallback

I'm wondering if its possible to use the value in DB before properties file in PropertyPlaceholderConfigurer. So what I want to achieve is to load the properties file, and if any keys exist in the database, use that. Right now I don't know where to start, but I'm assuming that there is a method/class that I can override or interface that I need to implement.
Just mention the method/class/interface and I will gladly start from there. TIA
PropertyPlaceholderConfigurer has a "properties" property that can point to an object that retrieves the database values. See an example here: http://pure-essence.net/2011/02/10/spring-loading-properties-from-database-with-a-twist/
Also, you'll want to set "ignoreUnresolvablePlaceholders" to true on the bean that config that loads the properties from the database. That way you can add another PropertyPlaceholderConfigurer as a fallback to provide properties that are not found in the database.
Since you want to merge properties, you may want to implement InitializingBean on your target bean. Your hook will be the afterPropertiesSet method, where you can go about with your kung-fu.
BTW, Spring loads and overrides beans definitions in the order the container encounters it.

Using Dependency Injection in Spring to replace Factory pattern

I am currently working on an application in which the an instance of the domain object D is injected in to the application. The domain object can contain many classes together in different combinations and permutations as defined by its bean and hence leading to many different final objects D, which I refer to as different versions of D. For a given version of D, I have to fill up the primitive values in it and then save it to the database. Saving it to the database is pretty simple using JPA and Hibernate. The problem is filling up the values in D. The values are fetched over the network using SNMP and then filled up. For each version of D, there is different a strategy to follow, since each version of D may have a different MIB. I are currently following the factory pattern. The factory takes a version of D and returns a valueRetriever for specific to that version of D, which is then used to fetch the values and fill D.
The other obvious way is to inject a configuration retriever in with D and then use it to retrieve the configuration. But I also need to use the retriever during runtime to re-fetch the configurations, so that makes it necessary to store the retriever too in the database, hence creating a new table for each retriever, which seems to an overhead currently.
My question is: Can there be a better way to retrieve the configurations i.e. have a valueRetriever given the above scenario using dependency injection.
Edit: Can AOP be of any use here?
It seems that some of the objects you needing to create have a complex creation logic. You may wont to look at the Spring FactoryBean interface, since a FactoryBean can get all the complex details over the network while allowing you to create an instance and then inject it into other beans.
The basis for Spring's DI is the Bean Factory/Application Context, so it's entirely possible to replace what you're doing.
The difference will be that you'll have to be able to put all your permutations into the Spring configuration and give control over to the application context. If you can't do that, perhaps the solution you've got is preferred.
UPDATE: I would start to fear that your Spring solution is adding in too many unfamiliar technologies into what might be an overly complicated situation.
Take a breath and think "simple".
I wouldn't worry about the database for now. The Spring application context will be the database if you can get all the combinations you need into the bean factory. I'm assuming these configurations are read-only and not altered once you declare them. If that's not the case all bets are off.

Categories