Spring DI Unsatisfied dependency expressed - spring

applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.pomkine.pottyauth.domain.User"/>
<bean id="userdao" class="com.pomkine.pottyauth.persistance.GaeUserDao"/>
<bean id="userservice" class="com.pomkine.pottyauth.service.UserServiceImpl">
<constructor-arg ref="userdao"/>
</bean>
</beans>
Controller:
#Controller
public class RosterController {
private UserService userService;
#Inject
public RosterController(UserService userService){
this.userService=userService;
}
#RequestMapping(value = {"/userRoster"}, method = RequestMethod.GET)
public String showRosterPage(Map<String,Object> model){
model.put("users",userService.getAllUsers());
return "userRoster";
}
}
So I want UserService to be injected into my controller. But I'm getting the following exception:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'rosterController' defined in file [S:\Coding\Idea_workspace\pottyAuth\target\pottyAuth-1.0\WEB-INF\classes\com\pomkine\pottyauth\mvc\RosterController.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [com.pomkine.pottyauth.service.UserService]: : No matching bean of type [com.pomkine.pottyauth.service.UserService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
Here is my UserServiceImpl class:
public class UserServiceImpl implements UserService {
private UserDao dao;
public UserServiceImpl(UserDao dao){
this.dao=dao;
}
#Override
public User getUser(User user) {
return dao.getUser(user);
}
#Override
public void addUser(User user) {
dao.addUser(user);
}
#Override
public List getAllUsers() {
return dao.getAllUsers();
}
}
So I'm expecting Spring container to create UserServiceImlp bean and inject it into RosterController. But it seems that it cannot find UserServiceImpl bean.
What could be wrong?

UserServiceImpl is not implementing UserService
edit:
also I can't see
<context:component-scan base-package="">
Is this whole Spring configuration?

It means Spring couldnt find any bean of type UserService. Check your UserServiceImpl class.
Wondering why you are using both XML and annotation based approach to define beans? It will good if you stick to either of them.
EDIT:
Add #Component annotation to UserServiceImpl. So that Spring will come to know that it should create a object of UserServiceImpl
#Component
public class UserServiceImpl implements UserService
{
.....
}
and as #pawelccb have mentioned use
<context:component-scan base-package="your.base.package">
in Spring config file.
Check this link for details.

Related

#Autowired not working in spring Integration

In service implementation,with help of #Autowired i am injecting CollectInfo object in serviceImpl but i am getting NullPointerException.
package net.group.cts.service.serviceImpl;
#Service
public class EmployeeImpl implements EmployeeService {
#Autowired
CollectInfo info;
public void processData(){
info.getName();
}
}
package net.group.cts.model;
#Component
public class CollectInfo (){
String name;
public String getName(){
name = name + "Mr.";
return name;}
}
}
Xmlconfig.xml
<context:annotation-config/>
<context:component-scan base-package="net.group.cts"/>
<bean id="info" class="net.group.emp.model.CollectInfo "/>
You cannot inject a bean in a class if this class is not a Spring bean.
EmployeeImpl is not annotated with any Spring bean stereotype such as #Component or #Service.
Add one of them on EmployeeImpl and ensure that the two classes are located inside the package scanned by Spring <context:component-scan base-package="net.group.emp.service"/>
and it should be ok.
Besides, both annotating a bean with #Component :
#Component
public class CollectInfo (){...}
and configuring it in the Spring xml configuration :
<bean id="info" class="net.group.emp.model.CollectInfo "/>
is redundant. It will finally create two beans : one name collectInfo and another named info.
I advise you to favor annotation over xml configuration as it is possible (it is the very most of cases).

springboot+mybatis Exception : org.springframework.beans.factory.NoSuchBeanDefinitionException

