java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'VausRestController' method - spring-mvc

I am trying to setup REST server that supports only 1 HTTP request.
I received the following exception:
2017/05/10 16:42:46.036 ERROR:
Failed starting server: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'VausRestController' method
public org.springframework.http.ResponseEntity<com.nds.ch.vge.vaus.restController.VausRestController$ErrorResponse> com.nds.ch.vge.vaus.restController.VausRestController.signature(com.nds.ch.vge.vaus.types.EcdsaSignature)
to {[/authentication/signature],methods=[PUT]}: There is already 'vausRestController' bean method
public org.springframework.http.ResponseEntity<com.nds.ch.vge.vaus.restController.VausRestController$ErrorResponse> com.nds.ch.vge.vaus.restController.VausRestController.signature(com.nds.ch.vge.vaus.types.EcdsaSignature) mapped.
The application context (relevant part):
<context:annotation-config />
<bean id="VausRestController" class="restController.VausRestController">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
Code:
import javax.annotation.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
#Controller
#RestController
public class VausRestController {
#Resource(name="authenticationManager")
AuthenticationManager authenticationManager;
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
#RequestMapping(value ="/authentication/signature", method = RequestMethod.PUT)
public ResponseEntity<Object> signature( #RequestBody final EcdsaSignature ecdsaSignature) {
return ......
}
Notice that I have only one #RequestMapping.
I also tried to change the spring versions in my pom.xml - didn't help.

The reason for this failure is that in the application context 'bean' I had capital letter id="VausRestController"
To fix, I used:
<bean id="vausRestController" class="restController.VausRestController">
<property name="authenticationManager" ref="authenticationManager" />
</bean>

Related

Spring-MVC - Error creating bean with name 'productsController': Injection of autowired dependencies failed

Im having a problem with a spring-mvc project. The #autowiring is not creating the beans required. Ive worked on this for over 4 days and followed all the search results. But nothing has worked. Can someone please take a look. Thank You
The error stack is this:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'productsController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.davis.ty.service.ProductsService com.davis.ty.controller.ProductsController.productsService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.davis.ty.service.ProductsService] 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)}
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
My servlet.xml is:
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<context:annotation-config />
<context:component-scan base-package="com.davis.ty" />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<mvc:resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/jdbc.properties" />
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
<bean id="dataSource"
class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.databaseurl}" p:username="${jdbc.username}"
p:password="${jdbc.password}" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
My controller is:
package com.davis.ty.controller;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
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 com.davis.ty.domain.Products;
import com.davis.ty.service.ProductsService;
#Controller
public class ProductsController {
#Autowired
private ProductsService productsService;
#RequestMapping(value = "/index", method = RequestMethod.GET)
public String listProducts (Map<String, Object> map) {
System.out.println("index");
map.put("products", new Products());
map.put("productsList", productsService.listProducts());
return "index";
}
#RequestMapping(value = "/add", method = RequestMethod.POST)
public String addProducts(#ModelAttribute("products")
Products products, BindingResult result) {
productsService.addProducts(products);
return "redirect:/index";
}
#RequestMapping("/delete/{Id}")
public String deleteProducts(#PathVariable("Id")
Integer Id) {
productsService.removeProducts(Id);
return "redirect:/index";
}
}
My service program is:
package com.davis.ty.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.davis.ty.dao.ProductsDAO;
import com.davis.ty.domain.Products;
#Service
public class ProductsServiceImpl {
#Autowired
private ProductsDAO productsDAO;
#Transactional
public void addProducts(Products products){
productsDAO.addProduct(products);
}
#Transactional
public List<Products> listProducts() {
return productsDAO.listProducts();
}
#Transactional
public void removeProducts(Integer id) {
productsDAO.removeProducts(id);
}
}
Well, your ProductsServiceImpl class doesn't implement ProductsService... so there's no way that bean is injected in a field of type ProductsService.
From my experience, I just add #Repository at my DAO, maybe you can try to use it too
#Repository
public class ProductsDAO
{
}
How Spring autowire works is, Spring application context scans for all the classes inside the package and sub packages, specified by the component scan and internally creates a map by Type and Name. Incase of Type, value can be List of implementing classes, and by name its one.
Then whenever a #Autowire if encounter,
first it check by Type, so if you autowire using interface, it checks for all the implementation of that interface, and if only 1 if found then inject the same. (In case more then 1 is found, then you need to qaulify using the Qualifier and give proper name.
If above fails, if check by name, and injects.
If both fails, if gives NoSuchBeanDefinitionException,
So in your case, you have set the component scan, which is correct. Then while autowiring, you are giving Interface class name and the implementation class does not implements interface. So type check is failing, and also the by name is also failing, and hence you are getting NoSuchBeanDefinitionException.
To fix this, you will need to do what #JB Nizet is suggesting, so that #1 works and bean gets injected properly.
Add implements ProductService after public class ProductsServiceImpl
create a service interface and implement the interface method in service Impl class with #Overrride annotation.
public interface ProductService{
List<Product> getProducts();
}
And then
#Service
public class ProductsServiceImpl implements ProductService{
#Override
public List<Product> getProducts() {
return productRepository.findAll();
}

ehcache generates empty data file

I want to use data caching with ehcache in my portlet. I use Spring MVC and liferay portal. If I want to use Cacheable annotation, empty data file is generated.
SocialGraphUI-portlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd">
<context:component-scan base-package="socialgraphui" />
<cache:annotation-driven />
<cache:annotation-driven cache-manager="cacheManager" mode="proxy" proxy-target-class="true" />
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:config-location="/WEB-INF/ehcache.xml" p:shared="true" />
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cacheManager-ref="ehcache" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
</bean>
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.GsonHttpMessageConverter" />
</mvc:message-converters>
</mvc:annotation-driven>
<bean class="org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
<bean class="org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
<!-- Spring MVC Message Source -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="useCodeAsDefaultMessage" value="true"/>
<property name="basenames">
<list>
<value>content.socialGraph</value>
</list>
</property>
</bean>
</beans>
ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<diskStore path="user.dir"/>
<defaultCache eternal="true" overflowToDisk="true" diskPersistent="true" />
<cache name="socialGraphCache" eternal="true" overflowToDisk="true" diskPersistent="true" />
</ehcache>
SocialGraphViewController.java
package socialgraphui.controller;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.liferay.portal.kernel.util.ParamUtil;
import socialgraphui.model.Edge;
import socialgraphui.model.Message;
import socialgraphui.model.Node;
import socialgraphui.model.SocialGraph;
import socialgraphui.service.SocialGraphService;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import org.apache.log4j.Logger;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.portlet.bind.annotation.ActionMapping;
import org.springframework.web.portlet.bind.annotation.RenderMapping;
import org.springframework.web.portlet.bind.annotation.ResourceMapping;
/**
*
* Controller for VIEW mode of portlet
*/
#Controller("socialGraphViewController")
#RequestMapping(value = "VIEW")
public class SocialGraphViewController{
Gson gson = new GsonBuilder().setPrettyPrinting().create();
private static final Logger logger = Logger.getLogger(SocialGraphViewController.class);
// -- auto-wiring of service dependency
#Autowired
#Qualifier("SGService")
private SocialGraphService socialGraphService;
public void setSocialGraphService(SocialGraphService service){
this.socialGraphService = service;
}
#ModelAttribute(value="socialgraph")
public SocialGraph getSocialGraph(){
return socialGraphService.getSocialGraph();
}
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(PersonDefinitionTypeList.class, new PersonDefinitionTypeListEditor());
}
#ActionMapping(SocialGraphPortletConstants.SUBMIT_FILTER)
public void handleActionRequest(ActionRequest request, ActionResponse response, PortletSession session)throws Exception {
logger.info("handleActionRequest in was executed");
...
}
#RenderMapping
public String handleRenderRequest(RenderRequest request, RenderResponse response, ModelMap model, Locale locale, PortletSession session) {
logger.info("handleRenderRequest was executed");
...
return SocialGraphPortletConstants.VIEW;
}
}
I want to cache result of service constructor, but not sure if I do it in proper way.
SocialGraphServiceImpl.java
import com.google.common.base.Function;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.Sets;
import socialgraphui.controller.SocialGraphViewController;
import socialgraphui.model.Discussion;
import socialgraphui.model.Edge;
import socialgraphui.model.Email;
import socialgraphui.model.Message;
import socialgraphui.model.Node;
import socialgraphui.model.PhoneCall;
import socialgraphui.model.SocialGraph;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
/**
*
*/
#Service(value="SGService")
public class SocialGraphServiceImpl implements SocialGraphService{
private SocialGraph socialgraph = new SocialGraph();
private CreateObjects crObjects = new CreateObjects();
public SocialGraphServiceImpl(){
this.fillGraph();
}
#Override
#Cacheable(value = "socialGraphCache")
public SocialGraph fillGraph(){
this.socialgraph = crObjects.createObjects();
return this.socialgraph;
}
}
And here is what I want to cache.
SocialGraph.java
package socialgraphui.model;
import java.io.Serializable;
import java.util.List;
public class SocialGraph implements Serializable{
private static final long serialVersionUID = -6977846672304367384L;
private List<Node> nodes;
private List<Edge> edges;
public List<Node> getNodes() {
return nodes;
}
public void setNodes(List<Node> nodes) {
this.nodes = nodes;
}
public List<Edge> getEdges() {
return edges;
}
public void setEdges(List<Edge> edges) {
this.edges = edges;
}
}
When I deploy the portlet, I don't get any errors, but generated cache file is empty.
I have same problem and it cause due to i didn't implement all object(class) that used in main object that i want to save in disk.
for more detail see this example.
public class User implements Serializable{
private Address address; // this object(class) not implements Serializable
}
so after implements for all class it works correctly.

Spring interceptor not work

I coded an interceptor as follows:
package org.mybatis.jpetstore.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.mybatis.jpetstore.annotation.CsrfTokenCheck;
import org.mybatis.jpetstore.tool.CsrfTokenTool;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public class CsrfTokenAnnotationInterceptor extends HandlerInterceptorAdapter {
#Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception {
}
#Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception {
}
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object ojbect) throws Exception {
System.out.println("======================");
//if(ojbect instanceof HandlerMethod){
CsrfTokenCheck csrfTokenCheck = ((HandlerMethod) ojbect).getMethodAnnotation(CsrfTokenCheck.class);
System.out.println("++++++++++++++++++++++");
if(csrfTokenCheck != null && !new CsrfTokenTool().verify((HttpServletRequest) request)){
response.sendRedirect("http://www.google.com");
return false;
}
//}
return true;
}
}
but it seems not work at all.(the codes depend on spring3.2)
annotation in controller:
#CsrfTokenCheck
public ModelAndView list(HttpServletRequest request,
HttpServletResponse response) throws Exception {
ModelAndView mav = new ModelAndView("category/category");
return mav;
}
interface:
package org.mybatis.jpetstore.annotation;
public #interface CsrfTokenCheck{
}
I also configued something as follows in my spring-config.xml:
<bean id="requestMappingHandlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="interceptors">
<list>
<ref bean="csrfTokenAnnotationInterceptor" />
</list>
</property>
</bean>
<bean id="csrfTokenAnnotationInterceptor" class="org.mybatis.jpetstore.interceptor.CsrfTokenAnnotationInterceptor" />
Start by fixing your annotation. It should contain at least a #Retention meta-annotation and make it available at runtime, currently it isn't and as such will also fail.
#Target({ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface CsrfTokenCheck{}
Next to that make sure you don't have an <mvc:annotation-driven /> in your configuration as that will render your explicitly configured RequestMappingHandlerMapping useless. If you are using <mvc:annotation-driven /> you should use the <mvc:interceptors /> tag to register interceptors.
Check these files:
resources/spring/spring.xml
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
...
<property name="configLocation" value="classpath:/mybatis/mybatis-config.xml"/>
</bean>
resources/mybatis/mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
...
<plugins>
<!-- Interceptor configuration -->
<plugin interceptor="com.w.pay.api.test.mvn.res.db.MybatisLogPrinter" />
</plugins>
</configuration>
Please search for interceptors in all XML files in your workspace.
I solved this by realizing that the servlet-context file already exists where the annotation driven and other interceptors are defined. After placing my interceptor definition in that file it worked like a charm.
I spent quite 1.5 day scratching my head, it turns out that spring does not like multiple locations for interceptors.

