#Autowired annotations behavior in Spring 3 - spring

I wanted to understand how exactly the #Autowired annotation works.
import com.test.WorkFlowDAO;
public class ServiceCentralBOImpl implements IServiceCentralBO
{
/**
* Logger for logging functionality.
*/
private static final Log log = LogFactory.getLog(ServiceCentralBOImpl.class);
#Autowired
private WorkFlowDAO workFlowDAO;
.
.
.
}
and the bean is declared in my Spring applicationContext.xml file:
<bean id="workflowDAO" class="com.test.WorkFlowDAO">
</bean>
Upon closer inspection you can see the two IDs in the Java class and the context XML file are different.
workFlowDAO and
workflowDAO
[The letter 'f' is different in the two IDs]
Since my application runs just fine even with this configuration; I wanted to know,
how does #Autowired annotation work so that it does not complain when the bean IDs do not match exactly.
In case of simple bean usage; Spring would have complained of mismatching bean names.
I am running a J2EE application with Spring 3.0.5 on Websphere App Server 7.0
Let me know if any more information is required.

#Autowired matches the beans by type. The ID is not considered.
If you declare another bean of the same type in your XML configuration, Spring would complain about not being able to determine the correct bean.
If you want to use IDs together with #Autowired you can do so by utilizing #Qualifier although #Resource is recommended in this case.
Find some more info on that topic here.

Completely agree with the first comment.
If you want your beans to be autowired by name, you may consider using #Qualifier("givenName").
See for all details:
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html

Related

Spring Bean and Autowire to datasource

Noob to Spring. I have 2 files:
foo-servlet.xml which has the following statement:
<bean id:"DAO" class="a.b.data.MyDAO"/>
fooController.java has the following:
#Controller
public class FooController{
#Autowired
private FooDAO fooDAO;
public void setFooDAO (FooDAO fooDAO){ this.fooDAO = fooDAO;}
My question: Is Spring actually replacing / injecting the definition of DAO in the servlet into my FooDAO? I'm trying to understand the 'tie-in' between the bean and how Spring know to substitute that file for my FooDAO in the controller.
Oh, and there is no mention of #Repository or #Component anywhere in this example code...
The XML looks kind of corrupted. I think it needs to be id=DAO
As far as i know: Autowiring is either done via the type or the name and the type.
So when MyDAO implements FooDao your bean will be considered for Autowiring.
But this is just a guess. The code of the Daos and the rest of the configuration would be helpful to give a correct answer to this question.
Understanding Spring #Autowired usage
This might answer your question as well.

spring autowired aop circular dependency

I'm using java config with #ComponentScanin order to initialize my beans
and #EnableAspectJAutoProxy(proxyTargetClass=true)to use cglib proxies.
In this project we have a lots of generated services autowired between them using #Autowired. It works pretty well.
But, for some of these services I've added #Async (I've also added #EnableAsync(proxyTargetClass = true)on my #Configurationclass).
After that, I'm getting:
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'ConversationUserLocalService': Bean with name 'ConversationUserLocalService' has been injected into other beans [ConversationUserHistoryLocalService] i
n its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'a
llowEagerInit' flag turned off, for example.
I guess this is because Spring is injecting the service with #Asyncmethod BEFORE AOP creates the proxy.
Could this be the problem?
How I should fix it?
In order to try to clarify my problem, let's say I have:
#Service A, B & C;
A has autowired B & C, B has autowired A & C, C has autowired A & B;
C has a method marked as #Async.
When Spring initialize applicationContext, it tries to initialize A, but needs B & C, so it initializes them. But after all, AOP tries to make a proxy of C (because #Async) and then it detects that autowired C into B and A is not the same as proxy of C so it fails.
I hope this can explain a little more what is happening.
Finally I sorted it out using #Lazyon services (with methods annotated with #Async), and also, where they were autowired.
This way I guess Spring only initialize and autowires those services when they're required instead of on application context initialization.
I have same issue and I solved this issue:
I identified which #Autowired property is reason for circular dependency.
Eg:
#Autowired
private TestService testService;
(Tips to identified just try to comment and find out which property is reason to break the application)
Once identified just use #Lazy on top of this #Autowired variable.
Eg :
#Lazy
#Autowired
private TestService testService;
And Application worked smoothly.
AsyncConfigurer configuration classes get initialized early in the application context bootstrap. If you need any dependencies on other beans there, make sure to declare them #Lazy as far as possible in order to let them go through other post-processors as well.
Reference JavaDoc: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/EnableAsync.html
I managed to fix a similar issue by adding #Qualifier together with #Autowire, for example:
#Autowired
#Qualifier("publisher")
private Publisher publisher;

How to override a Spring #Autowire annotation and set a field to null?

I am a Spring neophyte who is working on a large Spring-based project that has extensive coupling between Spring beans. I am trying to write some integration tests that exercise subsets of the total application functionality. To do so, I'd like to override some of the autowiring.
For example, suppose I have a class
public class MyDataServiceImpl implements MyDataService {
#Qualifier("notNeededForMyDataServiceTest")
#Autowired
private NotNeededForMyDataServiceTest notNeededForMyDataServiceTest;
//...
}
and a context file with:
<bean id="myDataService"
class="MyDataServiceImpl">
</bean>
In my test, I have no need to use the notNeededForMyDataServiceTest field. Is there some way I can override the #Autowired annotation and set notNeededForMyDataServiceTest to null, perhaps in the XML file? I don't want to modify any of the Java classes, but I do want to avoid the (problematic) configuration of notNeededForMyDataServiceTest.
I tried doing:
<bean id="myDataService"
class="MyDataServiceImpl">
<property name="notNeededForMyDataServiceTest"><null/></property>
</bean>
That doesn't work. IntelliJ informs me "Cannot resolve property 'notNeededForMyDataServiceTest'", apparently because there are no getters and setters for that field.
I'm using Spring Framework 3.1.3.
The following configuration should work, I took the liberty of mixing in Java configuration
#Configuration
//This will load your beans from whichever xml file you are using
#ImportResource("classpath:/path/beans.xml")
public class TestConfigLoader{
// This will declare the unused bean and inject MyDataServiceImpl with null.
public #Bean(name="notNeededForMyDataServiceTest") NotNeededForMyDataServiceTest getNotNeededForMyDataServiceTest(){
return null;
}
... any other configuration beans if required.
}
And annotate your test class like so:
// In your test class applicationContext will be loaded from TestConfigLoader
#ContextConfiguration(classes = {TestConfigLoader.class})
public class MyTest {
// class body...
}
These could help:
Context configuration with annotated classes
Testing with #Configuration Classes and Profiles
Spring TestContext Framework
and profiles:
beans profile="..."
Introducing #Profile
You could create different beans definition in the XML configuration and then activate them using the -Dspring.profiles.active="profile1,profile2" env.
You're using the #Autowired mechanism wrong. The qualifier is not a property that you need to set. That's actually the name of a bean, so that the container will be able to choose one particular instance in case multiple beans of the same type are defined in the same context.
So the container will look for a bean of type NotNeededForMyDataServiceTest and the name (which would actually be the bean id in XML): notNeededForMyDataServiceTest.
What I think you want is to instruct the container to not inject anything in that field if no bean of type NotNeededForMyDataServiceTest is defined in the application context. That could be achieved simply by setting the required attribute of the annotation to false:
#Autowired(required = false)
NotNeededForMyDataServiceTest someOptionalDependency;
The only drawback of this approach would be that the container will never complain at runtime if there's nothing to inject in that field (and perhaps you would want this sanity check when your code runs in production).
If you don't want to make that dependency optional (or you can't edit that code for some reason), you'll need to provide a mock / null value for that field by setting that explicitly in your context. One option to do that would be to use Java configuration instead of XML (like in #Abe's answer) and another approach would be to make use of a factory bean which returns null (like in this question).

