Autowiring Unmanaged Beans Annotated With #Component - spring

I want to use #AutoWired to inject a non-managed bean configured with #Component into a managed bean. I'm pretty sure I have the configuration right, but for some reason I keep getting the exception:
No unique bean of type [foo.Baz] is defined: Unsatisfied dependency of type [class foo.Baz]: expected at least 1 matching bean
Based on the error, I'm guessing it's not able to find the Baz class, but I'm not sure why. It's my understanding that the context:spring-configured element in the XML config was supposed to allow me to do this. I also made sure to include the appropriate jar files (spring-weaving.jar and aspectjweaver.jar).
Here's a simple example of my set up.
My XML config:
<beans ...>
...
<context:annotation-config/>
<context:spring-configured/>
<context:component-scan base-package="foo"/>
<bean id="bar" class="foo.Bar"/>
...
</beans>
I have one managed bean:
package foo;
public class Bar {
#Autowired
private Baz baz;
public void setBaz(Baz baz) {
this.baz = baz;
}
...
}
And one unmanaged bean:
package foo;
#Component
public class Baz {
...
}
Is there something I'm missing?
EDIT: The log lists the beans its instantiating, and foo.Baz isn't one of them. I don't know why it's not picking up the #Component annotated class.

Because Bar is configured with xml, it can only be configured with xml. i.e. you can't mix them. So that "#Autowired" annotation on Baz is not getting picked up (none of the annotations would be). It is only when you add the spring annotation at class level that spring will listen to any of the other annotations.
What you'll need to do is in the xml configure the bean to be autowired by type, add a setter for that type and you'll achieve the desired behaviour.
<bean id="bar" class="foo.Bar" autowire="byType"/>
One more thing, when you annotate a bean with #Component it is a spring managed bean. Just because it is not created with xml does not mean it is unmanaged. An unmanaged bean is one you don't get from spring.
Bar and Baz are both spring managed. It is the mechanism you've chosen to define them that differs.

The previous response is not correct, in one aspect. You can autowire beans that are otherwise configured with xml.
From section 3.4.5 in http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html:
When using XML-based configuration metadata[2], you specify autowire mode for a bean definition with the autowire attribute of the element. The autowiring functionality has five modes. You specify autowiring per bean and thus can choose which ones to autowire.
You can autowire by name, type and constructor. There is a crude example of this here: http://www.java2s.com/Code/Java/Spring/AutoWiring.htm

The error is due to the sequence of beans defined in your XML config file.
As on your XML file, bean for bar is created first and then their dependent beans due to which #Autowired is not able to find baz.
You must first declare bean for baz and then for bar.

Related

What is the difference between "constructor based injection" and " autowire by constructor mode" in Spring