I got the following exception:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [pers.panxin.springboot.demo.mapper.UserMapper] 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)}
Controller :
#Controller
public class HelloController {
#Autowired
private UserService userService;
#RequestMapping("/userList")
#ResponseBody
public String getAllUser(){
return "userList : "+userService.getAllUser().toString();//+list.toString();
}
}
Service:
public interface UserService {
public String getString();
public List<User> getAllUser();
}
ServiceImpl:
#Service
public class UserServiceImpl implements UserService {
#Autowired
private UserMapper userMapper;
#Override
public String getString() {
return "something else ... ";
}
#Override
public List<User> getAllUser() {
return userMapper.getAllUser();
}
}
Mapper Interface:
#Service
public interface UserMapper {
/**
* #return
*/
public List<User> getAllUser();
}
Application's main class
#ComponentScan
#EnableAutoConfiguration
#SpringBootApplication
public class ApplicationStarter {
public static void main(String[] args) {
SpringApplication.run(ApplicationStarter.class, args);
}
}
how the exception happened or something wrong in my code?
1.
I am not sure if you are using mybatis-spring library. If you are trying to integrate MyBatis with Spring you should use it. So make sure you have it as dependency.
2.
When you have mybatis-spring as dependency, just add this annotation to you configuration class:
#MapperScan("package.where.mappers.are.located")
It is because mybatis-spring has separate scanning for MyBatis mappers. Also you should remove #Service annotation from you mapper because if this separate mybatis-spring scanning.
EDIT:
As #Persia pointed out, you can use mybatis-spring-boot-starter library to pull mybatis-spring dependency into your Spring Boot project.
Get the same error today. Check the bean configuration org.mybatis.spring.mapper.MapperScannerConfigurer and org.mybatis.spring.SqlSessionFactoryBean. I mistyped the "basePackage" value for the former one, and the "typeAliasesPackage" value for the second one. After fixing the path, it works fine. Like this:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="package.path.to.your.model"/>
<property name="mapperLocations" value="classpath*:mappers/*.xml"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="package.path.to.your.dao"/>
</bean>
Add MappedTypes along with #MapperScan with
Code looks like the below
#MappedTypes({UserMapper.class})
#MapperScan("package.where.mappers.are.located")

Spring: Autowired is null in ejb class

I have the following situation:
#Controller
public class myController {
#Autowired
private IProxy service;
public ModelAndView init(HttpServletRequest request, HttpServletResponse response) throws Exception {
List<String> list = service.getName();
}
}
Then my Service is define as follow:
public interface IProxy {
public List<String> getName();
}
Proxy class is responsible for the lookup to the remote bean
#Service("service")
public class Proxy implements IProxy {
...
public List<String> getName() {
return myClass.getName();
}
And the implementation is the following:
#Interceptors(interceptor.class)
#Stateless
#Resource(name = "java:/db")
#Remote(MyClassRemote.class)
public class MyClassImpl extends MyEjb implements MyClassRemote{
#PersistenceContext(unitName = "db")
private EntityManager em;
#Resource
private SessionContext sctx;
#Autowired
public IMyRepo myRepo;
#Override
public List<String> getName() {
try {
return myRepo.getName(em);
}
catch (Exception ex) {
ex.printStackTrace();
throw ex;
}
finally {}
}
So, the problem is that here myRepo is null. I don't know why because IMyRepo and his implementation are always located within the path scanned by Spring.
Just one clarification: MyRepo class that implements IMyRepo is annotated with #Repository.
Any idea?
you can inject spring beans in EJB using Spring interceptors, as explained here in the official documentation. Basically you'll need to adjust your class as follows:
// added the SpringBeanAutowiringInterceptor class
#Interceptors({ interceptor.class, SpringBeanAutowiringInterceptor.class })
#Stateless
#Resource(name = "java:/db")
#Remote(MyClassRemote.class)
public class MyClassImpl extends MyEjb implements MyClassRemote{
// your code
}
You'll also need to define the context location in a beanRefContext.xml file (with your own application context file):
application-context.xml version
<bean id="context"
class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>application-context.xml</value>
</list>
</constructor-arg>
</bean>
Java Configuration version:
<bean id="context"
class="org.springframework.context.annotation.AnnotationConfigApplicationContext">
<constructor-arg>
<list>
<value type="java.lang.Class">com.your.app.Configuration</value>
</list>
</constructor-arg>
</bean>
Spring beans and EJB are two different things, you can't just inject a Spring bean in an EJB, because that EJB is no Spring bean, so Spring doesn't know there is a field which should be injected by Spring (unless you use some fancy AOP stuff, which can enable injection into non-Spring-managed beans).

Abstract Class bean definition for autowired field within jar

I am having a problem with autowiring. Here is my project's situation:
I have a jar (let's call it module.jar). This jar contains an Interface (IService):
package com.module.service;
public interface IService {
String create(Object data) throws Exception;
String update(Object data);
}
an abstract class which implements the interface (ServiceImpl):
package com.module.service
public abstract class ServiceImpl implements IService {
#Override
public final String create(Object data) throws Exception {
return update(data);
}
public abstract String update(Object data);
}
and a separate class which has an autowired IService field:
package com.module.service;
public class DoSomething {
#Autowired
IService service;
public String doCreate(Object data) {
return service.create(data);
}
}
I have a project (let's call it project). This project contains module.jar, and a class which extends the abstract ServiceImpl (we'll call it ServiceImplExt). ServiceImplExt is declared like so:
package com.project.service;
import com.module.service.ServiceImpl;
#Service
public class ServiceImplExt extends ServiceImpl {
#Override
public String update(Object data) {
data.setFname("John");
data.setLname("Doe");
return data;
}
}
I have added the ServiceImplExt's package to the component-scan of my spring xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<context:component-scan base-package="com.project.service" />
</beans>
After all of this, still when I start the server I get the following exception:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.demo.service.IService] 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)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1100)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:960)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:855)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
... 42 more
I cannot figure out what it is that I can be doing wrong. Any ideas?
Added the code, added xml to aide potential helpers

