web-dev-qa-db-fra.com

BeanNotOfRequiredTypeException en raison de champs câblés automatiquement

Je suis toujours nouveau dans Spring MVC et lors de la construction de mon projet de test, j'ai reçu ce message des journaux Tomcat:

SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'divisionController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'adminService' must be of type [employee.service.impl.AdminServiceImpl], but was actually of type [$Proxy52]
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.Java:307)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.Java:1106)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.Java:517)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.Java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.Java:294)
    ...
Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'adminService' must be of type [employee.service.impl.AdminServiceImpl], but was actually of type [$Proxy52]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.Java:360)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.Java:197)

J'ai deux services rolle pour utilisateur et administrateur avec leurs interfaces:

package employee.service;

import employee.model.EmployeeDiv;
import employee.model.EmployeeInfo;
import employee.model.UserInfo;

import Java.util.List;

/**
 *
 * @author serge
 */

public interface AdminService extends UserService {

     //  !!!! for register & udate of Employee use String type birthday !!!!

    /*
     * Employee
     */
    public EmployeeInfo registerEmployee(EmployeeInfo employeeInfo);

    public EmployeeInfo updateEmployee(EmployeeInfo employeeInfo);

    public EmployeeInfo findEmployeeByID(Integer id);   

    /*
     * Division
     */
    public EmployeeDiv registerDivision(EmployeeDiv division);

    public EmployeeDiv updateDivision(EmployeeDiv division);

    public List<EmployeeDiv> findAllDivisions();

    public List<EmployeeDiv> findDivisionsByName(EmployeeDiv division);

    public EmployeeDiv findDivisionsById(Integer id);

    /*
     * Login
     */
    public UserInfo registerUser(UserInfo user);

    public UserInfo updateUser(UserInfo user);

    public List<UserInfo> findAllUsesrs();

    public List<UserInfo> findUsesrByLogin(UserInfo user);

    public UserInfo findUsesrById(Integer id);
}

C'est AdminServiceImpl:

package employee.service.impl;

import employee.DAO.EmployeeDivDAO;
import employee.DAO.EmployeeInfoDAO;
import employee.DAO.UserDAO;
import employee.model.EmployeeDiv;
import employee.model.EmployeeInfo;
import employee.model.UserInfo;
import employee.service.AdminService;
import employee.validation.ParsingDate;
import org.Apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import Java.util.List;

/**
 * @author serge
 *
 * Admin level
 *
 * Service for processing employee, divisions, userslogin
 */

//@Repository("adminService")
@Service("adminService")
@Transactional
public class AdminServiceImpl extends UserServiceImpl implements AdminService {

    protected static Logger adminLogger = Logger.getLogger("service");
    private EmployeeDivDAO emplDivDAO;
    private UserDAO userDAO;
    private EmployeeInfoDAO emplInfoDAO;

    @Autowired
    @Override
    public void setEmployeeDao(EmployeeInfoDAO emplInfoDAO) {
        this.emplInfoDAO = emplInfoDAO;
    }

    @Autowired
    public void setEmployeeDao(EmployeeDivDAO emplDivDAO) {
        this.emplDivDAO = emplDivDAO;
    }

    @Autowired
    public void setUserDao(UserDAO userDAO) {
        this.userDAO = userDAO;
    }

    public AdminServiceImpl() {

        initTestEmployee();
    }

    /**
     * Initialize EmployeeInfo test
     */
    @Transactional
    @Secured("ROLE_ADMIN")
    private EmployeeInfo initTestEmployee() {

        adminLogger.debug("saving testEmployee");

        EmployeeInfo employeeInfo = new EmployeeInfo();
        ParsingDate date = new ParsingDate();
        employeeInfo.setFirstName("Petr");
        employeeInfo.setLastName("Ivanenko");
        employeeInfo.setEmpDiv("second");
        employeeInfo.setBirthdate(date.parseDate("1981-10-03"));
        employeeInfo.setSalary(3500);
        employeeInfo.setActive(true);

        return employeeInfo;
    }

