Custom annotation like #Value - spring

I need to create a means to add a custom annotation like
#Value("${my.property}")
However, in my case I need to get the value from a database rather then a properties file.
Basically I would like to create a bean on container startup that reads in property name value pairs from a database and can then inject these into fields belonging to other beans.

Approach #1:
One way is to create an Aspect, with a point-cut expression that matches any method having this annotation.
Your aspect will then:
Read the property value in the annotation
Look up the required value an inject it into the class.
AOP Kickstart
Here's a guide to getting started with AOP in Spring
http://www.tutorialspoint.com/spring/aop_with_spring.htm
Joinpoint matching
Here's a reference that describes how to create a join-point that matches on annotations: http://eclipse.org/aspectj/doc/next/adk15notebook/annotations-pointcuts-and-advice.html
Approach #2:
Another way is to use a BeanFactoryPostProcessor - this is essentially how a PropertyPlaceholderConfigurer works.
It will look at your bean definitions, and fetch the underlying class.
It will then check for the annotation in the class, using reflection.
It will update the bean definition to include injecting the property as per the value in the annotation.
. . actually I think approach #2 sounds more like what you want - all of the processing happens on "start-up". . . (In actual fact your modifying the bean recipes even before startup). . whereas if you used AOP, you'd be intercepting method invocations, which might be too late for you?
Namespace Handler
If you wanted you could even create your own Spring namespace handler to turn on your post processor in a terse way. Eg:
<myApp:injectFromDb />
as an alternative to:
<bean class="MyDatabaseLookupProcessorImpl etc, etc. />
Update: Approach #3
As of Spring 3.1 there's also the PropertySourcesPlaceholderConfigurer, that will provide most of the plumbing for you, so you can achieve this with less code.

Alternatively you should be able to configure kind of properties repository bean and then use it in SpEL directly in #Value annotation.
Let's say you'd have bean called propertiesRepository in your context that implements following interface:
interface PropertiesRepository {
String getProperty(String propertyName);
}
then on bean where you want to inject values you can use following expression
#Value("#{propertiesRepository.getProperty('my.property')}")
String myProperty;

You can use #Value annotation by injecting database configuration in application environment itself.
I know this is an old question but I didn't find an exact solution. So documenting it here.
I have already answered the same on different forum.
Please refer to this answer for exact solution to your problem.

Related

Alias annotation for providing value to bean method parameter in another annotation

I've been looking around the forum for solution that would implement this functionality, but couldn't find any I could understand. Is it possible to create an alias or through creating an processor an annotation, that will work as follows:
#myAnnotation("myvalue")
So that the underlying logic behind it would be:
#baseAnnotationFromSpring(property="some-static-value=#bean.method('my-value')")

Use of #Scope annotation with Spring Controller