Problems with SPRING 3.0 annotated Controller

Hi im new in the spring world so i want to create my own controller using #Controller notation, but i suppose im doing something bad. Anybody can help me???
Here is my dispatch-servlet
<bean Class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
<context:component-scan base-package="hibernateTest.web" />
<context:annotation-config/>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
And here is my controller
package springapp.web;
import com.sun.msv.reader.Controller;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.LogFactory;
import org.hibernate.validator.internal.util.logging.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.portlet.ModelAndView;
import springapp.service.ProductManager;
#org.springframework.stereotype.Controller
public class HelloController {
protected final Log logger = (Log) LogFactory.getLog(getClass());
private ProductManager productManager;
#RequestMapping("/hello.htm")
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String now = (new java.util.Date()).toString();
logger.info("returning hello view with " + now);
Map<String, Object> myModel = new HashMap<String, Object>();
myModel.put("now", now);
myModel.put("products", this.productManager.getProducts());
return new ModelAndView("hello", "model", myModel);
}}
The result of running this is a 404, when The hello.jsp exist
Your controller class is in package springapp.web, while in context:component-scan you have base-package set to hibernateTest.web.
Spring cannot detect your controller, because your configuration tells it to search for annotated classes only in hibernateTest.web package.
Changing package name in context:component-scan should fix this:
<context:component-scan base-package="springapp.web" />

