Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

spring 3 @controller not able to inject service object which has @Transactional

I am using Spring 3 MVC, I have a problem in injecting the Objects. I created the Controller Object with the @Controller. And I have created a Service Object with the @Service Object. I injected the service object in the controller with AutoWire. And I created the DAO Object, and injected in the Service Object, and Tested the application , it is running fine. Then I put @Transactional on DAO, then also it worked fine. But when I put the @Transactional on service object,It is Giving me the problem. At the time of deploying , at the Controller it says as "

Context initialization failed: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loginController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void com.erudicus.controller.LoginController.setLoginService(com.erudicus.model.service.LoginServiceImpl); nested exception is java.lang.IllegalArgumentException: argument type mismatch".

Here is the Code Controller

@Controller
public class LoginController {
     private static Logger LOG = Logger.getLogger(LoginController.class);

    private LoginServiceImpl loginService = null;


    public LoginServiceImpl getLoginService() {
        return loginService;
    }

    @Autowired
    public void setLoginService(LoginServiceImpl loginService) {
                this.loginService = loginService;
    }

    @RequestMapping(value="/login" , method= RequestMethod.GET)
    public String login(Model model) {
        model.addAttribute(new Login());
            return "login";
    }

    @RequestMapping(value="/loginDetails", method=RequestMethod.POST)
    public ModelAndView create(@Valid Login login, BindingResult result) {
      }
}

Service Object

@Service
public class LoginServiceImpl implements LoginService {

    private LoginDao loginDao = null;


    public LoginDao getLoginDao() {
        return loginDao;
    }

    @Autowired
    public void setLoginDao(LoginDao loginDao) {
        this.loginDao = loginDao;
    }

    @Transactional(readOnly = true, propagation = Propagation.REQUIRED)
    public Login getUserDetails(String userId) {
           return getLoginDao().getUserDetails(userId);
    }
}

Dao

@Service
@Transactional(propagation = Propagation.MANDATORY)
public class LoginDaoImpl extends SqlSessionDaoSupport implements LoginDao {

    @Transactional(readOnly = true, propagation = Propagation.MANDATORY)
    public Login getUserDetails(String userId) {
    }
}

In the Configuration I specified

<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
    <!-- enable autowire -->
    <!-- enable transaction demarcation with annotations -->
    <tx:annotation-driven transaction-manager="txManager"/>
 <context:annotation-config/>

Any one can please help

like image 630
Kumar Avatar asked Dec 22 '22 18:12

Kumar


1 Answers

Define the field to be an interface, rather than a concrete class. (So UserService instead of UserServiceImpl). You can add the @Transactional annotation on the concrete class - it will work.

The problem is that by default spring uses JDK proxies (java.lang.reflect.Proxy) which are interface-only proxies. Your concrete class is then used by the invocation handler, but you cannot cast to it.

If there is no interface, spring uses another method - CGLIB, which subclasses the target class in order to make the proxy.

You can use <aop:scoped-proxy /> to configure the proxying stragegy (proxy-target-class) per bean.

like image 56
Bozho Avatar answered Dec 24 '22 08:12

Bozho