I know and understand constructor based injection. But, the autowiring modes confuse me.
1) I have read that default mode for autowiring is 'no autowiring' i.e. We have to manually set the properties in xml file. But, isn't xml based configuration a type of autowiring? How can it be considered 'No autowiring'?
2) Other modes for autowiring are i) byName ii) byType iii)constructor iv) auto-detect. Am i correct to assume the following:
a) When using xml configuration based autowiring, the default mode is 'byName'(i.e. I have to keep the name of property reference the same as the name of the bean which is being used as a property.)
b) When using Annotations, default mode is 'byType'( Regardless of the place the #Autowired keyword is placed i.e on the setter, on the constructor or on the property, it will search the type of the property being autowried)
3) What is the difference between constructor based injection and 'constructor' mode of autowiring?(I have read that constructor mode means it applies byType mode on all the constructor arguments, but how is it different from placing #Autowired keyword on the constructor)
4) I know that to enable autowired mode byName in annotations, in the bean definition in the xml file, I have to use " autowire = 'byName' ". But, suppose I am using Annotations only config( using #Component, and no bean definitions in the xml ), and I want to use byName autowire mode, then what is the way of doing that?
I think you are a bit confused. First, you need to understand dependency injection (see here). There is ton of info about DI but in short, it means some third party (e.g spring IOC) passes the dependencies to the objects rather than the objects to create/obtain the references themselves. This could happen either through constructor or setter. For instance, consider constructor DI
class B{
}
class A{
private B b;
public A(B b){
this.b = b;
}
}
Some third party will inject an instance of class B into A rather class A create a reference to B itself. Very often you would use an interface so class A wouldn't even know what object will be injected into it.
Now in Spring there are different ways to configure these associations between the objects (the example above). You can either use XML, Java Config or Autowiring. They are independent but do the same stuff.
In both XML and JAVA config you need to configure the dependencies explicitly - either in xml file or having a #Configuration class for the JAVA Config and annotating the beans with #Bean. The autowiring is different. There you create simple POJOs which you annotate with #Component, #Controller, #Service or #Repository. They will be automatically registered as beans via component scanning. With autowiring you don't need to explicitly configure the dependencies in XML file or JAVA Config class. You can do it in code directly. For instance, if we have to compare java config vs autowiring using the previous example
Java Config (explicit config in a config class)
#Bean
public A getA(){
return new A(new B());
}
Autowiring (implicit - done in code)
#Component
class B{
}
#Component
class A{
private B b;
#Autowired
public A(B b){
this.b = b;
}
}
In the latter we autowire class B into class A (they both will be registered as beans due to #Component annotation) without having explicitly defined this association in an xml file or java config class. I hope it makes sense.
If you have to specify the bean names in the xml, its not happening automatically, hence its not autowiring.
With autowiring spring will figure out what bean to inject even though it may not be explicitly written.
When using xml configuration based autowiring, the default mode is 'byName'
When using Annotations, the ordering that happens depends on the annotation used as there are a few that can be used. #Autowire #Resource #Inject.
When using #Component, the default wiring is of type. The method below will resolve on any autowiring needs for a Service object.
#Bean
public Service getMyService(){
return new Service();
}
If there are multiple #Bean methods that return a Service you will get an error.
If you wanted to do wire via name while using #Component you would add the #Qualifier("nameToUse") annotation to the variable. It would find an #Bean annotated method called getNameToUse().
#Autowired
#Qualifier("nameToUse")
private Service myService;

Beginner confusion about autowiring in Spring

All:
I just begin the Spring study, there is one concept confused me so much: The Autowiring.
The question I need to be clear is:
What kind of thing can be autowired? Is it only other beans?
If I define a class Bar:
public class Bar {
#Autowired
public String name;
}
I am thinking what if I put a #Autowired annotation to a member variable like String name; and in bean config XML I wrote:
<bean id="bar" class="com.Bar">
<property name="name" value="Bar" />
</bean>
So many ways to do same thing in Spring confused me so much. ToT.
Is there any good trick to clearly remember and tell diff among different ways?
Thanks
Yes, You can only #Autowired Beans. #Autowired is the way of using Dependency Injection in Spring. It is provided for Beans - components wrote once and used many times. There's no sense using DI on String property and I think You get Exception.
You can't autowire in a String value like you have done.
By writing your XML bean declaration, what you have done is created a singleton instance of Bar with the name field set to the value of 'Bar'.
If you wanted to then use this Bar class elsewhere in your application (say in a class called Foo) you could do this:
public class Foo {
#Autowired
private Bar bar;
}
Spring would then inject your instance of Bar into your Foo class.
However because Bar is a singleton by default, no matter how many instances of Bar you autowired into different classes, you would have the same instance of Bar in all of them. So if you try and modify name in one class, it will change for all the other classes.
As a general rule of thumb, if your class has any mutable data (data that will be changed and updated), then your class is not something that you should be declaring for autowiring (because there will only ever be one instance of it inside your Spring application). It works better for things like DAO's and service classes. In answer to your first question, yes you can only autowire instances of classes (beans).
If you need to get a String/Integer/Long/Array/Mutable Data Type value from somewhere, configure a properties file, and read up how to use the org.springframework.beans.factory.config.PropertyPlaceholderConfigurer class with the #Value annotation.

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).

Spring #Autowired and bean declaration in applicationContext.xml

Hi I am relatively new to spring. Am using Annotations.
My doubt begin I have a class
as
public class MyClassA{
#Autowired
private MyClassB variableClassB;
// more code here
.
.
.
in my applicationContext.xml
<context:component-scan base-package="package containing MyClassB" />
My question being do I need to add bean declaration in applicationContext.xml as follows
<bean id="classB" class="com.MyClassB"
or is it sufficient to have #Autowired annotation
No it is not.
If your MyClassB is annotated with annotations like #Component, #Service, #Repository or #Controller the component scan will create a bean for the class in the bean factory.
If you are not using any of these annotations then, you need to create a bean manually as you have given
Ex:
#Component
public class MyClassB{
}
If you have Annotation #Component on MyClassB, it's no need to add <bean id="classB" class="com.MyClassB" in applicationContext.xml. Otherwise, needed.
The whole purpose of the #Autowired annotation is just to avoid explicitly mentioning the bean in the xml file. Doing
<context:component-scan base-package="package containing MyClassB" />
checks the package and searches for the annotations #Controller, #Service, #Repository etc and makes the bean itself.
The #Autowired annotation lets you avoid having to explicitly state the need for MyClassB in the XML declaration of MyClassA, but it does not mean that the MyClassB bean is created automatically. If you don't want to have MyClassB appearing in the XML at all, you need to do a context:component-scan to find the #Bean (and derived) annotations. (The scan is fairly expensive, so you need to ask for it explicitly.)

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