I'm trying to integrate Spring with Vaadin, but I can't use the #Autowired annotation in my Vaadin classes.
Firstly, I created the followed maven structure
This is my web.xml
<web-app>
<display-name>Vaadin Web Application</display-name>
<context-param>
<description>Vaadin production mode</description>
<param-name>productionMode</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/application-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class> org.springframework.web.context.request.RequestContextListener </listener-class>
</listener>
<servlet>
<servlet-name>Vaadin Application Servlet</servlet-name>
<servlet-class>com.mycompany.config.AutowiringApplicationServlet</servlet-class>
<init-param>
<description>Vaadin UI to display</description>
<param-name>UI</param-name>
<param-value>com.mycompany.ui.MyUI</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Vaadin Application Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
This is my application-context.xml
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://localhost/vaadin" />
<property name="username" value="postgres" />
<property name="password" value="tobbis" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="datasource"/>
<property name="persistenceUnitName" value="myUnit"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<jpa:repositories base-package="com.mycompany.repository"></jpa:repositories>
<context:annotation-config/>
<context:component-scan base-package="com.mycompany" />
Now I created my UserService that is within com.mycompany.services package
#Service
public class UserService {
public void saveUser(User user){
System.out.println("Test to Save");
}
}
And finally, I have my Panel where I want to inject the service
public class UserPanel extends VerticalLayout {
#Autowired
UserService service;
public UserPanel() {
// TODO Auto-generated constructor stub
Injector.inject(this);
service.saveUser();
}
}
but the result is always the same
Error creating bean with name 'com.mycompany.ui.UserPanel': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: com.mycompany.services.UserService com.mycompany.ui.UserPanel.service;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No matching bean of type [com.aiem.services.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)}
Try to declare your UserService at applicationContext.xml
<bean name="userService" class="com.mycompany.services.UserService"></bean>
As far as I know,
Injector.inject(this);
is not something from Spring, you may be mixing it with another framework.
Instead, I would make UserPanel a prototype-scoped Spring component (meaning it can be instantiated and autowired by Spring, but you remain responsible for it's lifecycle).
#Component
#Scope(SCOPE_PROTOTYPE)
public class UserPanel extends VerticalLayout {
Note that a new instance will be created anytime UserPanel is retrieved from the context (e.g. autowired in another object). It could be best to control the creation of instances yourself by explicitly invoking
context.getBean(UserPanel.class)
at the right time.
AnnotationConfigWebApplicationContext is not meant to be used with XML config. It is supposed to be used with the #Configuration annotated classes.
Since you're using an xml file for Spring config, then you should instead remove these lines from web.xml:
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
And then by default Spring will use the XmlWebApplicationContext and pick up your xml file.
I have tried the same scenario than you. At the end, the solution is at the Vaadin documentation.
Seems that the problem is that we are using Vaadin context and not Spring context, and therefore we need to do the trick showed in the documentation (SpringHelper) to obtain any bean. Outside of the Spring context, the autowiring is not goint to work.
There is an addon for enabling autowiring via annotations: http://vaadin.xpoft.ru/.
Here is the link to the Vaadin site: http://vaadin.com/addon/springvaadinintegration. Hope it helps.
Related
I'm working on a spring-mvc project built by someone else. Everything works fine when running with Tomcat on localhost using Eclipse. I have also committed some code and they have been deployed by the supervisor successfully.
However, when I run a JUnit test which is basically as follows:
package com.my.package.test;
...
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "classpath*:*/applicationContext.xml")
public class DataSynchronizationTest {
#Autowired
SomeMapper someMapper;
//some tests
}
I'm suddenly getting the error:
... org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.company.project.dao.SomeMapper] found for dependency: ...
This seems weird to me because that's exactly how someMapper is injected in the web application. For example, the following works just fine:
package com.my.package.controller;
...
#Controller
#RequestMapping("/foo")
#Scope("session")
public class FooController extends BaseController {
#Autowired
SomeMapper someMapper;
//...
}
I think I'm loading ApplicationContext correctly in this JUnit test because if I remove that #ContextConfiguration line or change it to #ContextConfiguration(locations = "/applicationContext.xml") then I would get the following error:
java.lang.IllegalStateException: Failed to load ApplicationContext
So if I'm using the same ApplicationContext (there is only one. I didn't create another one for testing), why does the injection works fine on server, but fails in JUnit test? Any help is appreciated.
Edit:
As M. Deinum said in the comment, I do have a ContextLoaderListener and a DispatcherServlet, both of which are defined in web.xml. Here is the relevant part of web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
However, someMapper lives in the applicationContext.xml (which is loaded by ContextLoaderListener) and apparently has nothing to do with the DispatcherServlet part. Here is the part of applicationContext.xml that is responsible for loading someMapper:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath:com/company/project/dao/*.xml" />
<property name="configLocation" value="classpath:MyBatis-Configuration.xml"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.company.project.dao" />
</bean>
SomeMapper.java and SomeMapper.xml are located in classpath:com/company/project/dao/, of course.
I have few parameters in web.xml file to be externalized. Application is in spring 4.0. Is there a spring way to do this?
More precisely, if I define PropertyPlaceholderConfigurer in context file, is there a way to use that for fetching properties in web.xml?
This is what I tried:
In applicationContext.xml:
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property
name="location"
value="classpath:/test.properties" />
<property
name="ignoreUnresolvablePlaceholders"
value="true" />
</bean>
Then in web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
</param-value>
</context-param>
But the below code returns param value as ${app.url}
<init-param>
<param-name>appUrl</param-name>
<param-value>${app.url}</param-value>
</init-param>
This is not possible as web.xml will be loaded before context initialization. The only solution for this is to move these properties to application server specific properties files.
I am using Tomcat and I moved this property to catalina.properties. Now it's working.
I have a Spring-based web application, with two servlets - one for MVC and one for spring-ws. There are several beans used in the application, and they are autowired using annotations. Each time the application starts, it creates 3 instances of each bean type - even though they are singleton-scoped. The #PostConstruct methods are also called three times for each of them.
I understand that there are 3 application contexts = 1 common + 2 servlets, but each bean, controller, endpoint, etc. is created three times. At least the common beans, loaded in the parent application context should be instanced only once.
The base-package attribute of component-scan points to disjoint packages.
I've used a class to dump the context information (https://gist.github.com/1347171) and it appears there are three different contexts with identical structure (same beans). Their id's are "/project/", "/project/rest", "/project/soap".
I tried commenting out the ContextLoaderListener, removing the soap servlet and their associated XML files (applicationContext & soap-servlet) and moving the common stuff into the rest servlet (so that there is only one config xml and only one component-scan), and I still get 3 instances of each bean. In this case the application context id's are "/Project/" (exact casing), "/project/" and "/project/".
web.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>soap</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<init-param>
<param-name>transformWsdlLocations</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>soap</servlet-name>
<url-pattern>/soap/*</url-pattern>
</servlet-mapping>
applicationContext.xml
<context:annotation-config/>
<context:component-scan base-package="test.common"/>
<task:annotation-driven/>
rest-servlet.xml
<mvc:annotation-driven/>
<context:component-scan base-package="test.rest"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<util:list id="beanList">
<ref bean="formHttpMessageConverter"/>
</util:list>
</property>
</bean>
<bean id="formHttpMessageConverter"
class="org.springframework.http.converter.FormHttpMessageConverter"/>
<mvc:interceptors>
<bean class="test.rest.Interceptor"/>
</mvc:interceptors>
soap-servlet.xml
<sws:annotation-driven/>
<context:component-scan base-package="test.soap"/>
<sws:dynamic-wsdl
id="service"
portTypeName="service"
locationUri="/soap/service"
targetNamespace="http://server/soap">
<sws:xsd location="/WEB-INF/SoapService.xsd"/>
</sws:dynamic-wsdl>
<sws:interceptors>
<bean id="validatingInterceptor"
class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
<property name="schema" value="/WEB-INF/SoapService.xsd"/>
<property name="validateRequest" value="true"/>
<property name="validateResponse" value="true"/>
</bean>
</sws:interceptors>
use the javax.ejb.Singleton annotation on your bean.
Well the reason is the slightly confusing documentation on spring mvc context initialization and these magical annotation defaults :(.
You probably have three copies because of the following:
your contextConfigLocation definition creates a root webapp context loading (only one per application) that is shared across all servlets. Each of your -servlet-config.xml files can access these beans but not vice versa.
Difference between applicationContext.xml and spring-servlet.xml in Spring Framework
so the second instance is coming from your -servlet application context because you defined the annotation-driven explicitly again.
Not sure which spring framework version you are using, but by defining both annotation-driven and custom request mapping adapter, you are pretty much creating two.
https://jira.spring.io/browse/SPR-8648
In fact, <mvc:annotation-driven> has all the tags to customize your adapter, check the schema which is what you want. Yet anther way to figure this out is by painful debugging in trace mode and looking at which bean is actually creating your adapter. Put a breakpoint in your adapter constructor and then look at the stack in DispatcherServlet->mapperHandler->interceptor->mapping->context->configFileLocation to see which file is creating this bean
If you do want to customize the message converters, you should be doing this:
<mvc:annotation-driven
content-negotiation-manager="contentNegotiationManager">
<mvc:message-converters register-defaults="false">
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="afterBurnerObjectMapper"/>
</bean>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
I am trying to implement applicationContextAware in my servlet.I have the data from client side coming to my servlet.From my servlet I need to pass it to the beans which has getters and setters.I have my DAO s where I have MYSQL operations.
My applicationContext.xml has
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/bazaar_admin_portal" />
<property name="username" value="usrnm" />
<property name="password" value="pwd" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg index="0">
<ref bean="dataSource" />
</constructor-arg>
</bean>
<bean
class="org.dao.impl.TestDAOimpl"
id="TestDAO">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
My web.xml contains
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<servlet>
<description></description>
<display-name>TestServlet</display-name>
<servlet-name>TestServlet</servlet-name>
<servlet-class>com.controllers.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet</servlet-name>
<url-pattern>/Test</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
And in my TestServlet under doPost method
private static ApplicationContext applicationContext = null;
public void setApplicationContext(ApplicationContext ctx)
throws BeansException {
applicationContext = ctx;
I have getters and setters class Test.Also interface TestDAO and TestDAOimpl class which implements the interface.
I want to know how do I pass the data from my servlet to the spring side...i.e set the data which will enable the TestDAOimpl to insert into my DB.
Thanks
Are you sure you don't want to use Spring WebMVC? It will handle your problem automatically.
Then try this in you POST Method (It's quite slow, init it lazily):
applicationContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
ApplicationContextAware is for beans to be aware of their application context . Read here for more info . What you could so is use WebApplicationContextUtils WebApplicationContextUtils.getRequiredWebApplicationContext(ServletContext sc) , get the application context , use getBean method and invoke the Dao.
in your servlet
#Autowired
private ApplicationContext ctx;
#Autowired
private MyDao myDao;
#Override
public void init() throws ServletException {
WebApplicationContextUtils.getWebApplicationContext(super.getServletContext()).getAutowireCapableBeanFactory().autowireBean(this);
}
Quick question based on a spring web app i am creating.
How do you go about setting up the context of the application so that you do not need to set the datasource parameters for simpleJDBC all the time and can call getSimpleJDBCTemplate().queryfor.... and it be set up with the datasource.
This is how i currently have it and it seems to go against inversion of control that spring is meant to provide as this is in every dao!
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("classpath:ApplicationContext.xml");
DataSource dataSource = (DataSource) ac.getBean("dataSource");
SimpleJdbcTemplate simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
ApplicationContext
<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-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:properties.properties"/>
</bean>
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</bean>
<bean name="SimpleJdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
<constructor-arg><ref bean="dataSource"/></constructor-arg>
</bean>
<context:annotation-config/>
</beans>
Latest Stack Trace from Tomcat log
13-Jan-2011 20:15:18 com.sun.jersey.api.core.PackagesResourceConfig init
INFO: Scanning for root resource and provider classes in the packages:
ptc.jersey.spring
13-Jan-2011 20:15:18 com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFO: Root resource classes found:
class ptc.jersey.spring.resources.LoginResource
13-Jan-2011 20:15:18 com.sun.jersey.api.core.ScanningResourceConfig init
INFO: No provider classes found.
13-Jan-2011 20:15:19 com.sun.jersey.spi.spring.container.servlet.SpringServlet getContext
INFO: Using default applicationContext
13-Jan-2011 20:15:19 com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.4 09/11/2010 10:30 PM'
13-Jan-2011 20:15:21 com.sun.jersey.spi.container.ContainerResponse mapMappableContainerException
SEVERE: The RuntimeException could not be mapped to a response, re-throwing to the HTTP container
java.lang.NullPointerException
at ptc.jersey.spring.daoImpl.UserDaoImpl.getUser(UserDaoImpl.java:43)
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">
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:ApplicationContext.xml</param-value>
</context-param>
<servlet>
<servlet-name>Jersey Spring Web Application</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>ptc.jersey.spring</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Spring Web Application</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
</web-app>
Any help would be great
Thanks
Chris
Why don't you declare the SimpleJdbcTemplate instance as well in the application context file?
For example with these bean declarations
<bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.gjt.mm.mysql.Driver"/>
<property name="url" value="dburl"/>
<property name="username" value="dbusername"/>
<property name="password" value="password"/>
</bean>
<bean name="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
<constructor-arg><ref bean="dataSource"/></constructor-arg>
</bean>
And in your web.xml to load the application context
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:ApplicationContext.xml</param-value>
</context-param>
Declare the SimpleJdbcTemplate bean in the context:
<bean name="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
<constructor-arg ref="dataSource"/>
</bean>
and use it like this:
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:ApplicationContext.xml");
SimpleJdbcTemplate simpleJdbcTemplate = (SimpleJdbcTemplate) ac.getBean("jdbcTemplate");
or in a DAO:
#Autowired
private SimpleJdbcTemplate simpleJdbcTemplate;
It is thread-safe, and therefore reusable.
What I'd recommend is that you declare your DataSource as bean and also the classes which need it and use dependency injection to introduce the DataSource to your class. As an example, your bean definition could look like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans">
<bean id="dataSource" class="...">
<!-- your dataSource config here -->
</bean>
<bean id="yourClassThatNeedsDataSource" class="com.stackoverflow.q4684102.Example">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
and the accompanying class
package com.stackoverflow.q4684102;
import javax.jdbc.DataSource;
import org.springframework.jdbc.core.simple.*;
public class Example implements YourDaoInterface {
private SimpleJdbcOperations jdbc;
public void setDataSource(DataSource ds) {
jdbc = new SimpleJdbcTemplate(ds);
}
// your DAO methods here
}
Why do it this way instead of creating a bean out of the SimpleJdbcTemplate itself?
No difference, really - some people like it the other way, some others like it this way - you wan't have a huge XML with loads of bean definitions for intermediate objects if you do it this way, that's for sure. That, of course, is up to you to decide on how you want to design your software.
If you create SimpleJdbcTemplate inside setDataSource then you are creating a template per Dao instance.
If you configure as a bean and inject into the Dao, then you can resuse the same template across the Daos - which is recommended, because its threadsafe.