Spring injected resource is always null - java

ISSUE:
I am trying to inject a service into a bean but the service instance is always null.
BACKGROUND:
I have two beans one called from the other. This is how they are defined in XML config:
<context:annotation-config />
<bean class="com.test.MyBeanImpl" name="myBean"/>
<bean id="myService" class="com.test.MyServiceImpl" />
and the beans are implemented like so:
MyServiceImpl.java
class MyServiceImpl implements MyService {
public void getString() {
return "Hello World";
}
}
MyBeanImpl.java
#Component
class MyBeanImpl implements MyBean, SomeOtherBean1, SomeOtherBean2 {
#Resource(name="myBean")
private MyService myService;
public MyBeanImpl() {}
}
QUESTIONS:
Is there some reason related to the fact that my bean implements 3 interfaces that is preventing the Service being injected? If not what other factors could be effecting it?

as you are using annotations Just mark your service class with #Service annotation and use #Autowired annotation to get the instance of your service class
MyServiceImpl.java
package com.mypackage.service;
#Service
class MyServiceImpl implements MyService {
public void getString() {
return "Hello World";
}
}
MyBeanImpl.java
#Component
class MyBeanImpl implements MyBean, SomeOtherBean1, SomeOtherBean2 {
#Autowired
private MyService myService;
public MyBeanImpl() {}
}
also make sure you mention your package name in <context:component-scan /> element in your dispatcher file as
<context:annotation-config />
<context:component-scan base-package="com.mypackage" />
hope this will solve your problem

Make sure the bean you are injecting MyService into is a bean.
/* This must be a bean, either use #Component or place in configuration file */
#Component
public class SomeClass{
#Resource
private MyService myService;
}
Also make sure that within your configuration you have specified that the application uses annotation-based configuration using:
<context:annotation-config/>
Since your using multiple interfaces it may be best to qualify the bean with a name:
<bean class="com.test.MyBeanImpl" name="myBean" />
Then specify the name element on the #Resource annotation
#Resource(name="myBean")
private MyService myService;
Here is a Github Gist that explains these concepts.

Related

ConflictingBeanDefinitionException : Same class name, different package

I have a dao in one package:
package com.mypackage.dao;
#Repository
public class MyDao {
// some code here
}
I have another dao with same class name in a sub package:
package com.mypackage.one.dao;
#Repository
public class MyDao {
// some other code here
}
I have third class where I am trying to inject the bean using autowiring:
import com.mypackage.one.dao;
public class TestClass{
#Autowired
private MyDao myDao;
}
On deployment, I get the following error:
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'myDao' for bean class [com.mypackage.dao.MyDao] conflicts with existing, non-compatible bean definition of same name and class [com.mypackage.one.dao.MyDao]
My applicationContext.xml has:
<context:component-scan base-package="com.mypackage.dao"/>
<context:component-scan base-package="com.mypackage.one.dao"/>
I can not rename the classes as its a legacy application.
What is the solution for this ?
I tried using qualifier, but that is not working.
Added below line:
<bean id="oneMyDao" class="com.mypackage.one.dao.MyDao" />
And changed autowiring to:
#Autowired
#Qualifier("oneMyDao")
private MyDao myDao;
But it still throws the same error.
i think your mixing XML and Java bean configuration for same bean.
your code should be something like this
package com.mypackage.dao;
#Repository
#Qualifier("myDAOBasePackage")
public class MyDao
{
// some code here
}
package com.mypackage.one.dao;
#Repository
#Qualifier("myDAOSubPackage")
public class MyDao {
// some other code here
}
Ues this to inject
#Autowired
#Qualifier("myDAOBasePackage")
private MyDao myDao;
I think that the problem is in definition of beans. You have to give your beans different names.
Please, try to change annotations to #Repository("dao1") for the first dao and to #Repository("dao2") for the second dao. And then try to #Autowire bean using #Qualifier("dao1") or #Qualifier("dao2").
Also you should remove this line
<bean id="oneMyDao" class="com.mypackage.one.dao.MyDao" />
if you use #Repository annotation

Spring No matching bean of type, expected at least 1 bean