    /**
     * registrating new Employee Information
     *
     * @return EmployeeInfo object
     */
    @Override
    @Transactional
    @Secured("ROLE_ADMIN")
    public EmployeeInfo registerEmployee(EmployeeInfo employeeInfo) {

        adminLogger.debug("registrating new Employee");

        try {

            emplInfoDAO.save(employeeInfo);

        } catch (NullPointerException e) {
        }
        return employeeInfo;
    }

    /**
     * updating Employee Information
     *
     * @return EmployeeInfo object
     */
    @Override
    @Transactional
    @Secured("ROLE_ADMIN")
    public EmployeeInfo updateEmployee(EmployeeInfo employeeInfo) {

        adminLogger.debug("updating Employee with id: " + employeeInfo.getId());
        try {

            emplInfoDAO.update(employeeInfo);

        } catch (NullPointerException e) {
        }
        return employeeInfo;
    }

    /**
     * Retrieving Employee Information by id 
     *
     * @return EmployeeInfo object
     */
    @Override
    @Transactional
    @Secured("ROLE_ADMIN")
    public EmployeeInfo findEmployeeByID(Integer id) {

        adminLogger.debug("Retrieving Employee with id= " + id);
        EmployeeInfo employeeInfo = new EmployeeInfo();
        employeeInfo.setId(id);
        emplInfoDAO.find(employeeInfo);
        return employeeInfo;
    }

    /**
     * registrating new Employee Division
     *
     * @return EmployeeDiv object
     */
    @Override
    @Transactional
    @Secured("ROLE_ADMIN")
    public EmployeeDiv registerDivision(EmployeeDiv division) {

        adminLogger.debug("registrating new Division");
        try {

            emplDivDAO.save(division);

        } catch (NullPointerException e) {
        }
        return division;
    }

    /**
     * updating Employee Division
     *
     * @return EmployeeDiv object
     */
    @Override
    @Transactional
    @Secured("ROLE_ADMIN")
    public EmployeeDiv updateDivision(EmployeeDiv division) {

        adminLogger.debug("updating Division with id: " + division.getId());
        try {

            emplDivDAO.update(division);

        } catch (NullPointerException e) {
        }
        return division;
    }

    /**
     * Retrieving all Employee Divisions
     *
     * @return List of EmployeeDiv objects
     */
    @Override
    @Transactional
    @Secured("ROLE_ADMIN")
    public List<EmployeeDiv> findAllDivisions() {

        adminLogger.debug("Retrieving all divisions");
        return emplDivDAO.findAll();
    }

    /**
     * Retrieving all Employee Divisions by name
     *
     * @return List of EmployeeDiv objects
     */
    @Override
    @Transactional
    @Secured("ROLE_ADMIN")
    public List<EmployeeDiv> findDivisionsByName(EmployeeDiv division) {
        String empDiv = "empDiv";

        adminLogger.debug("Retrieving Divisions by name: " + division.getEmpDiv());
        return emplDivDAO.findAllByParam(empDiv, division.getEmpDiv());
    }

     /**
     * Retrieving Employee Divisions by id 
     *
     * @return EmployeeDiv object
     */
    @Override
    @Transactional
    @Secured("ROLE_ADMIN")
    public EmployeeDiv findDivisionsById(Integer id) {

        adminLogger.debug("Retrieving Division with id= " + id);
        EmployeeDiv employeeDiv = new EmployeeDiv();
        employeeDiv.setId(id);
        emplInfoDAO.find(employeeDiv);
        return employeeDiv;
    }

    /**
     * registrating new User Information
     *
     * @return UserInfo object
     */
    @Override
    @Transactional
    @Secured("ROLE_ADMIN")
    public UserInfo registerUser(UserInfo user) {

        adminLogger.debug("registrating new User");
        try {

            userDAO.save(user);

        } catch (NullPointerException e) {
        }
        return user;
    }

