How to handle externally stored default values in Domain Class - spring

I want to be able to set default values for some fields in my domain classes.
Till now I had a class which stored a Map of settings for my whole project, with a task in mind to move this map into a redis database.
The day has come and I moved all the data to redis and created a nice spring bean to get/set the values.
However...
it seems that default values are set on the domain class instance before bean is injected.
This kind of breaks the whole process.
Also... there's an issue with unit tests.
I've created a class which implements the same interface as the spring bean and holds test values. I wanted to inject it into domain classes, but this fails as well.
So right now I'm trying to find a good way to handle externally stored defauls values for my domain classes with ability to run unit tests.
Any thoughts?

There are a few different approaches you could take:
Introduce a separate bean with the default values so that those are supplied in the same way as they were before. In a separate higher level context or later on in application startup, you could then override the bean definition with the one that pulls from the database
Use a BeanPostProcessor or BeanFactoryPostProcessor to specify the default values, then use your new bean for retrieving new values
If neither of these answers is helpful, please post your setup and example code so I can get a clearer picture of what you're trying to do.

What I did in the end:
I've created a class which is connecting to Redis and gets me all the data I require.
For unit testing I've created a copy of this class, it implements the same interface but instead of getting the data from Redis it has a simple Map inside and get's the data from there. In the end it acts the same, but the data is stored internally. So in my unit tests I just inject this Unit test version of this class where appropriate.
Probably not the best solution there is but it worked for me for the last few months.

Related

Returning an object from a Spring Batch job / processor

I have a Spring Batch job that reads in a very large fixed length file and maps it just fine to an object. Validated all of the data in the associated processing task.
Being rather new to Spring and Spring Batch I am wondering if it is possible to get out of the job, a fully populated object to be used in a particular case when I am running the job as part of another process ( that I would like to have access to the data).
I realize that I could do the above without Batch, and it seems to be designed with scope limitations for its purpose.
I could serialize the objects in the processor and go that route but for my immediate satisfaction I am hoping there is a way to get around this.
Thanks
In my #configuration class for the batch processing, I created a class variable (it is a list of the object I want to get back) and instantiated with the no arg constructor.
My Step, ItemReader, LineMapper are setup to use a list for input. The custom FieldSetMapper takes that list instantiated from the constructor as a parameter and adds to the list as the file is read and mapped. Similarly my custom ItemProcessor takes the list as input and returns it.
Finally I created a ReturnObjectList bean that returns the populated list.
In my main I cast the AnnotationConfigApplicationContext getbean to the list of that object type. I am now able to use the list of objects generated from the fixed file in the scope of my main application.
Not sure if this is a healthy work around in terms of how Spring Java config is supposed to work, but it does give me what I need.

getting bean id of target class in advice

I have a few classes that interact with databases (more than one). Some classes are reused so for example "obs.table1" is used to interact with table1 in database "obs" while "ref.table1" is used to interact with table1 in database "ref". These databases are at different URLs and each gets its own connection pool, etc... obs.table1 and ref.table1 are both instances of MyTable1Class, defined in beans file.
I have a pointcut that intercepts calls to methods annotated with #Transactional or with a custom annotation #MyTablesAnnotation and have it set so those calls will all get routed into a #Around advice.
This all works and the flow through the advice is correct.
What I am trying to add is reporting on what is going on in there. Currently I can tell where in there I am, but I can't tell if it was obs.table1 or ref.table1 object that got me there.
Is there a way to extract the bean id of the object on whose method the advice was invoked on?
ProceedingJoinPoint that is passed to the method the only thing I do with it is call a .proceed on it and the rest is just various checks and catches. I see that I can get either the target class or proxy class out of it, but... not sure how to go from there to knowing what the bean id was.
Is it possible?
Firstly it is not recommended to depend on bean id as it creates tight coupling with framework.
To quote from docs Note that it is not usually recommended that an object depend on its bean name, as this represents a potentially brittle dependence on external configuration, as well as a possibly unnecessary dependence on a Spring API.
Now to answer your question yes it is possible to fetch the name of bean via org.springframework.beans.factory.BeanNameAware.
The class for which you require the bean name should implement it and spring will auto-magically inject the name of the bean. However there is a gotcha which you should be aware and is mentioned in docs here

Application-wide process in SpringMVC

