I used #Autowired hundreds of time but today I don't get it, neither #Autowired nor #Inject work in a new project I just created, I get the famous error
Invalid property 'jdbcTemplate' of bean class [com.xxx.SomeDAO]: Bean
property 'jdbcTemplate' is not writable or has an invalid setter
method. Does the parameter type of the setter match the return type of the getter?
When I add a setter for jdbcTemplate in SomeDAO, it works...
applicationContext.xml:
...
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="com.xxx.SomeDAO" class="com.xxx.SomeDAO">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
...
SomeDAO.java:
import org.springframework.jdbc.core.JdbcTemplate;
import javax.inject.Inject;
//import org.springframework.beans.factory.annotation.Autowired;
public class SomeDAO {
#Inject // Doesn't work
//#Autowired // Doesn't work either
private JdbcTemplate jdbcTemplate;
...
/* Works if I add this setter
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}*/
}
What could prevent the injection through the annotation? Thanks!
It is not possible to use field-injection when the bean is created with the XML-context the way you have provided it. Your class is not part of any component-scanning and therefore the annotations does not kick in. Therefore, I can see at least the following options:
1. Use a setter as per your example and remove the #Inject
This is the simplest approach since you got the code and XML prepared. However, this means that your DAO must expose an unnecessary setter-method.
2. Use a constructor that sets your jdbcTemplate field
This is according to me a better alternative but it means that you need to rewrite the XML like this:
<bean id="com.xxx.SomeDAO" class="com.xxx.SomeDAO">
<constructor-arg ref="jdbcTemplate"/>
</bean>
And, your constructor like this:
public class SomeDAO {
private final JdbcTemplate jdbcTemplate;
public SomeDAO(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
3. Add component-scanning and use #Autowired (or #Inject)
I think that this is the best approach if you fully want to utilize the beauty of Spring's dependency injection capabilities. Add the following to your XML-context:
<context:component-scan base-package="com.xxx"/>
And then the code you previously provided should work. However, you should probably consider avoiding field-injection in favour of constructor-injection. The opinions differ on this matter but I find the code harder to test when field-injection is used.
Constructor injection looks like this:
// The component scanner will find this annotation and create
// the bean (and inject the dependencies)
#Component
public class SomeDAO {
private final JdbcTemplate jdbcTemplate;
#Autowired // enables constructor-injection
public SomeDAO(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
I personally prefer alternative #3 since it is clean, Java-based (practically no XML required) which also means that it is refactoring friendly, there is no field magic happening and the constructor-based approach makes the code testable and does not expose any unnecessary setter-methods.
A good starting point to learn more about this is the excellent Spring Documentation. There you can find a great explanation for all of the above!
Related
I have a prototype Bean which is instantiated by singleton bean with a Provider:
#Component
#Scope("prototype")
class MyPrototype {}
#Component
class MySingleton {
#Autowired
javax.inject.Provider<MyPrototype> prototypeFactory;
}
This works fine, but our company rules state that #Autowired is not allowed; the common pattern is #Resource(SingletonBeanClass.BEAN_ID).
Is it possible to annotate the Provider this way so the Spring lookup can create it?
I'm aware I can add a factory method with #Lookup, or a singleton factory bean, but I prefer the Provider.
EDIT:
I didn't get it to work this way and in the end had to edit spring.xml; see below for details.
As you have an XML configuration file, you can configure it via XML in the following way:
<bean id="myPrototype" class="some.package.MyPrototype" scope="prototype" />
<bean id="mySingleton" class="some.package.MySingleton">
<lookup-method name="getPrototypeFactory" bean="myPrototype "/>
</bean>
In this way, you have to access to the myPrototype with the getPrototypeFactory() and not directly to the property. You can even remove the annotations on those 2 classes.
For any extra details, you can look at the following blog post Injecting a prototype bean into a singleton bean
For reference, if someone comes across this via Google:
I ended up needing to declare it in the spring.xml. I tried #Lookup, but even that didn't work due to the prototype-bean referencing yet another prototype-bean.
This is how it was recommended here,
but it does not work:
#Component("proto1")
#Scope("prototype")
class MyPrototypeBean1 {
#Lookup(value="proto2")
protected MyPrototypeBean2 createBean2() { return null; }
}
#Component("proto2")
#Scope("prototype")
class MyPrototypeBean2 {
}
#Component("singleton")
class MySingleton {
#Lookup(value="proto1")
protected MyPrototypeBean1 createBean1() { return null; }
}
This results in the error message "Cannot apply #Lookup to beans without corresponding bean definition" when trying to create "innerBean...".
I assume it is due to "lookup methods cannot get replaced on beans returned from factory methods where we can't dynamically provide a subclass for them" as is quoted in the link above.
So what I ended up doing in the spring.xml:
<bean name="proto2" class="my.package.PrototypeBean2" />
<bean name="proto1" class="my.package.PrototypeBean1" >
<lookup-method name="createBean2" bean="proto2" />
</bean>
<bean name="singleton" class="my.package.SingletonBean" >
<lookup-method name="createBean1" bean="proto1" />
</bean>
And this works.
For the unit tests, I had to subclass the respective classes:
class SingletonUnitTest {
#Mock
MyPrototypeBean1 bean1;
#InjectMocks
DummySingleton sut;
#Before public void setBean1() {
sut.bean = bean1;
}
static class DummySingletonBean extends MySingeton {
MyPrototypeBean1 bean;
protected MyPrototypeBean1 createBean1() {
return bean;
}
}
}
Spring Version: 3.2.4.RELEASE and 3.2.9.RELEASE
Mockito Version: 1.8.5
I've been trying to introduce H2 tests to an old project for integration testing, and I've been running into a few issues. Due to the way transactions were propagating, I needed to mock out an autowired class. I've done this before, but I'm now running into severe problems. The following error message is being thrown when initialising the test:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.stuff.XMLITCase': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'TheProcessor' must be of type [com.stuff.XMLBatchFileProcessor], but was actually of type [$Proxy118]
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:307)
Diving into this a bit deeper, it turns out the the bean is in-fact a proxy. If we check the AbstractBeanFactory (round line 239), we can see the proxy:
sharedInstance = {$Proxy117#7035} "com.stuff.XMLBatchFileProcessor#66c540d0"
h = {org.springframework.aop.framework.JdkDynamicAopProxy#7039}
The only problem is, I've no clue where this is coming from. I've gone over the config and dependencies, and can't find anywhere that this should be happening.
Project Setup
Unfortunately I can't give a sample project for this, but I'll go over my test configuration. I have a root class that I extend for the tests:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:/spring/spring-test-context.xml"})
#TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public abstract class AbstractIntegrationTest {
}
This simply loads in some spring config and rolls back the transactions after each test.
The spring config is nothing strange either, though there is one difference between my other module and this one. This is the transaction manager and session factory:
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="hibernateSessionFactory"/>
</bean>
<bean id="hibernateSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
...
</bean>
In my other module, I'm using an entityManagerFactory, and a different transaction manager:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
...
</bean>
The actually class has some autowired fields, and the usual #Service annotation:
#Service(value = "TheProcessor")
public final class XMLBatchFileProcessor extends BatchFileProcessor implements IXMLBatchProcessor {
Finally, the actual test is as follows:
public class XMLITCase extends AbstractIntegrationTest {
#Resource(name = "TheProcessor")
#InjectMocks
private XMLBatchFileProcessor xmlProcessor;
#Mock
private ProcessHelper processHelper;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() throws Exception {
Assert.assertNotNull(xmlProcessor);
}
}
If I replace the XMLBatchFileProcessor with the interface and autowire the field, then there aren't any problems compiling. Mockito, however, never replaces the autowired bean with the mocked object. If it did, then I wouldn't bother with the #Resource annotations and naming the service, thus avoiding the Proxy issue.
Any assistance on this would be appreciate. I'll be focusing on the session factory and the differences there, but it's quite possible that I'm missing something else entirely.
EDIT
Going on Sotirios' comment, I had another look this morning and indeed had missed that the xmlProcessor has a #Transactional annotation, thus meaning that the class needs to be proxied. If I remove the final declaration and let CGLib enhance it, then Mockito does replace the bean when initMocks(this) this called. When a method is called, however, CGLib seems to replace all the beans with Spring enhanced versions, hence overwriting the Mockito version.
What is the correct way to use both Mockito and Spring in an integration test for a class with #Transactional annotations?
Alright, once I realised that the class was being proxied due to the #Transactional annotation, the solution to the problem became clearer. What I needed to do was unwrap the proxy, and set the mocked object directly on that:
So in my AbstractIntegrationTest:
/**
* Checks if the given object is a proxy, and unwraps it if it is.
*
* #param bean The object to check
* #return The unwrapped object that was proxied, else the object
* #throws Exception
*/
public final Object unwrapProxy(Object bean) throws Exception {
if (AopUtils.isAopProxy(bean) && bean instanceof Advised) {
Advised advised = (Advised) bean;
bean = advised.getTargetSource().getTarget();
}
return bean;
}
Then in my #Before:
#Mock
private ProcessHelper processHelper;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
IXMLBatchProcessor iXMLBatchProcessor = (IXMLBatchProcessor) unwrapProxy(xmlProcessor);
ReflectionTestUtils.setField(iXMLBatchProcessor , "processHelper", processHelper);
}
This left all the #Autowired classes intact, while injecting the correct mocked object.
you can optimise the accepted response using the class AopTestUtils that provides the methods:
getTargetObject to unwrap the top-level proxy if exists
getUltimateTargetObject to unwrap all levels of proxies if they
exist
I am mostly using #Autowired and #Component annotations in my project. However, I am going to use DataSource class for database actions.
So, I use this is in my dispatcher-servlet.xml :
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/market"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</bean>
In my dao class, My setter for the dataSource is :
#Autowired
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
this.jdbcTemplateObject = new JdbcTemplate(dataSource);
}
However this is not doing the trick. My jdbcTemplateObject is null.
If I dont use "context:component scan ..." and use classical spring beans instead, without utilizing #Autowired annotation, all works good.
I can use my database. However, I dont want to declare all the beans one by one in my xml file. As the project grows, it is not going to be practical. How can I solve this problem ? Is it possible to declare dataSource in my dispatcher-servlet.xml as component, so #Autowired works on dataSource ?
When you use #Autowired on fields Spring will look for dependencies and inject them right there there is no point if setter method here.
You do not need to worry about how spring is going to inject the dependency. It will take care of complete life cycle.
For more on Spring's Dependecy Injection visit this link.
You have annotated the field with #Autowired which tells spring to inject the dependency directly into the field. If you really want to use the setter annotate the setter with #Autowired instead of the field.
#Autowired
public void setDataSource(DataSource ds) { ... }
However I strongly suggest to not create a JdbcTemplate for each bean that needs one (it is quite heavy to create). The JdbcTemplate is a thread-safe object, once constructed. So instead of creating a new one for each bean that needs one (in the setDataSource method) just create a single JdbcTemplateand inject that.
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
Then in your dao.
#Autowired
private JdbcTemplate jdbcTemplate;
Or what I like to do..
private final JdbcTemplate jdbcTemplate;
#Autowired
public YourRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate=jdbcTemplate;
}
This way you cannot construct an illegal object, whereas with setter based injection you could. While maintaining the possibility to inject one for testing purposes.
Another note, the DriverManagerDataSource is nice for testing but not for production usage, for that use a real connection pool like HikariCP or Tomcat JDBC.
I need to wire external lib class to my bean,in order to use it as singleton.
.xml config:
<bean id="myBean" class="com.my.MyBean">
<property name="someLib" value="com.ExternalBean" />
</bean>
java bean:
#Service
public class MyBean {
#Autowired
private ExternalBean externalBean;
public void setExternalBean(ExternalBean externalBean) {
this.externalBean = externalBean;
}
Further I use wired variable externalBean in public method ,in order not to instantiate it in every method call.
Problem is it null.
Do I wire bean correctly?What is mistake.
You have to define the external class as a bean in order to make #Autowired work.
<bean id="externalBean" class="some.external.package.ExternalBean">
</bean>
<bean id="myBean" class="com.my.MyBean">
</bean>
Also, if you use #Autowired you don't need the setter for it.
loodakrawa is right. A second thing that can cause a problem is, that you have a xml bean declaration for myBean and additional annotated the bean with #Service. I guess this will cause trouble as soon as use enable component scan.
I think that the better ide ais to use context path scan:
<context:component-scan base-package="some.external.package">
</context:component-scan>
Make sure that all these classes are within the package. Then mark both classes with one of the Annotations (#Repository, #Service, #Component).
One of the benefits, no setter required.
P.S: If you re using scan base you don't need to declare class as bean, annotations are enough
Maybe, because of my wrong English, I couldn't understand the benefit of using #Autowired annotation.
According to the tutorial we can simplify the first(I.) case to second case(II.) by means of #Autowired.
My question is, what is the meaning of the #Autowired ? Because it doesnt tell any more, since without using #Autowired the compiler can figure out that "EmpDao emDao" and "EmpManager" are closely related according the declaration.
code cited from here
I.
<bean id="empDao" class="EmpDao" />
<bean id="empManager" class="EmpManager">
<property name="empDao" ref="empDao" />
</bean>
public class EmpManager {
private EmpDao empDao;
public EmpDao getEmpDao() {
return empDao;
}
public void setEmpDao(EmpDao empDao) {
this.empDao = empDao;
}
...
}
II.
<context:annotation-config />
<bean id="empManager" class="autowiredexample.EmpManager" />
<bean id="empDao" class="autowiredexample.EmpDao" />
import org.springframework.beans.factory.annotation.Autowired;
public class EmpManager {
#Autowired
private EmpDao empDao;
}
#Autowired is spring-specific. #Inject is the standard equivallent. It is an annotation that tells the context (spring, or in the case of #Inject - any DI framework) to try to set an object into that field.
The compiler has nothing to do with this - it is the DI framework (spring) that instantiates your objects at runtime, and then sets their dependencies at the points you have specified - either via XML or via an annotation.
I agree it is a possible scenario for a DI framework to try to inject dependencies into all fields, even if they are not annotated. (And if you want to exclude a particular field, to annotate it). But they chose the other strategy (configuration-over-convention). By the way:
if using xml config and choose some form of autowiring, the dependencies of the bean will be automatically autowired without the need to specify anything
you can specify per-context autowiring settings.
When the server bootstraps itself. It finds
<context:annotation-config />
in the application context and then goes through the classes defined in the contexts. If there are any beans that are autowired, it injects that into the class by referring the context file.
Basically, it promotes convention over configuration. That's what most frameworks do these days to reduce the development time.
the #Autowired Spring annotation tells Spring to for a bean named 'empDao' and inject it into the EmpManager class, without you having to add the empDao bean as a property in your spring config file.
#Autowired tells Spring to find a bean of the declared type and wire in that bean, rather than requiring an explicit lookup by bean name. It can, under certain circumstances, make configuring applications easier if you only have one implementation of your types in a given Spring context.