Spring #Autowired not working

I have some problems wth autowire annotation. My app looks like this:
Here is controller:
#Controller
public class MyController {
#Autowired
#Qualifier("someService")
private SomeService someService;
....
}
It's a service layer:
public interface SomeService {
...
}
#Service
public class SomeServiceImpl implements SomeService{
#Autowired
#Qualifier("myDAO")
private MyDAO myDAO;
....
}
And DAO layer:
public interface MyDAO{
....
}
#Repository
public class JDBCDAOImpl implements MyDAO {
#Autowired
#Qualifier("dataSource")
private DataSource dataSource;
....
}
This is a app-service.xml file:
....
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/jdbc.properties" />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.url}"
p:username="${jdbc.username}"
p:password="${jdbc.password}"/>
<bean id="SomeService" class="com.service.SomeServiceImpl" />
<bean id="myDAO" class="com.db.JDBCDAOImpl" />
So... When I'm launching a web-app, MyController Autowires correctly (the someService field correctly injected by SomeServiceImpl class object), but myDAO feild of someService has null value (not injected properly).
Could you help me to find a problem?
P.S. Its interesting, but when I'm changing a "bean id" from myDAO to some another (e.g. myDAO2), system gives me an error, that injecting could not be done, because bean myDAO doesn't exist. So, Spring make an injection, but where it is? And why it's not work correctly?
I found the solution. As Javi said (thanks a lot for you, Javi), I have to annotate DAO and Service layer classes with #Repository and #Service annotation. Now I've tried to write like this:
#Service("someService")
public class SomeServiceImpl implements SomeService{
#Autowired
#Qualifier("myDAO")
private MyDAO myDAO;
....
}
and
#Repository("myDAO")
public class JDBCDAOImpl implements MyDAO {
#Autowired
#Qualifier("dataSource")
private DataSource dataSource;
....
}
and all works fine!!!
But I still not found an answer for this quesion: if application will be more complex, and will have more complex structure, where #Repositore and #Service annotation are not preferred for some classes, how to inject correctly beans, which located in lower levels (in a fields of classes, or in a field of fields of classes) (with #Autowire annotation, of course)?
I guess you need <context:annotation-config />.
You can use
<context:component-scan base-package="PATH OF THE BASE PACKAGE"/>
entry in your configuration .xml file. This entry will scan/read all the stated type and annotations from the java classes.
Important points:
Sometimes, #Component may leads to a problem where it might say no default constructor found.
The class which is defined as a #Component annotation, it must have a default constructor.
Suppose, we have applied #Autowired annotation at field which is a user defined class reference.
Now, if we also apply #Component to that class then it will always be initialized with null.
So, a field with #Autowired should not have #Component at its class definition.
By default #Autowired is byType.
Address bean is autowired at Student class.
Let’s see what happens if we apply #Component at Address.java.
CollegeApp.java:
package com.myTest
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import com.bean.Address;
import com.bean.Student;
//Component scanning will for only those classes
//which is defined as #Component. But, all the class should not use
//#Component always even if the class is enabled with auto
//component scanning, specially the class which is Autowired
//Or which is a property of another class
#Configuration
#ComponentScan(basePackages={"com.bean"})
public class CollegeApp {
#Bean
public Address getAddress(){
return new Address("Elgin street");
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(CollegeApp.class);
Student student=context.getBean(Student.class);
System.out.println(student.toString());
context.close();
}
}
We want Elgin street to be autowired with Student address.
Address.java:
package com.bean;
import org.springframework.stereotype.Component;
#Component
public class Address {
private String street;
public Address()
{
}
public Address(String theStreet)
{
street=theStreet;
}
public String toString()
{
return (" Address:"+street);
}
}
Student.java:
package com.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class Student {
private String name;
private int age;
private Address address;
public Student()
{
}
public Student(String theName,int theAge)
{
name=theName;age=theAge;
}
#Autowired
public void setAddress(Address address) {
this.address = address;
}
public String toString()
{
return ("Name:"+name+" Age:"+age+ " "+address);
}
}
Output: - Name:null Age:0 Address:null //Address not Autowired here.
To resolve the issue, only change the Address.java as below:
Address.java:
package com.bean;
public class Address {
private String street;
public Address(String theStreet)
{
street=theStreet;
}
public String toString()
{
return (" Address:"+street);
}
}
Output:-
Name:null Age:0 Address:Elgin street
You should include this section of XML code in spring-config.xml :
<context:component-scan base-package="Fully.Qualified.Package.Name" />
but you should know the difference between <context:annotation-config> vs <context:component-scan> as most people are suggesting these two :
1) First big difference between both tags is that <context:annotation-config> is used to activate applied annotations in already registered beans in application context. Note that it simply does not matter whether bean was registered by which mechanism e.g. using <context:component-scan> or it was defined in application-context.xml file itself.
2) Second difference is driven from first difference itself. It does register the beans in context + it also scans the annotations inside beans and activate them. So <context:component-scan>; does what <context:annotation-config> does, but additionally it scan the packages and register the beans in application context.
There can be two reasons for this.
When you have not annotated the injected object or say service with proper #Service/#Component/#Repository annotations.
Once you have made sure of point 1 ,next check for whether the class package of your annotated service class is included in the class-path for your spring boot application in the main class.You can configure this using the following annotation.
#SpringBootApplication(scanBasePackages = {
"com.ie.efgh.somepackage","com.ie.abcd.someotherpackage" })
Doing this you tell spring to look into the packages for the classes during class loading.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Specifying base package of the Components like Controller, Service,
DAO -->
<context:component-scan base-package="com.jwt" />
<!-- Getting Database properties -->
<context:property-placeholder location="classpath:application.properties" />
<!-- DataSource -->
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"
id="dataSource">
<property name="driverClassName" value="${database.driver}"></property>
<property name="url" value="${database.url}"></property>
<property name="username" value="${database.user}"></property>
<property name="password" value="${database.password}"></property>
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
</bean>
</beans>

Resources