Getting error
No matching bean of type [foo.bar.service.AccountService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
my service:
public interface AccountService {
#Service
public class AccountServiceImpl implements AccountService {
So I should get the implementation
Where I am trying to get it :
public class CustomAuthentication implements AuthenticationProvider {
#Autowired
private AccountService accountService;
In my other class also doing same thing, but there it works.
#Controller
public class AccountController {
#Autowired
private AccountService accountService;
When I remove the those 2 lines from my CustomAuthentication, getting no errors.
configuration just incase:
<context:component-scan base-package="foo.bar" />
Only a spring managed object can Autowire another component/service/repository.
public class CustomAuthentication implements AuthenticationProvider need to be spring managed
like
#Controller
public class AccountController
Try annotating the CustomAuthenitcation with #Component
#Component
public class CustomAuthentication implements AuthenticationProvider
and let me know how CustomAuthentication Object is created. CustomAuthentication object should be a proxy obtained by requesting to Spring(ApplicationContext.getBean() or autowired in another bean).
UPDATE:
reason for this error is you have two config files. spring-servlet.xml and spring-security.xml. Beans defined in spring-security.xml is not able to find those in other.
so you should try something like <import resource="spring-servlet.xml"/> in spring-security.xml .
Please try <context:component-scan base-package="foo.bar.*" /> or <context:component-scan base-package="foo.bar.service" />. I believe it would work.
you have to write on AccountServiceImpl class #Service("accountService")

#Autowired issue with #Configurable servlet

I am trying to autowire a class into a WebSocketServlet in the following way:
#Configurable(autowire=Autowire.BY_TYPE)
public class MyServlet extends WebSocketServlet {
#Autowired
public MyClass field;
// etc...
}
Here's what my configuration looks like:
<context:annotation-config />
<context:component-scan base-package="org.*" />
<bean id="config" class="org.*.MyClass">
<!-- a bunch of properties -->
</bean>
Note that autowire used to work just fine as long as I was in a Spring #Controller. I had to step out of that because i don't know how to map a WebSocketsServlet to a method of the #Controller as you do with regular servlets.
Any idea what I might be missing?
In order to use #Configurable, you need to have these line in tour context:
<context:load-time-weaver aspectj-weaving="true"/>
<context:spring-configured/>
<context:annotation-config />
<context:component-scan base-package="org.*" />
In addition, I think you must reference spring-aspect in the Import-Library section of your Manifest.
I didn't succeed to make it work, there is a post on this in the Virgo forum at Eclipse.
If you succeed, let me know how ;)
Getting rid of #Configurable and doing the following in the servlet init method does the trick:
#Override
public void init() throws ServletException {
super.init();
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
As per the spring documentation
Externalized values may be looked up by injecting the Spring Environment into a #Configuration class using the #Autowired or the #Inject annotation:
#Configuration
public class AppConfig {
#Inject Environment env;
#Bean
public MyBean myBean() {
MyBean myBean = new MyBean();
myBean.setName(env.getProperty("bean.name"));
return myBean;
}
}

Anonymous Spring bean

How is an anonymous Spring bean useful?
There are two uses that i can think of straight of.
As an inner bean
<bean id="outer" class="foo.bar.A">
<property name="myProperty">
<bean class="foo.bar.B"/>
</property>
</bean>
As a configurer of static properties
public class ServiceUtils {
private static Service service;
private ServiceUtils() {}
...
public static void setService(Service service) {
this.service = service;
}
}
public class ServiceConfigurer {
private static Service service;
private ServiceUtils() {}
...
public void setService(Service service) {
ServiceUtils.setService(service);
}
}
Now that class can be configured like this.
<bean class="foo.bar.ServiceConfigurer">
<property name="service" ref="myService"/>
</bean>
In addition if there is a bean that is not depended upon by any other bean eg RmiServiceExporter or MessageListenerContainer then there is no need other than code clarity to give this bean a name.
There is several uses:
a bean injected inline as dependency in other bean
a bean that implements InitializingBean and DisposableBean, so his methods are called by IoC container
a bean implementing BeanClassLoaderAware, BeanFactoryPostProcessor and other call-back interfaces
On top of already provided answers (inner bean, life-managing interfaces, configurer of static properties) I would another one, which we use a lot. That is...
in combination with autowiring (by type). When you configure multiple objects of given type and you don't really care how they are called in XML.

Is it possible to use Spring 3 #Autowired annotation inside #Service?

I'm using class that is not called by my #Controller directly and when I try to use #Autowired propeprty in that class what is defined as #Service, property is null. But #Autowired with same markup will work inside #Controller.
Example code:
#Service
public class UsernameValidator implements Validator {
#Autowired private UserDao userDao;
// code here when used, userDao is always null
}
This should work perfectly fine, if you have the following in your applicationContext.xml:
<context:component-scan base-package="com.yourproject" />

Categories