How to search bean class if defined by context:component-scan - spring

All:
I wonder if someone defines bean in Java-based configuration way, like use #component etc in class rather than defined it in xml, and use context:component-scan, when I want to find out the implementation of that bean class, how can I find where it is?
Suppose I am using Eclipse.
Thanks

You can either search for the class name (as default the bean name is the same as the class name with the first letter as lower case) or do a full text search for the bean name in Eclipse (you can limit the search to *.java files to speed up the search).

Related

Custom annotation like #Value

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.

JSF 2 managed beans and their methods naming convention when used in EL expressions (in conjunction with Spring)

As far as I know, standard JavaBeans convention for converting properties/class names is used in JSF EL, i.e. method pairs (get|is)Property + setProperty are converted to just property:
public class SomeComponent {
public String getAttribute() { ... }
public void setAttribute(String attribute) { ... }
}
<h:outputText value="#{comp.attribute}" />
The same goes for bean names (unless these names are directly specified in #ManagedBean annotation):
#ManagedBean
public class UsefulBean {
...
}
<h:outputText value="#{usefulBean.doSomething()}" />
This behavior is mostly documented. However, I couldn't manage to find anything about conversion conventions when bean or properties names are started with an acronym, something like
#ManagedBean
public class URLManagerBean {
}
<h:outputText value="#{...ManagerBean.doSomething()}" />
What should go instead of ellipsis in the previous snippet?
Surprisingly, but there is little to no information on the internet on this. Almost all examples of JSF managed beans usage use bean names without multiple adjacent capital letters in the beginning. In the few places I've managed to find it is suggested that bean names started with multiple capital letters should not be converted in any way, i.e. it would be URLManagerBean in the previous code snippet.
Unfortunately, we have a project where a lot of beans are named that way. And everywhere these beans are used they follow this weird, to the least extent, convention:
class URLManagerBean -> uRLManagerBean
That is, only the first letter of the acronym is decapitalized. The project seems to be working well, so this convention somehow works. But IntelliJ IDEA does not like this; it thinks that JSF beans really should be named like URLManagerBean unless I rename it explicitly through the annotation.
I tried changing usage of class URLManagerBean from uRLManagerBean to URLManagerBean, but apparently this does not work - those pages where I tried it stopped working.
Now I think that the reason behind such weird convention is that we're using Spring integration via SpringBeanFacesELResolver. However, this behavior is not documented anywhere.
Is there some explanation for this behavior?
Which #ManagedBean annotation are you using? The one from javax.faces.bean or javax.annotation?
In the first case Spring has nothing to do with it as it will be a JSF managed bean and will follow the conventions as specified by JSF.
The value of the name() attribute is taken to be the managed-bean-name. If the value of the name attribute is unspecified or is the empty String, the managed-bean-name is derived from taking the unqualified class name portion of the fully qualified class name and converting the first character to lower case. For example, if the ManagedBean annotation is on a class with the fully qualified class name com.example.Bean, and there is no name attribute on the annotation, the managed-bean-name is taken to be bean. The fully qualified class name of the class to which this annotation is attached is taken to be the managed-bean-class. Source: #ManagedBean javadocs
In the second case Spring is in the mix and then the behavior differs based on which spring version and/or configuration option you use. Using the AnnotationConfigApplicationContext the AnnotationBeanNameGenerator is used which follows the guidelines (and would result in 'URLManagerBean ' as a bean name). Using other means you might end up with the DefaultBeanNameGenerator which has a much simpler algorithm.
Simply said it might depend on which spring version and which annotation you use.
Links
#ManagedBean Java Documentation
Source for ManagedBeanConfigHandler which generates the beanname (reference implementation)

2 beans with same name but in different packages; how to autowire them?

I have an application that has 2 beans with the same name, but which are in different packages. My Spring application fails because it cannot decide on which bean to take. Is there any solution for this? The beans do not currently implement specific interfaces.
See below an edited example of the exception:
Caused by:
org.springframework.context.annotation.ConflictingBeanDefinitionException:
Annotation-specified bean name 'dataTransferHandler' for bean class
[aaaaa.ws.handler.DataTransferHandler] conflicts with existing,
non-compatible bean definition of same name and class
[bbbbb.ws.handler.DataTransferHandler]
You will have to give your beans different names - if multiple beans are defined with the same name, then the one defined later will override the one defined earlier - so in your case only one bean will exist with the name of dataTransferHandler.
You can give these two beans different names, so that both can exist and you can inject in the correct one either using:
#AutoWired #Qualifier("dataTransferHandler")
OR
#Resource(name="dataTransferHandler")
You can give attribute primary="true" to the bean defination you want to have the preference when autowired. But the bean names must be different. There is no solution for same bean name.
At run-time when you will get the autowired class then the primary true bean will get the preference for autowiring. Hope this helps you. Cheers.
I asked another question regarding the same problem, and there is a solution that doesn't require using the #Qualifier annotation: if both of your DataTransferHandler classes have a #Component annotation, you can simply add a String argument to one of their constructions (i.e. #Component("Foo")), and that should solve the problem without needing additional changes.
See User9123's answer on my question for more details.

Autowired.. more than one?

I am using
<context:component-scan base-package="com.package.dao"/> (Spring 3)
and in my controllers with #Autowired will retrieve automatically the DAO I need. That's perfect and works.
The problem is when I need more than one DAO manager.
How can I do?
I tried with #Qualifier but I am not sure about the name of the dao-manager. className doesn't work
someone can help me?
Thank you!
See in the spring documentation:
#Autowired is fundamentally about type-driven injection with optional semantic qualifiers. This means that qualifier values, even when using the bean name fallback, always have narrowing semantics within the set of type matches; they do not semantically express a reference to a unique bean id
...
If you intend to express annotation-driven injection by name, do not primarily use #Autowired - even if is technically capable of referring to a bean name through #Qualifier values. Instead, prefer the JSR-250 #Resource annotation which is semantically defined to identify a specific target component by its unique name, with the declared type being irrelevant for the matching process.
Use #Resource instead, see here.

Overriding the bean defined in parent context in a child context

Our app has a requirement to support multi-tenancy. Each of the boarded customer might potentially override 1 or more beans or some properties of a bean defined at the core platform level (common code/definitions). I am wondering what is the best way to handle this.
Spring allows you to redefine the same bean name multiple times, and takes the last bean definition processed for a given name to be the one that wins. So for example, your could have an XML file defining your core beans, and import that in a client-specific XML file, which also redefines some of those beans. It's a bit fragile, though, since there's no mechanism to specifically say "this bean definition is an override".
I've found that the cleanest way to handle this is using the new #Bean-syntax introduced in Spring 3. Rather than defining beans as XML, you define them in Java. So your core beans would be defined in one #Bean-annotated class, and your client configs would subclass that, and override the appropriate beans. This allows you to use standard java #Override annotations, explicitly indicating that a given bean definition is being overridden.

Resources