Autowired Field is Null

Im have been working on a example for spring MVC + Spring Security + hibernate to make a login page, but now i have come to a problem with a fuel #Autowire that keeps giving me null values. the server doesnt report any errors its just that it doesnt complete the operation.
CustomUSerDetailsService.java
package com.carloscortina.paidosSimple.service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import com.carloscortina.paidosSimple.dao.UsuarioDao;
import com.carloscortina.paidosSimple.model.Usuario;
#Service
#Transactional(readOnly=true)
public class CustomUserDetailsService implements UserDetailsService {
private static final Logger logger = LoggerFactory.getLogger(CustomUserDetailsService.class);
#Autowired UsuarioDao userDao;
#Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
logger.info(username);
Usuario domainUser = userDao.getUsuario(username);
logger.info(domainUser.getUsername());
boolean enabled = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
return new User(
domainUser.getUsername(),
domainUser.getPassword(),
enabled,
accountNonExpired,
credentialsNonExpired,
accountNonLocked,
getAuthorities(domainUser.getRol().getId()));
}
public Collection<? extends GrantedAuthority> getAuthorities(Integer rol){
List<GrantedAuthority> authList = getGrantedAuthorities(getRoles(rol));
return authList;
}
public List<String> getRoles(Integer rol){
List<String> roles = new ArrayList<String>();
if(rol.intValue() == 1){
roles.add("ROLE_DOCTOR");
roles.add("ROLE_ASISTENTE");
}else if (rol.intValue() == 2){
roles.add("ROLE_ASISTENTE");
}
return roles;
}
public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles){
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (String role : roles) {
authorities.add(new SimpleGrantedAuthority(role));
}
return authorities;
}
}
Here the field userDao keeps beign null so when i try to use userDao.getUsuario(username) the operation just doesnt continue, it doesn't report an error or similar its just gives me a 404- error
UsuarioDao.xml
package com.carloscortina.paidosSimple.dao;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.carloscortina.paidosSimple.model.Usuario;
#Repository
public class UsuarioDaoImp implements UsuarioDao {
private static final Logger logger = LoggerFactory.getLogger(UsuarioDaoImp.class);
#Autowired
private SessionFactory sessionFactory;
private Session getCurrentSession(){
return sessionFactory.getCurrentSession();
}
#Override
public Usuario getUsuario(String username) {
logger.debug("probando");
List<Usuario> userList = new ArrayList<Usuario>();
Query query = getCurrentSession().createQuery("from Usuario u where u.Username = :username");
query.setParameter("username", username);
userList = query.list();
if (userList.size() > 0){
return (Usuario) userList.get(0);
}else{
return null;
}
}
}
servlet-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
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/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<!-- Enable transaction Manager -->
<tx:annotation-driven/>
<!-- DataSource JNDI -->
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/paidos" resource-ref="true" />
<!-- Session factory -->
<beans:bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
p:dataSource-ref="dataSource"
p:hibernateProperties-ref="hibernateProperties"
p:packagesToScan="com.carloscortina.paidosSimple.model" />
<!-- Hibernate Properties -->
<util:properties id="hibernateProperties">
<beans:prop key="hibernate.dialect">
org.hibernate.dialect.MySQL5InnoDBDialect
</beans:prop>
<beans:prop key="hibernate.show_sql">false</beans:prop>
</util:properties>
<beans:bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory" />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.carloscortina.paidosSimple" />
</beans:beans>
I dont know whats missing , so any idea its welcome, thanks in advance.
Edit:
UsuarioDaoImp
package com.carloscortina.paidosSimple.dao;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.carloscortina.paidosSimple.model.Usuario;
#Repository
public class UsuarioDaoImp implements UsuarioDao {
private static final Logger logger = LoggerFactory.getLogger(UsuarioDaoImp.class);
#Autowired
private SessionFactory sessionFactory;
private Session getCurrentSession(){
return sessionFactory.getCurrentSession();
}
#Override
public Usuario getUsuario(String username) {
logger.debug("probando");
List<Usuario> userList = new ArrayList<Usuario>();
Query query = getCurrentSession().createQuery("from Usuario u where u.Username = :username");
query.setParameter("username", username);
userList = query.list();
if (userList.size() > 0){
return (Usuario) userList.get(0);
}else{
return null;
}
}
}
After trying to add a bean with UsuarioDaoImp i got this error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'usuarioServicioImp': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.carloscortina.paidosSimple.dao.UsuarioDao com.carloscortina.paidosSimple.service.UsuarioServicioImp.usuarioDao; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.carloscortina.paidosSimple.dao.UsuarioDao] is defined: expected single matching bean but found 2: usuarioDaoImp,userDao
UsuarioServiceImp
package com.carloscortina.paidosSimple.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.carloscortina.paidosSimple.dao.UsuarioDao;
import com.carloscortina.paidosSimple.model.Usuario;
#Service
#Transactional
public class UsuarioServicioImp implements UsuarioService{
#Autowired
private UsuarioDao usuarioDao;
#Override
public Usuario getUsuario(String username) {
return usuarioDao.getUsuario(username);
}
}
i think I'm short in knowledge about the subject, that why i was following an example but i ended with this, so my apologise if I'm not giving the information correctly or if im misunderstanding concepts.
spring-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
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/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<beans:bean class="com.carloscortina.paidosSimple.service.CustomUserDetailsService" id="customUserDetailsService"></beans:bean>
<security:http auto-config="true">
<security:intercept-url pattern="/sec/moderation.html" access="ROLE_ASISTENTE" />
<security:intercept-url pattern="/admin/*" access="ROLE_DOCTOR" />
<security:form-login login-page="/user-login.html"
default-target-url="/success-login.html"
authentication-failure-url="/error-login.html" />
<security:logout logout-success-url="/index.html" />
</security:http>
<security:authentication-manager>
<security:authentication-provider user-service-ref="customUserDetailsService">
<security:password-encoder hash="plaintext" />
</security:authentication-provider>
</security:authentication-manager>
</beans:beans>
How are you accessing CustomUSerDetailsService class ? I hope you haven't added this class as bean in security config file or any other spring config?
Editted:
Your service bean is annotated with #service and you have also declared it in xml, spring has created two service beans one based on #service annotation (fully populated as its autowried) and second using the xml config (in which I assume you haven't injected dao dependency explicitly), so the second one doesnt have dao object set. As you are using the bean name of the service bean declared in your security config, you are getting userDao as null on debug.
Either comment the explicit bean definition in security xml, use ref="customUSerDetailsService" directly as #service annotation already added a bean with this name in spring context.
i.e. comment/remove this line in your security config and every thing should work.
<beans:bean class="com.carloscortina.paidosSimple.service.CustomUserDetailsService" id="customUserDetailsService"></beans:bean>
When you annotate a bean with #component/#service spring adds a bean with name equals to short classname(first letter lower case), so bean with name "customUserDetailsService" already exists, defining it explicitly in xml is overriding it.
Or declare all the bean definitions (including there dependencies) explicitly it xml config
Add the dao package to the component scan
<context:component-scan base-package="com.carloscortina.paidosSimple, com.carloscortina.paidosSimple.dao" />

Resources