I am new to Spring, and have a simple problem.
I have written a simple controller with a simple constructor, annotated as shown below.
#Controller
public class LoginController
{
private LoginService loginService;
#Inject
public LoginController(LoginService loginService)
{
System.out.println("LoginController constructor - initializing login service");
this.loginService = loginService;
}
When I try to access my web app in a browser, I get the following error:
No default constructor found;
When I replace the #Inject annotation with the #Autowired annotation, it works. Can anyone explain why? Everything I've read says that have identical behavior. I'm using Tomcat 6.0.43.
Also, below is my spring dispatcher servlet xml:
<mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:annotation-driven/>
<context:component-scan base-package="com.rockwell_collins.webquery"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
You must be missing the JavaEE Inject API from your runtime classpath. Spring will only look for #Inject if the class is found in the classpath.
You can get it from Maven here and add it to your runtime classpath (manually or through dependencies).
Related
I'm trying to make dependencies injection for DAO and services. But I get stuck with an error "cannot find bean for metier". Here is my controller code:
#Autowired
#Qualifier("metier")
private MetierInterface metierInterface;
And my applicationContext.xml
<bean id="dao" class="com.act.cours.dao.DaoImplement"></bean>
<bean id="metier" class="com.act.cours.metier.MetierImplement">
<property name="dao" ref="dao"></property>
</bean>
I have interfaces DaoInterface.java, MetierInterface.java and implementing classes DaoImplement.java, MetierImplement.java.
I am refering to Spring AOP by Mkyong http://www.mkyong.com/spring/spring-aop-example-pointcut-advisor/
It worked when tried running from main (i.e. App.java) as given on above link,
I want to integrate it in restful webservice where i have multiple service like CutomerService in mkyong's example.
For example i have controller which calls CustomerService,
#RestController
#RequestMapping(value = "/customer")
public class CustomerController{
#Autowired CustomerService customerService;
#RequestMapping(value = "/getCustomer", method = RequestMethod.GET")
public ResponseEntity<CommonResponse> getService(){
customerService.printName();
}
}
It didn't worked.
i have tried this also:
#Autowired
private ProxyFactoryBean customerServiceProxy;
#RequestMapping(value = "/getCustomer", method = RequestMethod.GET")
public ResponseEntity<CommonResponse> getService(){
CustomerService customerService = (CustomerService) customerServiceProxy
.getTargetSource().getTarget();
customerService.printName();
}
}
this dosent work either.
Any Solution for this?
my bean-config.xml is same as mkyong's example.
It worked ! Just need to change proxy class from "org.springframework.aop.framework.ProxyFactoryBean" to
"org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"
Auto proxy creator identifies beans to proxy via a list of names. So we don,t need to specify target bean instead list of beans can be specified and it will intercept automatically.
My config look as below:
<bean id="adviceAround" class="com.tdg.ess.semantic.event.log.AdviceAround" />
<!-- Event logging for Service -->
<bean id="testServicePointCut" class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedNames">
<list>
<value>process</value>
</list>
</property>
</bean>
<bean id="testServiceAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="pointcut" ref="testServicePointCut" />
<property name="advice" ref="adviceAround" />
</bean>
<bean
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<!-- Differnt beans which have certain service defined like CustomerService-->
<value>testService1</value>
<value>testService2</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>testServiceAdvisor</value>
</list>
</property>
</bean>
Thanks everyone for looking into.
I have a spring boot application where I am trying to convert the following spring xml config to java config:
<bean id="pageDAO" factory-bean="springWSDaoFactory"
factory-method="createPageDAO" lazy-init="true">
<constructor-arg type="java.lang.String" value="${cds.host}" />
<constructor-arg type="java.lang.Integer" value="${cds.port}" />
</bean>
<!-- CoreApi + plugins configuration -->
<import resource="classpath:coreAPI_SpringWSContext.xml"/>
<bean name="springWSDaoFactory" class="com.blan.torque.dao.springws.SpringWSDAOFactory" lazy-init="true">
<property name="serviceVersion" value="${service.version}"/>
<property name="securityKey" value="${service.key}"/>
</bean>
Here's what I have for javaconfig so far:
#Bean
public PageDAO pageDAO() {
return springWSDAOFactory().createPageDAO(null, null);
}
#Bean
public SpringWSDAOFactory springWSDAOFactory() {
SpringWSDAOFactory springWSDAOFactory = new SpringWSDAOFactory();
springWSDAOFactory.setServiceVersion(null);
springWSDAOFactory.setSecurityKey(null);
return springWSDAOFactory;
}
I have no idea how to implement <import resource...../> in Java let alone import the variables like ${cds.host}. I've put null everywhere as place holders. But any ideas on how to do this with annotations?
In your configuration class you can use the annotation #ImportResource instead of <import resource... />.
To read Strings from a property file, try to declare an String using #Value and the use the previously declared string.
For example:
#Value("${service.version}")
private String serviceVersion;
Then using it as parameter
springWSDAOFactory.setServiceVersion(this.serviceVersion);
I hope have helped you.
I'm trying to run some tests for my controller but somehow the #Autowire annotation is not working.
Here is what I'm trying to do:
#WebAppConfiguration
#ContextConfiguration("/WEB-INF/spring/app-config.xml")
public class ClientsTest {
private Client client = new Cliente();
#Test
public void test() {
BindingResult result = mock(BindingResult.class);
ClientController clientController = new ClientController();
ModelAndView model = clientController.regClient(client, result);
Assert.assertEquals("success", model.getViewName());
}
}
#Controller
public class ClientController {
#Autowired private ClientService clientService;
#RequestMapping(value="/regClient.html", method = RequestMethod.POST)
public ModelAndView regClient(#ModelAttribute("client") #Valid Client client, BindingResult result){
ModelAndView model = new ModelAndView();
if(result.hasErrors())
{
model.setViewName("error");
}
else
{
model = clientService.regClient(client);
model.setViewName("success");
}
return model;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- Scans the classpath of this application for #Components to deploy as beans -->
<context:component-scan base-package="com.app.app_v2.web" />
<!-- Configures the #Controller programming model -->
<mvc:annotation-driven conversion-service="conversionService"/>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>client</value>
</list>
</property>
</bean>
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatters">
<set>
<ref bean="clientFormatter"/>
</set>
</property>
</bean>
<bean id="clientFormatter" class="com.app.app_v2.spring.ClientFormatter"/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<bean id="clientService" class="com.app.app_v2.services.ClientService"/>
</beans>
As far as I know the clientService is null and this is why I'm getting the exception.
Because I don't know much about running test I'm asking for your help.
Your immediate problem about #Autowire not working is related to the fact that you're explicitly instantiating the clientController, and not through Spring framework. If you want the class to be a Spring bean you need to let the Spring framework manage its lifecycle, only than the dependency injection will kick-in, and all the spring beans annotated with #Autowire will be injected. Moreover, the test should be run with spring runner SpringJUnit4ClassRunner
Note that this is not necessary, cause with your test you can go two ways. More towards unit testing, by mocking your clientService e.g. via EasyMock or Mockito. Your currently posted test looks more geared towards that way. To learn how to complete your test take a look at this blog post
On the other hand, you can go for an integration test. Since version 3.2 Spring MVC offers test module which should really be the way to write integration test against Spring MVC. You can follow a great blog series backed with source code to learn how to do it.
I am attempting to setup a very simple base configuration for a spring web application that can handle the following cases:
map resource root requests to /index, eg / maps to /index, /resource/ maps to /resource/index
map /static/** to /static/ (this is a resources view - css,js,images)
handle some specific request paths with controller mappings
map all other requests to a url based view, eg /resource/page maps to /WEB-INF/views/resource/page.jsp
In my current configuration what I have is:
<mvc:annotation-driven/>
<mvc:default-servlet-handler/>
<mvc:resources mapping="/static/**" location="/static/"/>
<mvc:view-controller path="/" view-name="index"/>
which works for static resources and root requests (/) but not for resource based root requests (/resource/). When attempting to handle all other requests (**/) I break handling of the static resources.
<mvc:view-controller path="**/*" />
Is there a way to do all of these things at the same time? It doesn't need to be an xml only solution, I'm fine with a code configuration or hybrid solution.
I have managed to find a solution by implementing my own Controller and Config.
view-servlet.xml
<mvc:resources mapping="/static/**" location="/static/"/>
<context:component-scan base-package="com.example.web.view"/>
com.example.web.view.ViewConfig
#Configuration
public class ViewConfig {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver vr = new InternalResourceViewResolver();
vr.setPrefix("/WEB-INF/views/");
vr.setSuffix(".jsp");
return vr;
}
#Bean RequestMappingHandlerMapping requestMappingHandlerMapping(){
return new RequestMappingHandlerMapping();
}
#Bean RequestMappingHandlerAdapter requestMappingHandlerAdapter(){
RequestMappingHandlerAdapter adapter = new RequestMappingHandlerAdapter();
adapter.setOrder(2); //process after mvc:resources
return adapter;
}
}
com.example.web.view.ViewController
#Controller
public class ViewController {
#RequestMapping(value = "**/")
public String all(HttpServletRequest request) {
String path = request.getRequestURI().replace(request.getContextPath(),"");
return path.endsWith("/") ? path +"index" : path;
}
}
The magic was with setting the order value on the adaptor in ViewConfig. Spring creates a default mapping handler that all RequestMappings found by component-scan are added to. The reason why my initial setup failed was that the ordering of this handler is to match before the one registered by mvc:resources. Creating my own adaptor and setting its order to be processed after mvc:resources allowed both to work.
Information regarding this can found in the spring documentation 19.9.1 Setting up the dispatcher for annotation support.
Of course the ViewConfig can also be implemented purely in xml:
<mvc:resources mapping="/static/**" location="/static/"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="order" value="2"/>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
<context:component-scan base-package="com.example.web.view"/>
Update: Changed to RequestMappingHandlerMapping and RequestMappingHandlerAdapter from DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter to reflect changes made in Spring 3.1.x and above.