I'm trying to develop a simple REST WS that connects to an embedded Neo4J DB that runs locally on my machine. First I got a simple GET operation just returning a simple String when the Service was called and that works normally. Now I'm trying to get this to really do something so I've searched a couple of tutorials on how to integrate Spring with Neo4J. The truth is I've found this to be much more tricky than what I was expecting, mainly because there's a lot of tutorials and they all look different, so there's like 100 different ways to do it and I'm trying to adapt to my solution. I'm not sure on my Annotations and also on my XML configuration files. Any help is apreciatted. May the Force be with me. :)
UPDATE_1: this is myStore servlet now
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:mvc="http://www.springframework.org/schema/mvc" 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-3.0.xsd http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="com.ruitex23.myStore" />
<jpa:repositories base-package="com.ruitex23.myStore.repositories" />
<bean name="soapOperationRepository" class="com.ruitex23.myStore.services.SoapOperationService" />
<context:annotation-config />
</beans>
The Controller
package com.ruitex23.myStore.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.ruitex23.myStore.domains.SoapOperation;
import com.ruitex23.myStore.services.SoapOperationService;
#RestController
public class SpringRestController {
#Autowired SoapOperationService operationService;
//the dummy method
#RequestMapping(value = "/hello/{name}", method = RequestMethod.GET)
public String hello(#PathVariable String name) {
String result = "Hallo " + name;
return result;
}
//the real method
#RequestMapping(value = "/soapOperation/{version}", method = RequestMethod.GET)
public SoapOperation getSoapOperationByVersion(#PathVariable("version") Integer version) {
return operationService.searchBySoapOperationVersion(String.valueOf(version));
}
}
The Repository
package com.ruitex23.myStore.repositories;
/**
*
*/
import org.springframework.data.neo4j.repository.GraphRepository;
import org.springframework.data.repository.query.Param;
import com.ruitex23.myStore.domains.SoapOperation;
/**
* #author ruitex23
*
*/
public interface SoapOperationRepository extends GraphRepository<SoapOperation> {
SoapOperation findBySoapOperationVersion(#Param("soapOperationVersion") String soapOperationVersion);
}
The Service
package com.ruitex23.myStore.services;
/**
*
*/
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruitex23.myStore.domains.SoapOperation;
import com.ruitex23.myStore.repositories.SoapOperationRepository;
/**
* #author ruitex23
*
*/
#Service
public class SoapOperationService {
#Autowired SoapOperationRepository soapOperationRepository;
public SoapOperation searchBySoapOperationVersion(String operationVersion) {
return soapOperationRepository.findBySoapOperationVersion(operationVersion);
}
}
MyStore Servlet
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" 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-3.0.xsd http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="com.ruitex23.myStore" />
//read somewhere that the interface should point to the impl
<bean name="soapOperationRepository" class="com.ruitex23.myStore.services.SoapOperationService" />
<context:annotation-config />
</beans>
web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>myStore</display-name>
<servlet>
<servlet-name>mystore</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mystore</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
And now the error related to the Autowired object.
12:05:58.649 [main] WARN o.s.w.c.s.XmlWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springRestController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.ruitex23.myStore.services.SoapOperationService com.ruitex23.myStore.controllers.SpringRestController.operationService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'soapOperationService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.ruitex23.myStore.repositories.SoapOperationRepository ruitex23.myStore.services.SoapOperationService.soapOperationRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.ruitex23.myStore.repositories.SoapOperationRepository] 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.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
The error continues on and on, but I think this the important part. If u need to see anything else of the log error let me know.
Thank in advance
You are missing the configuration for the repositories in your XML configuration file. In fact, as reported in the Creating repository instances/XML Configuration at the Spring Data Neo4j - Reference Documentation:
Each Spring Data module includes a repositories element that allows
you to simply define a base package that Spring scans for you
Now, what you need to add to add to your XML configuration file is the following snippet:
<jpa:repositories base-package="com.ruitex23.myStore.repositories" />
You have also to:
add the following schema definition in your <beans...> tag:
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
add the following schema location to your xsi:schemaLocation:
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
Related
I'm trying to inject a bean that was defined on a XML into an annotated, It is only annotated and not declared on XML, I think that is just something that I'm missing here is my *context.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:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
...
<bean id="userBusiness" class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">
<property name="jndiName" value="java:global/app-common/app-common-core/UserBusinessImpl" />
<property name="businessInterface" value="com.app.common.business.UserBusiness" />
</bean>
...
<context:annotation-config/>
<context:component-scan base-package="com.app.common.jsf" />
</beans>
Here's the component:
#Component
public class AppAuthorization {
#Autowired
private UserBusiness userBusiness;
#Autowired
private AppLogin sabiusLogin;
...
#Local
public interface UserBusiness {
User listUserByFilter(User user) throws UserBusinessException;
...
#Stateless
#Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
#Interceptors({SpringBeanAutowiringInterceptor.class})
public class UserBusinessImpl implements UserBusiness {
#Autowired
private ProgramasUsuariosDao programasUsuariosDao;
...
When I try to access the AppAuthorization Spring says that:
Could not autowire field: private com.app.common.business.UserBusiness com.app.common.jsf.AppAuthorization.userBusiness"
Seems that the annotated bean can't see the declared one, but search and seems that I only needed to add the annotation-config to the XML, is this right? Hope some can help me.
EDIT
I think that this is the most important part of the stack trace:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.app.common.business.UserBusiness] 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:997)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:867)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:779)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:503)
... 201 more
Following the steps on the context creation I see no bean registered tha can be seen by annotations just when springs creates the context based on the xml is that I can see all the beans that wre created.
EDIT 2
This is the beanRefContext.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.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="contexts" class="com.app.common.spring.ClassPathXmlApplicationContext" />
</beans>
This is the class that loads the XML context files:
public class ClassPathXmlApplicationContext extends org.springframework.context.support.ClassPathXmlApplicationContext {
public ClassPathXmlApplicationContext() {
super((System.getProperty("module.context.file").split(";")));
}
}
As I said, the annotated beans cannot see the XML ones so, spring cannot autowire them.
EDIT 3
I don't have a #Configuration bean (I'm not using AnnotationConfigApplicationContext), all the config is in the XML and if I try to create one the server doesn't start, it's a legacy system with spring 3.2 and EJB 3.0 and I can't change this aspect now.
Thanks in advance!
I think you missed to specify #Component annotation for the UserBusiness class
EDIT:
Can you make the component-scan config to com.app.common instead of com.app.common.jsf
What seems to work was create a #Configuration import the xml that have the bean declaration (with #ImportResource) and don't scan it's package in XML.
For some reason if I declare the file in the XML the server don't start, it's strange because I have no definition anywhere that I'm using an annotation configuration.
ERROR
ERROR Bundle [za.co.multichoice.eventtracker.logging] Error creating
bean with name
'org.eclipse.gemini.blueprint.service.exporter.support.OsgiServiceFactoryBean#0':
Initialization of bean failed; nested exception is
org.springframework.beans.TypeMismatchException: Failed to convert
property value of type 'java.lang.String' to required type
'java.lang.Class[]' for property 'interfaces'; nested exception is
java.lang.IllegalArgumentException: Cannot find class
[com.soa.message.handler.HandlerFactory]
LoggingHandlerFactory class
package za.co.multichoice.eventtracker.logging;
import com.digev.fw.exception.GException;
import com.soa.message.handler.HandlerContext;
import com.soa.message.handler.HandlerFactory;
import com.soa.message.handler.HandlerRole;
import com.soa.message.handler.MessageHandler;
public class LoggingHandlerFactory implements HandlerFactory {
public MessageHandler create(HandlerContext context, HandlerRole role)
throws GException {
return new LoggingHandler();
}
}
OSGI xml file
<?xml version="1.0" encoding="UTF-8"?>
<!--
Spring definition for the logging handler OSGi integration.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd">
<osgi:service interface="com.soa.message.handler.HandlerFactory">
<osgi:service-properties>
<entry key="name" value="examples.logging.factory"/>
<entry key="scope" value="all"/>
<entry key="role" value="provider"/>
</osgi:service-properties>
<bean class="za.co.multichoice.eventtracker.logging.LoggingHandlerFactory"/>
</osgi:service>
</beans>
I've been getting this exception in the console.I tried a lot and could not resolve the issue
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'reportsController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private main.java.com.shc.mso.service.VendorService main.java.com.shc.mso.controllers.ReportsController.vendorsservice; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [main.java.com.shc.mso.service.VendorService] 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.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4760)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5184)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1396)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1386)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private main.java.com.shc.mso.service.VendorService main.java.com.shc.mso.controllers.ReportsController.vendorsservice; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [main.java.com.shc.mso.service.VendorService] 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.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
... 22 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [main.java.com.shc.mso.service.VendorService] 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)
... 24 more
I tried looking at all the answers but could not figure out the solution.
ReportsController.class
package main.java.com.shc.mso.controllers;
import java.util.ArrayList;
import java.util.List;
import main.java.com.shc.mso.model.PandLReport;
import main.java.com.shc.mso.model.Vendor;
import main.java.com.shc.mso.service.PandLService;
import main.java.com.shc.mso.service.VendorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.google.gson.Gson;
/*
*
* This is the Reports controller class.
* It invokes several methods present in Service layer; which in turn invokes methods present in DAO layer.
* It contains methods which creates jqGrid data, models, validations etc.
*
* */
#Controller
public class ReportsController {
//Logger myLog = LogManager.getLogger(ReportsController.class);
#Autowired
private VendorService vendorsservice;
#RequestMapping(value="/pandlreport", method = RequestMethod.GET)
public ModelAndView listEmployees() {
Gson gson = new Gson();
List list=new ArrayList<String>();
for (Vendor v:vendorsservice.listVendors()){
String json = new String();
json = gson.toJson(v);
list.add(json);
}
System.out.println(list.toArray());
ModelAndView modelAndView = new ModelAndView("employeesList");
modelAndView.addObject("employeesList", list);
System.out.println(modelAndView);
return modelAndView;
}
}
VendorService.class
package main.java.com.shc.mso.service;
import java.util.ArrayList;
import main.java.com.shc.mso.model.Vendor;
public interface VendorService{
public ArrayList<Vendor> listVendors();
}
VendorServiceImpl.class
package main.java.com.shc.mso.service;
import java.util.List;
import main.java.com.shc.mso.dao.VendorDao;
import main.java.com.shc.mso.model.Vendor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service("vendorService")
#Transactional
public class VendorServiceImpl {
#Autowired(required=true)
private VendorDao vendorDao;
#Transactional
public List<Vendor> listVendors(){
return vendorDao.listVendors();
}
}
Spring.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.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/lang
http://www.springframework.org/schema/lang/spring-lang.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- Activates various annotations to be detected in bean classes -->
<mvc:annotation-driven />
<context:component-scan base-package="main.java.com.shc.mso.controllers" />
<context:component-scan base-package="main.java.com.shc.mso.dao" />
<context:component-scan base-package="main.java.com.shc.mso.model" />
<context:component-scan base-package="main.java.com.shc.mso.service" />
<context:component-scan base-package="main.java.com.shc.mso.util" />
<!-- Forwards requests to the "/" resource to the "welcome" view -->
<mvc:view-controller path="/" view-name="login"/>
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources/ directory -->
<mvc:resources mapping="/resources/**" location="/resources/" />
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- View Resolver for Excel Documents -->
<bean id="nonJSPViewResolver" class="org.springframework.web.servlet.view.XmlViewResolver">
<property name="order" value="0" />
<property name="location" value="/WEB-INF/spring/spring-excel-views.xml" />
</bean>
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
<!-- Use SpringException when it is invoked-->
<!-- Use defaultErrorView when any other exception occurs -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="com.shc.mso.util.SpringException">
ExceptionPage
</prop>
</props>
</property>
<property name="defaultErrorView" value="error"/>
</bean>
</beans>
import main.java.com.shc.mso.dao.VendorDao;
import main.java.com.shc.mso.model.Vendor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service("vendorService")
#Transactional
public class VendorServiceImpl {
#Autowired(required=true)
private VendorDao vendorDao;
#Transactional
public List<Vendor> listVendors(){
return vendorDao.listVendors();
}
}
fix VendorServiceImpl as following
#Service
public class VendorServiceImpl implements VendorService{
#Autowired
private VendorDao vendorDao;
#Transactional
public List<Vendor> listVendors(){
return vendorDao.listVendors();
}
}
then in controller use
#Autowired
VendorService vendorService;
and call method as
vendorService.listVendors();
and in spring xml keep only the following line. you dont need all five
<context:component-scan base-package="main.java.com.shc.mso" />
As exception suggest NoSuchBeanDefinitionException: No qualifying bean of type [main.java.com.shc.mso.service.VendorService] found, you didn't annotate VendorService class as a service which could be register with spring container.
I guess this is just a simple mistake VendorServiceImpl should implement the VendorService interface.
#Autowire is done by type and in the code above VendorServiceImpl is not of type VendorService
See also
Inject and Resource and Autowired annotations
I'd like to test some services that them themself contain other autowired services. But these "external" services are not required for the test itself.
How can I create a test setup, eg for the following example?
package de.myapp.service;
#Service
public class MyServiceDelegator {
#Autowired
private List<ServiceInterface> services;
public ServiceInterface delegate(String id) {
//routine to find the right ServiceInterface based on the given id
}
}
#Service
public class MyService implements ServiceInterface {
}
#Service
public class MyCustomService implements ServiceInterface {
//that is the problem during testing
#Autowired
private de.myapp.repository.SomeDao dao;
}
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("applicationContext.xml")
public class ServiceDelegatorTest {
#Autowired
private ApplicationContext ac
#Test
public void testDelegator() {
MyServiceDelegator dg = ac.getBean(MyServiceDelegator.class);
ac.delegate("test");
}
}
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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"
xsi:schemaLocation="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">
<context:component-scan base-package="de.myapp.service" />
</beans>
Problem: All services that contain autowired dependencies from packages that are not scanned within the JUnit test (like MyCustomService), will throw an Exception:
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type [SomeDao] 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:1103)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:963)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
... 57 more
You can use Springockito to add mocked service implementations to your test application context.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mockito="http://www.mockito.org/spring/mockito"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
http://www.mockito.org/spring/mockito
http://www.mockito.org/spring/mockito.xsd">
<context:component-scan base-package="de.myapp.service" />
<mockito:mock id="dao" class="de.myapp.repository.SomeDao" />
</beans>
The problem is that SomeDao is not being picked up by component scanning because it's not under the de.myapp.service package.
You have explicitly stated that the package for component scanning is de.myapp.service.
I sugggest you make the following change:
<context:component-scan base-package="de.myapp" />
That way all the code under de.myapp will be eligible for component scanning.
If you want to avoid including all your code in component scanning you could do the following:
<context:component-scan base-package="de.myapp.service, de.myapp.repository" />
I have user service that treat user entity, and #Autowired in user controller class before use user service. so, I got the error:
Unsatisfied 'required' dependency of type [class com.yes.service.UserService]. Expected at least 1 matching bean
here the codes:
userService
package com.yes.service;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.yes.domain.User;
import com.yes.repository.RoleRepository;
import com.yes.repository.UserRepository;
#Service
public class UserService {
#Autowired
private UserRepository userRepository;
#Autowired
private RoleRepository roleRepository;
public User create(User user) {
user.setId(UUID.randomUUID().toString());
user.getRole().setId(UUID.randomUUID().toString());
// We must save both separately since there is no cascading feature
// in Spring Data MongoDB (for now)
roleRepository.save(user.getRole());
return userRepository.save(user);
}
public User read(User user) {
return user;
}
public List<User> readAll() {
return userRepository.findAll();
}
public User update(User user) {
User existingUser = userRepository.findByUsername(user.getUserName());
if (existingUser == null) {
return null;
}
existingUser.setFirstName(user.getFirstName());
existingUser.setLastName(user.getLastName());
existingUser.getRole().setRole(user.getRole().getRole());
// We must save both separately since there is no cascading feature
// in Spring Data MongoDB (for now)
roleRepository.save(existingUser.getRole());
return userRepository.save(existingUser);
}
public Boolean delete(User user) {
User existingUser = userRepository.findByUsername(user.getUserName());
if (existingUser == null) {
return false;
}
// We must delete both separately since there is no cascading feature
// in Spring Data MongoDB (for now)
roleRepository.delete(existingUser.getRole());
userRepository.delete(existingUser);
return true;
}
}
userController (where i use the userService, and the problem is)
#Controller
#RequestMapping("/users")
public class UserController {
#Autowired
private UserService service;
#RequestMapping
public String getUsersPage() {
return "users";
}
#RequestMapping(value="/records")
public #ResponseBody UserListDto getUsers() {
UserListDto userListDto = new UserListDto();
userListDto.setUsers(service.readAll());
return userListDto;
}
#RequestMapping(value="/get")
public #ResponseBody User get(#RequestBody User user) {
return service.read(user);
}
#RequestMapping(value="/create", method=RequestMethod.POST)
public #ResponseBody User create(
#RequestParam String username,
#RequestParam String password,
#RequestParam String firstName,
#RequestParam String lastName,
#RequestParam Integer role) {
Role newRole = new Role();
newRole.setRole(role);
User newUser = new User();
newUser.setUserName(username);
newUser.setPassword(password);
newUser.setFirstName(firstName);
newUser.setLastName(lastName);
newUser.setRole(newRole);
return service.create(newUser);
}
#RequestMapping(value="/update", method=RequestMethod.POST)
public #ResponseBody User update(
#RequestParam String username,
#RequestParam String firstName,
#RequestParam String lastName,
#RequestParam Integer role) {
Role existingRole = new Role();
existingRole.setRole(role);
User existingUser = new User();
existingUser.setUserName(username);
existingUser.setFirstName(firstName);
existingUser.setLastName(lastName);
existingUser.setRole(existingRole);
return service.update(existingUser);
}
#RequestMapping(value="/delete", method=RequestMethod.POST)
public #ResponseBody Boolean delete(
#RequestParam String username) {
User existingUser = new User();
existingUser.setUserName(username);
return service.delete(existingUser);
}
}
spring-data.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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-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/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.1.xsd">
<context:property-placeholder
properties-ref="deployProperties" />
<!-- MongoDB host -->
<mongo:mongo host="${mongo.host.name}" port="${mongo.host.port}" />
<!-- Template for performing MongoDB operations -->
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"
c:mongo-ref="mongo" c:databaseName="${mongo.db.name}" />
<!-- Activate Spring Data MongoDB repository support -->
<mongo:repositories base-package="com.yes.repository" mongo-template-ref="mongoTemplate"/>
<!-- Service for initializing MongoDB with sample data using MongoTemplate -->
<bean id="initMongoService" class="com.yes.service.InitMongoService" init-method="init"/>
</beans>
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"
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">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<context:component-scan base-package="com.yes.controller"/>
<!-- 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>
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:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<context:property-placeholder
properties-ref="deployProperties" />
<!-- Activates various annotations to be detected in bean classes -->
<context:annotation-config />
<!-- Scans the classpath for annotated components that will be auto-registered
as Spring beans. For example #Controller and #Service. Make sure to set the
correct base-package -->
<context:component-scan base-package="com.yes.domain"/>
<context:component-scan base-package="com.yes.dto"/>
<context:component-scan base-package="com.yes.service"/>
<!-- Configures the annotation-driven Spring MVC Controller programming
model. Note that, with Spring 3.0, this tag works in Servlet MVC only! -->
<mvc:annotation-driven />
<mvc:resources mapping="/resources/**" location="/resources/" />
<!-- Imports datasource configuration -->
<import resource="spring-data.xml" />
<bean id="deployProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean"
p:location="/WEB-INF/spring/spring.properties" />
the error stack:
ERROR: org.springframework.web.servlet.DispatcherServlet - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.yes.service.UserService com.yes.controller.UserController.service; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.yes.service.UserService] 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.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287)
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/applicationContext.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
EDIT: the question is after fix the errors written in Sotirios Delimanolis answer and comment.
What is the problem cause the error?
Answer: The problem was what was described in Sotirios Delimanolis answer. The Exact solution described in comments on his answer
thank you
Your application context and servlet context are component scanning over the same packages.
Your application context
<context:component-scan base-package="com.yes" />
Versus everything in servlet context
<context:component-scan base-package="com.yes.service"/>
<context:component-scan base-package="com.yes.controller"/>
<context:component-scan base-package="com.yes.domain"/>
<context:component-scan base-package="com.yes.repository"/>
<context:component-scan base-package="com.yes.dto"/>
So some beans will be overriden. You don't want this. Your servlet context should scan for #Controller beans. Your application context should scan for everything else, but don't make your application context scan for things already scanned by your child (imported) data context. Fix your package declarations so all of these are disjoint.