How to make Spring #autowired annotation to pick a certain type without using #Qualifier?

Is there a way to specify the default type for Spring #autowired annotation? For example, I have bean ValidatorA and bean ValidatorB that extends ValidatorA.
The ValidatorA is used in some other places and is injected using #autowired.
Is there a way to force Spring to inject ValidatorB instead of ValidatorA without changing the existing code?
The only solution I found at How to override the behavior of Spring #Autowired suggests to exclude ValidatorA from the context.
Is there any other way?
For example, with Guice I would just bind the ValidatorA.class to ValidatorB.class and that will do exactly what I need.
I have no problem to add #Qualifier to ValidatorB but ValidatorA should stay unchanged.
Guice provides ability to define "Providers", is there something similar in Spring? Maybe with #Configuration annotation?
I think you could use primary indicator there. If your bean is defined through annotation, add #Primary to ValidatorB definition. If you are using xml config add primary="true" to <bean> definition.
Is there a way to force Spring to inject ValidatorB instead of ValidatorA without changing the existing code?
Without changing the code, I doubt it very much. You could change the app context or alter the code something like this :
#Component
#Qualifier("B")
public class ValidatorB extends ValidatorA {
}
and then inject like so (there are other syntactic options as well)
#Resource
#Qualifier("B")
private ValidatorA validatorB;

Why is there a need to specify the class in both the xml file and in the getBean() method in Spring

This might be an obvious but I'm having a hard time understanding why we need to define the class of a bean in two places....
From the spring reference manual...
...
<bean id="petStore"
class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="itemDao" ref="itemDao"/>
<!-- additional collaborators and configuration for this bean go here -->
</bean>
// retrieve configured instance
PetStoreServiceImpl service = context.getBean("petStore", PetStoreServiceImpl.class);
Shouldn't the xml fine be enough for the container to know the class of petStore?
You can use the following method:
context.getBean("petStore")
However, as this returns a java.lang.Object, you'd still need to have a cast:
PetStoreServiceImpl petstore = (PetStoreServiceImpl)context.getBean("petStore");
However, this could lead to problems if your "petStore" bean is not actually a PetStoreServiceImpl, and to avoid casts (which since the advent of Generics are being seen as a bit dirty), you can use the above method to infer the type (and let's spring check whether the bean you're expecting is really of the right class, so hence you've got:
PetStoreServiceImpl service = context.getBean("petStore", PetStoreServiceImpl.class);
Hope that helps.
EDIT:
Personally, I would avoid calling context.getBean() to lookup methods as it goes against the idea of dependency injection. Really, the component that uses the petstore bean should have a property, which can then be injected with the correct component.
private PetStoreService petStoreService;
// setter omitted for brevity
public void someotherMethod() {
// no need for calling getBean()
petStoreService.somePetstoreMethod();
}
Then you can hook up the beans in the application context:
You could also do away with the configuration via XML and use annotation to wire up your beans:
#Autowired
private PetStoreService petStoreService;
As long as you've got
in your spring context, the "petStore" bean defined in your application context will automatically be injected. If you've got more than one bean with the type "PetStoreService", then you'd need to add a qualifier:
#Autowired
#Qualifier("petStore")
private PetStoreService petStoreService;
There's no requirement to specify the class in the getBean() method. It's just a question of safety. Note there's also a getBean() that takes only a class so that you can just look up beans by type instead of needing to know the name.

Resources