    /**
     * updating new User Information
     *
     * @return UserInfo object
     */
    @Override
    @Transactional
    @Secured("ROLE_ADMIN")
    public UserInfo updateUser(UserInfo user) {

        adminLogger.debug("updating User with id: " + user.getId());
        try {

            userDAO.update(user);

        } catch (NullPointerException e) {
        }
        return user;
    }

    /**
     * retriviting all Users 
     *
     * @return List of UserInfo objects
     */
    @Override
    @Transactional
    @Secured("ROLE_ADMIN")
    public List<UserInfo> findAllUsesrs() {

        adminLogger.debug("Retrieving all Users");
        return userDAO.findAll();
    }

    /**
     * retriving all Users by login
     *
     * @return List of UserInfo objects
     */
    @Override
    @Transactional
    @Secured("ROLE_ADMIN")
    public List<UserInfo> findUsesrByLogin(UserInfo user) {
        String login = "login";

        adminLogger.debug("Retrieving User with login: " + login);
        return userDAO.findAllByParam(login, user.getLogin());
    }

    /**
     * Retrieving Employee Divisions by id 
     *
     * @return EmployeeDiv object
     */
    @Override
    @Transactional
    @Secured("ROLE_ADMIN")
    public UserInfo findUsesrById(Integer id) {

        adminLogger.debug("Retrieving Division with id= " + id);
        UserInfo userInfo = new UserInfo();
        userInfo.setId(id);
        emplInfoDAO.find(userInfo);
        return userInfo;
    }
}

C'est 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" 
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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
            http://www.springframework.org/schema/mvc 
            http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">

    <!-- Activates annotations -->

    <context:annotation-config />

    <!-- Scans for annotated components in base-package-->

    <context:component-scan base-package="employee" />

    <bean class="employee.service.impl.AdminServiceImpl"/>
    <bean class="employee.service.impl.UserServiceImpl"/>
    <!--bean class="employee.DAO.impl.EmployeeInfoDAOImpl"/>
    <bean class="employee.DAO.impl.EmployeeDivDAOImpl"/>
    <bean class="employee.DAO.impl.UserDAOImpl"/-->

    <!-- for Spring Jackson JSON support  -->

    <mvc:annotation-driven/>

    <!-- Shared Hibernate SessionFactory in a Spring application context. -->

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>

        <!--property name="dataSource">
            <ref bean="dataSource"/>
        </property-->

        <property name="annotatedClasses">
            <list>
                <value>employee.model.UserInfo</value>
                <value>employee.model.EmployeeInfo</value>
                <value>employee.model.EmployeeDiv</value>
            </list>
        </property>

        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>

    <!-- for database, imports the properties from database.properties -->

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:database.properties"/>
    </bean>
</beans>

S'il vous plaît dites-moi quel est le problème avec ce nom de bean, je comprends que c'est le problème AOP:

Bean named 'adminService' must be of type [employee.service.impl.AdminServiceImpl], but was actually of type [$Proxy52]

comment je peux le réparer?

J'utilise AdminServiceImpl dans les contrôleurs:

package employee.controller;

import employee.model.EmployeeDiv;
import employee.service.impl.AdminServiceImpl;
import org.Apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.annotation.Resource;

/**
 * @author serge
 *
 * Handles and retrieves division related requests
 */
@Controller
@RequestMapping("/division")
public class DivisionController {

    protected static Logger logger = Logger.getLogger("controller");
    @Resource(name = "adminService")
    private AdminServiceImpl adminService;