I am working on a project which is based on Struts 1.x, converting it to Spring 4. I have visited many tutorial sites and read Spring 4 tutorials but no one used #Scope annotation with #Controller in tutorial application. My Question is :
1) Is it compulsory to use #Scope attribute?
2) What if we do not use?
3) Is it good practice to use #Scope with #Controller?
We have also reading a property file at server start up and storing it into Property class. I am reading some property in DAOImpl class(Annotated as #Repository). If I use #Scope attribute with both Controller and Repository then it return value otherwise it return NullPointerException. Why is this behavior?
1) Is it compulsory to use #Scope attribute?
No. If you want the default ("singleton") then you don't need to specify.
2) What if we do not use?
Then your application will only create one instance of the bean.
3) Is it good practice to use #Scope with #Controller?
No. It does not make sense for an application to have more than one instance of a controller class (or a repository). If you have a need to use both annotations together, then you are not modelling your classes very well.
Why is this behavior?
Because the context cannot create a scoped bean to inject if the target bean is not being constructed in that scope (e.g. trying to inject a request-scoped bean into a bean that's being created outside the context of a request).
To solve this you need to use scoped-proxies, by setting proxyMode.
In your specific case, however, the solution is that you don't actually need non-default scope.
#Scope- Isn't Compulsory to use with #Controller, unless and until u need one based on your requirements. #Scope defines the scope of the bean, by default its singleton.
And also, Property Class should be managed by Spring, otherwise it will give you an exception.

Spring #Cachable bean reference in key

I want to use the #Cachable annotation on one of my methods, but I have the problem, that the result depends on an attribute of a spring bean that is not part of the method signature.
So I want something like this:
#Cachable(value="mycache", key="#id, #myspringbean.referenceId")
MyResult myMethod(int id);
I guess these are actually two problems: How to get use a composite key and how to use another spring bean in the expression.
The problem of how to use a composite key can probably be solved like in this SO question: #Cacheable key on multiple method arguments
However, I could not find anythig about how to reference to another spring bean in this expression. Is it possible and if yes, how?
You can have a lot a details on SpEL in the Spring documentation (http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/expressions.html). As you can see, you can use bean references using the #myBean syntax. You have to include a bean resolver in your context to do that.
It's not possible to use the current Spring bean name.
I think I would use the following pattern so that each bean object will have it's own "key-space" see also What can be the default key generator.
As for the problem above one can use:
#Cachable(value="mycache", key = "{#id, #root.targetClass.getDeclaredField('attribute').get(#root.target)}")
MyResult myMethod(int id);
just make sure your attribute is public

Spring lookup method injection with parameters

Is there a way to use Spring lookup method inject with parameters? For example, I want to be able to instantiate prototype-scoped beans while passing them arbitrary parameters via constructor.
It looks like this vital feature was finally added in Spring 4.1.0.RC2. I have tested it and it seems to work.
It was added as part of JIRA ticket SPR-7431 ("Passing lookup-method arguments to created bean constructor"):
<lookup-method/> should allow specifying any number of parameters. These parameters should be passed directly to the constructor of the newly created bean.
For more info on how the feature was finally added, this blog post was written by the guy who opened the JIRA ticket.
You can inject them via field/setter injection. (Note that constructor injection is frowned upon by spring, although it's supported)
in short, no. Spring does support something called "method injection" but it's different than you're thinking. Spring also supports constructor injection, but then you're not calling the constructor yourself, Spring is, and wiring it itself.
Instead, you can use reflection to instantiate the class and pass arbitrary parameters yourself:
Class<MyObject> clazz = MyObject.class; // this can be looked up or stored in a field, etc.
MyObject myObject = clazz.getConstructor(String.class, int.class)
.newInstance("arbitrary parameter", 42);

Making sure a Spring Bean is properly initialised

What is the most concise way of making sure that a Spring bean has all properties set and the init method called?
I'll favour answers which use setter injection and XML configuration, since that's what I'm using right now.
I'm trying to evade the case where I either forget to configure a setter or call the init-method.
In future projects I would favour skaffman's response, but I've chosen the one which suits me right now.
This poll is exactly what you are looking for.
Here are the results:
By using the dependency-check attribute in XML: 11.52%
By using the #Required annotation (or a custom annotation): 21.40%
By using InitializingBean and an assert facility: 23.87%
By using init-method and an assert facility: 14.40%
I don't have to, because I use constructor injection for required properties: 19.34%
I check my dependencies in my business methods: 7.41%
I don't check required dependencies: 34.16%
Use the #Required annotation on the setter methods. Spring will then check that they've all been set without you having to check manually.
Alternatively, annotate your init methods with #PostConstruct, and Spring will invoke them for you.
You can add the dependency-check attribute to your bean definition to ensure that all objects / primitives / both have been set.
<bean id="myBean" class="com.foo.MyBean" dependency-check="objects"/>
Skaffman's answer gives more control, but does introduce a compile-time dependency on Spring which you may / may not want.
Use the following attributes of the beans tag to make sure dependency checking and the init method is called on all beans, but it rather assumes you don't call your method "innit".
<beans default-init-method="init" default-dependency-check="objects">
see link

Resources