Suppose I have a certain operation that should be available to every process running in Spring MVC.
Say string normalization--
i need to run a method that normalizes the string fields before doing anything else on that form/data.
One thing specific to do is, to normalize the String fields on every input form before
they are dispatched to the back-end services. Likewise, that operation (normalization)
should be run on data from the back-end before it is dispatched to the view component.
One way of doing this that I can think of is:
Code a bean doing it-- the normalization. Then, define this bean somewhere at the top in
the context hierarchy of Spring-- ApplicationContext.xml or WebApplicationContext.xml(?),
so that it will be visible and can be used
accross all the processes/servlets in the application.
Then, Whenever and from wherever needed, invoke that method on the bean defined up there.
Or, inject it to the relevant fields in the bean definitions(?)
In this case, is there a way to call it before or during a HandlerMapping is running? if so, how?
Another i can come up with is:
Code a validator (implement Validator) to run that process and "validate" the String fields for you.
But i dont see how this would be of good help.
From what i know, a validator runs on specific object types. I can define that type generically(?)
but then I'm operating on the fields-- not objects as a whole each.
Coding validator(s) seems too costly to me for this use-- even if it is an option here.
I'm new to Spring. pls bear with me on this.

Spring bean new instance of varing type according to lookup

I have a servlet based application which currently uses an injected HashMap of command processors to process a user entered command. This works very well but I need to modify this so that each instance of the command processor is unique.
The new requirements comes from the need to "pipe" the output on one command into another so if the command processors remain a single instance "piping" a list into a list would be problematic.
I still need to be able to map the class that handles the command to the command text.
My first thought was the change the HashMap from mapping the command to an instance of the command processor to mapping it to the class name and using that to instantiate an instance of the class. But that does not work due to the need to configure some of the commands with for example a list of options.
I have looked at making the beans prototypes which would seam to do what I want regarding getting a new instance of the configured bean but I am confused as to how I can map this, was thinking I could use the bean ID.
I am now at the stage of complete confusion and cant think how to do this.
I am aware that the explanation is a little light but this is a reflection of my confusion and I suspect that the greatest help will come from request for clarification which will help to get the head in order.
You could use request-scoped beans:
#Component
#Scope(value=WebApplicationContext.SCOPE_REQUEST,proxyMode=ScopedProxyMode.TARGET_CLASS)
public class CommandProcessor {
}
You can just inject CommandProcessor in your code and Spring will make sure you get different instance for every user request. You also will need CGLIB on your classpath.
If I got your requirements right you either need a factory method in your command class, or a FactoryBean that creates the instances.

Can PropertiesPlaceholderConfigurer subclass detect active Spring profile?

We have a specific format for our config files, where instead of having multiple files - ie, dev.properties, uat.properties, prod.properties - we instead have all the values in one file, but separated by prefixes for each environment. For example:
SERVICE_PORT=9800
DEV_SERVICE_PORT=7800
UAT_SERVICE_PORT=6600
We have an existing class (subclass of PropertyPlaceholderConfigurer) that looks up these values, and decides what prefix to add inside resolvePlaceHolder() based on the IP address where it is executing, ie for a certain IP range, use DEV_ prefix, for another, use UAT_ prefix. These values then get passed on to other beans, in some cases using the context xml, and in some using the #Value${} annotation on some bean constructors. The use of the prefixes is transparent, so all other configs will use SERVICE_PORT (in the example)
We want to change this so that instead of using IPs, we will just detect the active Spring Profile. We have a custom ApplicationContextIniitalizer in our web.xml that detects a java System property that indicates our type of environment.
The problem I have is that at the time resolvePlaceHolder() gets called, there doesn't seem to be any Active Profiles yet! What I"m doing to detect the active profile is:
create an instance of StandardEnvironment
call getActiveProfiles()
(2) always seems to return an empty array. This implies that propertyplaceholder resolution occurs before any Spring profiles are activated. Is this correct??
When does the active profile get set, in relation to other events during Spring context loading, like creating the beans, loading property files, etc?
Is it possible to detect the active profile at the time that resolvePlaceHolder() is called? Should I be extending another class instead?
Beans managed within an ApplicationContext may register to be
EnvironmentAware or #Inject the Environment in order to query profile
state or resolve properties directly.
[Source: Environment javadocs ]
Don't create an instance of StandardEnvironment, inject it into your bean!

Resources