    /**
     * Handles and retrieves a /WEB-INF/jsp/divisionpage.jsp
     *
     * containing all division
     *
     * @return the name of the JSP page
     */
    @RequestMapping(method = RequestMethod.GET)
    public String getAllPage(Model model) {
        logger.debug("Received request to show all division page");

        // Retrieve all division and attach to model 
        model.addAttribute("division", adminService.findAllDivisions());
        return "divisionpage";
    } ....
35
Serge

Quelque part dans votre code, vous devez être en autowiring AdminServiceImpl comme ceci:

@Autowired
private AdminServiceImpl adminService;

Soit dépendre à peine de l'interface:

@Autowired
private AdminService adminService;

ou activé les proxies CGLIB.

Problèmes similaires

73
Tomasz Nurkiewicz

utilisez l'interface AdminService plutôt que les outils.

cette erreur provoquée par Annotation @Transactional, Spring crée un proxy pour AdminService à Runtime.

21
BobJiang

Lorsque votre classe de service implémente une interface, spring par défaut prend proxy par JDK. C'est pourquoi vous obtenez cette erreur. Vous pouvez donc résoudre ce problème en utilisant @Autowired sur l'interface ou en activant le proxy CGLIB .

J'ai résolu ce problème en activant le proxy CGLIB à l'aide de proxy-target-class attribut dans mon contexte d'application Spring 

<tx:annotation-driven proxy-target-class="true"
        transaction-manager="transactionManager" />

J'ai trouvé beaucoup de questions similaires à celle-ci lors de la recherche de mon problème sur Google. Cependant, dans mon cas, j'ai déjà utilisé une interface. J'ai donc pensé que cela pourrait être utile aux autres:

Cette exception peut également apparaître si vous avez deux beans portant le même nom!

Dans mon cas, j'avais une configuration de bean supplémentaire dans mon applicationContext.xml. Le problème est apparu après la fusion de deux applications. Le second définit un @Resource et son nom de variable membre correspond au nom de bean de la première application, mentionné ci-dessus. Bien entendu, la configuration du bean de la première application ne correspondait pas au bean inclus via @Resource par la deuxième application.

3
fishbone

J'ai le même problème, mais j'ai résolu le problème avec la solution suivante: 

Veuillez remplacer votre classe d'implémentation par interface . Par exemple:

class Abc
{
 @Autowire
 private Boy boy // remove @BoyImpl

.............
...................
}
2
pankaj

J'ai également rencontré le problème lors de l'exécution du test unitaire

J'ai créé un service factice pour implémenter le service réel afin de remplacer une méthode afin de tester facilement un cas d'utilisateur.

@Component
public static class FooServiceImplMock extends FooServiceImpl {
    @Override
    protected void bar() {
        // do some specific loginc here 
    }
}

mais quand exécuter la méthode de test 

@Autowired
private Foo1ServiceImplMock foo1ServiceImplMock;

J'ai eu l'erreur ci-dessous

Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'fooServiceImplTest.FooServiceImplMock' is expected to be of type 'com.foo.business.impl.FooServiceImplTest$FooServiceImplMock' but was actually of type 'com.Sun.proxy.$Proxy97'

Raison:

Il existe une méthode dans FooServiceImpl utilisée @Cacheable

@Cacheable("eventTypes")

Et de javadoc de EnableCaching je sais

org.springframework.cache.annotation.EnableCaching 
boolean proxyTargetClass()

Indicate whether subclass-based (CGLIB) proxies are to be created as opposed to standard Java interface-based proxies. The default is false.

Donc, la manière de résoudre est explicitement de spécifier utiliser CGLIB dans le contenu de l'application printanière

 <cache:annotation-driven proxy-target-class="true"/>
0
zhuguowei

J'ai également eu ce problème avec certaines classes @SpringBootTest qui testaient des points de terminaison. Les ordinateurs d'extrémité dépendaient d'un service de base de données comportant @Transactional sur quelques méthodes.

En raison du @Transactional, Spring intercepte cela et crée une classe proxy, de sorte que Spock (ou Junit) aurait du mal à injecter le modèle correct.

Ma solution de contournement consistait à répartir le service de base de données sur une couche et à effectuer des tests Spock simples autour de la couche centrale, qui ne sont pas concernés par cette opération.

0
Jimmy