Service is not injected in a Controller in Spring 3 - spring

Fist time I will say, I am quite new to Spring...
I have a method that must be transactional, but are in different classes. These methods receive some parameters from an Android app. So, I wrote a GeneralServiceImp:
public class GeneralServiceImp implements GeneralService{
UserDao userDao;
VehiculoDao vehicleDao;
#Override
#Transactional
public String addUserAndVehicle(User user, Vehiculo vehiculo) {
System.out.println("Method addUserAndVehicle() invpked");
userDao.addUser(user);
vehicleDao.addVehiculo(vehiculo);
return null;
}
public void setUsuarioDao(UserDao userDao) {
this.userDao = userDao;
}
public void setVehiculoDao(VehiculoDao vehicleDao) {
this.vehicleDao = vehicleDao;
}
}
This is UserController:
#Controller
public class UsuarioControllers {
#Autowired
UsuarioService usuarioService;
GeneralService generalService;
#RequestMapping("/usuario/add")
#ResponseBody
public String addUsuario(#ModelAttribute("usuario")
User usuario,#ModelAttribute("vehiculo")Vehiculo vehiculo,BindingResult result){
System.out.println("Petition received");
if(usuario==null){
System.out.println("Usuario is null");
}
if(vehiculo==null){
System.out.println("Vehiculo is null");
}
try{
//usuarioService.addUsuario(usuario);
if(generalService!=null){
generalService.addUserAndVehicle(usuario, vehiculo);
}else{
System.out.println("generalService is null");
return "fail";
}
}catch (DuplicateKeyException e){
return "duplicated";
}
return "ok";
}
And in the XML bean definition file i have generalService defined this way:
<bean name="generalService" class="com.goatsoft.appark.services.GeneralServiceImp">
<property name="usuarioDao" ref="userDao"/>
<property name="vehiculoDao" ref="vehiculoDao"/>
</bean>
Thigs this way, the program enters the "generalService is null" if, and I don't know why! If you see, there is a commented line "//usuarioService.addUsuario(usuario);". That worked perfectly. Can you help me please?
Thank you.

You have only autowired UsuarioService.
And your daos are not wired up at all. So it should look like this :
#Controller
public class UsuarioControllers {
#Autowired
UsuarioService usuarioService;
#Autowired
GeneralService generalService;

Related

Propagation.REQUIRES_NEW not working properly

I have the following scenario.
I have one transaction method which calls another transaction method which having REQUIRED_NEW Propagation. if the first method gets exception then the second method (REQUIRED_NEW Propagation) also rollbacks.
I am using JPA, Spring-boot and chainedKakfkaTransactionManager
I have tried with changing chainedKakfkaTransactionManager to default one still no luck
here is my code :
#Service
#Transactional(readOnly = false)
public class ComponentServiceImpl implements ComponentService {
#Autowired
private UserRepository userRepository ;
#Override
#Transactional
public boolean validateName(String name) {
try{
retrun userRepository.validate(name);
}catch(Exception e){
handleError(name);
throw new Exception("user not valid");
}
}
#Override
#Transactional(propagation=Propagation.REQUIRES_NEW)
public boolean handleError(String name) {
userRepository.update(name);
}
}
Rollback is happening in the handleError method too. is there any code mistake?
Thanks #DarrenForsythe,
By Creating an autowire object for the same class (self-reference) its worked for me
#Service
#Transactional(readOnly = false)
public class ComponentServiceImpl implements ComponentService {
#Autowired
private UserRepository userRepository ;
// CREATE SELF REFRENCE
#Autowired
private ComponentService componentService;
#Override
#Transactional
public boolean validateName(String name) {
try{
retrun userRepository.validate(name);
}catch(Exception e){
componentService.handleError(name);
throw new Exception("user not valid");
}
}
#Override
#Transactional(propagation=Propagation.REQUIRES_NEW)
public boolean handleError(String name) {
userRepository.update(name);
}
}

BeanNotOfRequiredTypeException with PlatformTransactionManager

I'm new to Spring and I did a login/register applicaton following a youtube tutorial but I want to add a new functionality that allows to delete a student. I used #Transactional on my delete method and modified accordingly the xml file but I get this error:
Message Request processing failed; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'platformTransactionManager' is expected to be of type 'org.springframework.transaction.PlatformTransactionManager' but was actually of type 'com.infotech.service.impl.StudentServiceImpl'
my Service class
#Service("studentService")
public class StudentServiceImpl implements StudentService {
#Autowired
private StudentDAO studentDAO;
public void setStudentDAO(StudentDAO studentDAO) {
this.studentDAO = studentDAO;
}
public StudentDAO getStudentDAO() {
return studentDAO;
}
//other methods
#Override
public void delete(String email) {
getStudentDAO().delete(email);
}
}
my DAO class
#EnableTransactionManagement
#Repository("studentDAO")
public class StudentDAOImpl implements StudentDAO {
#Autowired
private HibernateTemplate hibernateTemplate;
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
public HibernateTemplate getHibernateTemplate() {
return hibernateTemplate;
}
#Autowired
private SessionFactory sessionFactory;
protected Session getSession() {
return (Session) sessionFactory.getCurrentSession();
}
//other methods
#Transactional("platformTransactionManager")
public void delete(String email) {
Student student = (Student) ((HibernateTemplate) getSession()).get(Student.class, email);
((HibernateTemplate) getSession()).delete(student);
}
}
In the dispatcher servlet I have defined InternalResourceViewResolver, dataSource, hibernateTemplate, sessionFactory beans and then I added another bean
<tx:annotation-driven transaction-manager="platformTransactionManager"/>
<bean id= "platformTransactionManager"class="com.infotech.service.impl.StudentServiceImpl">
</bean>
Finally, this is the controller
#Controller
public class MyController {
#Autowired
private StudentService studentService;
public void setStudentService(StudentService studentService) {
this.studentService = studentService;
}
public StudentService getStudentService() {
return studentService;
}
//...RequestMappings...
#RequestMapping(value = "/delete/{email}", method = RequestMethod.GET)
public ModelAndView delete(#PathVariable("email") String email) {
studentService.delete(email);
return new ModelAndView("redirect:/view/home");
}
...
}
Now, how can I make my bean of PlatformTransactionManager type?
But most of all I think there's a simpler way to delete a field from my table, maybe without using #Transaction at all so can anyone help me understand why I get the error and explain me what is #Transactional and if I really should use it in this case?
Remember that I'm NEW to Spring, I still don't have many notions so sorry if I wrote something totally stupid :-)
Spring is looking for transaction manager - it requires a concrete implementation of the PlatformTransactionManager interface. It's being given your service implementation, which isn't a PlatformTransactionManager and not what it needs. If you're using JDBC, org.springframework.jdbc.datasource.DataSourceTransactionManager should work.
Try changing:
<bean id= "platformTransactionManager" class="com.infotech.service.impl.StudentServiceImpl">
To:
<bean id= "platformTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

#Autowired not working with custom AccessDecisionVoter

I am implementing a custom AccessDecisionVoter and I have a JPA repository which I need to autowire in the custom AccessDecisionVoter implementation. #Autowire is simply not working for neither a Service or Jpa Repository inside this class.
Project Structure
Application.java
#SpringBootApplication
#ComponentScan(basePackages="com")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
DynamicAuthorizationVoter.java
#Component
public class DynamicAuthorizationVoter implements AccessDecisionVoter<FilterInvocation> {
#Autowired
private PrivilegeRepository privilegeRepo;
#Override
public boolean supports(ConfigAttribute attribute) {
return true;
}
#Override
public boolean supports(Class clazz) {
return true;
}
#Override
public int vote(Authentication authentication, FilterInvocation object, Collection<ConfigAttribute> collection) {
String url = determineModule(object);
if (authentication == null || authentication instanceof AnonymousAuthenticationToken) {
return ACCESS_ABSTAIN;
}
return isAccessGranted(authentication, object.getRequestUrl())? ACCESS_GRANTED : ACCESS_DENIED;
}
String determineModule(FilterInvocation filterObject){
String url = filterObject.getRequestUrl();
return url;
}
boolean isAccessGranted(Authentication authObject, String url){
Set<Privilege> privileges = privilegeRepo.findByUrl(url);
String userRole;
for(GrantedAuthority authority : authObject.getAuthorities()){
userRole = authority.getAuthority();
for(Privilege priv : privileges){
if(priv.equals(userRole)){
return true;
}
}
}
return false;
}
}
PrivilegeRepository.java
public interface PrivilegeRepository extends JpaRepository<Privilege, Long> {
Set<Privilege> findByName(String name);
Set<Privilege> findByUrl(String url);
}
For #Autowire to work inside the DynamicAuthorizationVoter class, I changed the #Component to #Service, #Configuration and everything else I found here on SO but none of them works. This JPA Repository is #Autowired everywhere else.
I will appreciate all the help.
-Adil
Usually, if you don't see any error during deployment, autowired worked fine because it is required by default. See the #Autowired documentation
Anyway, try to use an #Autowired constructor instead of an #Autowired property.
private PrivilegeRepository privilegeRepo;
#Autowired
public DynamicAuthorizationVoter(PrivilegeRepository privilegeRepo){
this.privilegeRepo = privilegeRepo;
}
With that, you could add a breakpoint to this constructor and debug it to know if the autowire process works well.
Also, remember that to use the DynamicAuthorizationVoter instance you mustn't declare it as new. You must include the following code in the related class where you want to use it.
#Autowired
AccessDecisionVoter dynamicAuthorizationVoter;
Hope it helps,

How to use annotation and avoid xml configuration in spring framework

I have designed a packing structure.
Controller
Delegates (which is helper class) - this class do all the business and return the value to Controllers.
Service
Service Implementation
DAO
DAO Implementation.
I want to implement autowired (Annotation) concept and would like to avoid xml configuration such as service and DAO configuration on spring-bean.xml.
This code is not working if I want to avoid xml configuration.
I have done those changes
bean id :loginDelegate, userService, userDao
added the #Service & #Repository annotation to the corresponding service & DAO implementation.
#Controller("loginController")
public class LoginController {
#Autowired
private LoginDelegate loginDelegate;
public LoginDelegate getLoginDelegate() {
return this.loginDelegate;
}
public void setLoginDelegate(LoginDelegate tLoginDelegate) {
this.loginDelegate = tLoginDelegate;
}
#RequestMapping(value="/login.do",method=RequestMethod.GET)
public ModelAndView displayLogin(HttpServletRequest request, HttpServletResponse response) {
log.info("<---displayLogin()--->");
ModelAndView model = new ModelAndView("login");
LoginBean loginBean = new LoginBean();
model.addObject("loginBean", loginBean);
return model;
}
}
public class LoginDelegate {
#Autowired
private IUserService userService;
public IUserService getUserService() {
return this.userService;
}
public void setUserService(IUserService userService) {
this.userService = userService;
}
public boolean isValidUser(String username, String password) throws Exception {
return userService.isValidUser(username, password);
}
}
public interface IUserService {
public boolean isValidUser(UserBean userObj);
public int addUsers(UserBean userObj);
}
public class UserServiceImpl implements IUserService {
#Autowired
private IUserDao userDao;
public IUserDao getUserDao() {
return this.userDao;
}
public void setUserDao(IUserDao userDao) {
this.userDao = userDao;
}
public boolean isValidUser(UserBean userObj) {
return userDao.isExistUser(userObj);
}
#Override
public int addUser(final UserBean userObj) {
return userDao.saveUserDetails(userObj);
}
}
public interface IUserDao {
public boolean isExistUser(UserBean userObj);
public int saveUserDetails(UserBean userObj);
}
public class UserDaoImpl implements IUserDao {
#Autowired
UserBean userObj;
#Autowired
DataSource dataSource ;
public DataSource getDataSource(){
return this.dataSource;
}
public void setDataSource(DataSource dataSource){
this.dataSource = dataSource;
}
Use Java-based configuration if you want to completely get rid of XML-based configuration
#Configuration
#ComponentScan(basePackages = "com.acme")
public class AppConfig {
...
}
The above normal Java class when annotated with #Configuration, makes it a 'Spring Configuration class' (analogous to XML-based configuration).
#ComponentScan annotation scans for classes annotated with #Component, #Controller, #Service, #Repository classes from the package defined during start-up time to get them registered as Spring beans. This can be done in XML also with <context:component-scan base-package="com.acme" />
Refer:http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/beans.html#beans-java-instantiating-container-scan

Spring advice does not work as expected

I am new in Spring AOP, and I have create an application to learn the Spring AOP, however I found that the Aspect does not work as expected, this is the core code:
Target:
public interface UserService {
void getUserList();
}
#Component
public class UserServiceImpl implements UserService {
#Autowired
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
#Override
public void getUserList() {
this.userDao.getUserList();
}
}
Aspect:
#Aspect
public class LoggingAspect {
#Pointcut("execution(* com.kk.service.impl.UserServiceImpl(..))")
public void logTargetUserService() {
}
#Before("execution(* com.kk.service.impl.UserServiceImpl.getUserList(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("logBefore() is running!");
System.out.println("hijacked : " + joinPoint.getSignature().getName());
System.out.println("******");
}
}
spring.xml:
<context:component-scan base-package="com.kk"/>
<aop:aspectj-autoproxy proxy-target-class="true"/>
Application:
public class Application {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"spring.xml"});
UserServiceImpl userService = context.getBean(UserServiceImpl.class);
userService.getUserList();
}
}
When I run it I only got this output:
get user list at dao
It seems that the advise does not run at all.
What is going on?
You should regist your bean as like this
<bean id="loggingAspect" class="your.package.LoggingAspect"/>

Resources