Important Notice - Forums is archived
To simplify things and help our users to be more productive, we have archived the current forum and focus our efforts on helping developers on Stack Overflow. You can post new questions on Stack Overflow or join our Discord channel.

Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.
Spring integration helper class
I've come up with (IMHO) a somewhat cleaner way to integrate with Spring than shown in the FAQ (see ticket #4132) . I'm curious if other folks have comments.
The basic idea is if com.example.MyApplication is your Application subclass, then you use this new class AutowiringApplicationServlet (visible here)to automatically wire up your application:
<bean id="applicationServlet" class="org.springframework.web.servlet.mvc.ServletWrappingController"
p:servletClass="com.example.AutowiringApplicationServlet">
<property name="initParameters">
<props>
<prop key="application">com.example.MyApplication</prop>
</props>
</property>
</bean>
When it gets created, your MyApplication will be automatically configured from the containing application context, i.e., any @Autowired, @Required annotations and interfaces such as BeanFactoryAware will be respected, just as if the bean had been defined directly in the application context.
This is the cleanest and simplest way to do it I've found... are there even better/cleaner ways out there? Thanks.
You can autowire your Application class as your example shows, but how about other classes? In a large web app, you will no doubt have a lot of CustomComponents and other classes which you will need to autowire.
There's a project in incubator which uses the same methods you do. It provides autowiring by passing a SpringAwareApplication reference through constructors which take care of the autowiring:
http://dev.vaadin.com/browser/incubator/SpringIntegration/trunk
Just a while back I was considering on improving the project by making the autowiring through a static method which has access to Spring. But then I got the <context:spring-configured> to work with help from Petri Hakala and Henri Sara and it's been a lot easier to work with. Here's a thread where we discussed it:
http://vaadin.com/forum/-/message_boards/message/80732
In short, the FAQ way feels superior to me.
Valtteri Pirttilä: You can autowire your Application class as your example shows, but how about other classes? In a large web app, you will no doubt have a lot of CustomComponents and other classes which you will need to autowire.
You just stick them in your application context... the same one (or a parent).
In other words, everything is setup just like a normal Spring MVC web application, with ContextLoaderListener, DispatcherServlet, etc. The AutowiringApplicationServlet just serves to connect your Application to the Spring context that it's already living within.
Here's the setup I'm using:
web.xml
|
+-- ContextLoaderListener
| |
| +-- applicationContext.xml <-----+
| | |
| +-- Hibernate SessionFactory |
| | |
| +-- DAO beans parent
| | |
| +-- Whatever other beans |
| |
+-- DispatcherServlet |
| |
+-- dispatcher-servlet.xml >-----+
|
+-- ServletWrappingController
| |
| +-- AutowiringApplicationServlet
| |
| +-- MyApplication
|
+-- SimpleUrlHandlerMapping
|
+-- Whatever other beans
This is the normal Spring MVC setup.
The Vaadin Application (MyApplication in the example) acts just like any other bean in the dispatcher-servlet.xml application context. Everything works just like a normal Spring MVC setup... which is the whole point, right?
Specifically, this kind of thing works:
public class HelloWorld extends Application {
@Autowired
private UserDAO userDAO;
@Override
public void init() {
Window mainWindow = new Window("HelloWorld Demo");
Label label = new Label("userDAO = " + this.userDAO);
mainWindow.addComponent(label);
setMainWindow(mainWindow);
}
}
For completeness, here's some snippets from web.xml:
<!-- Spring context loader -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring dispatcher servlet -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/myapp/*</url-pattern>
</servlet-mapping>
and applicationContext.xml:
<!-- Hibernate session factory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
p:dataSource-ref="dataSource" p:configLocation="classpath:hibernate.cfg.xml">
<!-- Find DAO beans -->
<context:component-scan base-package="com.example.dao.hibernate"/>
and dispatcher-servlet.xml:
<!-- Spring annotation support -->
<context:annotation-config/>
<!-- Vaadin application servlet -->
<bean id="helloWorldController" class="org.springframework.web.servlet.mvc.ServletWrappingController"
p:servletClass="com.example.AutowiringApplicationServlet">
<property name="initParameters">
<props>
<prop key="application">com.example.HelloWorld</prop>
<prop key="productionMode">true</prop>
</props>
</property>
</bean>
<!-- Map URIs to web controllers -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="urlMap">
<map>
<entry key="/hello" value-ref="helloWorldController"/>
<entry key="/UIDL/**/*" value-ref="helloWorldController"/>
</map>
</property>
</bean>
Again, this is all just the normal (to me anyway) Spring MVC setup.
Archie, would you mind posting complete versions of your .xml files (web, applicationContext and dispatcher-servlet) for your example?
I'm new to Spring MVC (but not to Spring), Web applications and Vaadin, and I'm having trouble getting an example based on your post running. Everything appears to be created properly (logging shows all the beans are being created), but when Vaadin runs the application class, it dies on a NullPointerException, because a bean that should have been injected into the main class is not there.
I'm wondering if I've got something my versions of the files that is messing something up, or maybe I'm missing something?
Thanks, Maury
I managed to figure it out. As I suspected, I had extra code in the web.xml files that was getting in the way. Specifically, I still had the default Vaadin <servlet> entries in the file. Once I removed those, things were working as expected.
I would still like to see your .xml files, though.
Thanks, Maury
Maury Hammel: I would still like to see your .xml files, though.
Sure.. I've built a little example project that builds a WAR file. See attachment to this post.
-Archie
Very interesting.
There are definite upsides to this kind of integration. One thing I really like is that you don't need to mess with application wide xml configuration just to integrate with Vaadin, it acts like just another servlet. This should make it easier to add Vaadin to existing projects and use other technologies besides Vaadin.
Thumbs up for you Archie!
Thanks Archie. I've downloaded the file and I'll be looking at it later.
Maury
FYI,
The demo.zip that I uploaded demonstrates the Spring "MVC" approach using the DispatcherServlet, URL mappers, and Spring "controller" beans.
You can also do a simpler thing, which is to map the AutowiringApplicationServlet directly into your web.xml. With this approach, you still get your applicationContext.xml thanks to Spring's ContextLoaderListener, but there's no DispatcherServlet involved... and so your web.xml just looks like this:
<web-app 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"
version="2.5">
<display-name>Vaadin+Spring Demo #2</display-name>
<description>Vaadin+Spring Demo #2</description>
<!-- Spring context loader -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Vaadin servlet -->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.example.AutowiringApplicationServlet</servlet-class>
<init-param>
<param-name>application</param-name>
<param-value>com.example.HelloWorld</param-value>
</init-param>
<init-param>
<param-name>productionMode</param-name>
<param-value>false</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
This eliminates the "extra hop" through the DispatcherServlet.
I've attached this even simpler example as demo2.zip.
-Archie
Thanks Archie!
Those solutions looks very good for me also. Tomorrow I have to test that demo2 with vaadin Portlet 2.0. I am trying to get my Service connected to application class.
Hi
I am new to Vaadin. My current application uses spring mvc, security etc. Before I invest time in Vaadin, I want to know any problem to integrate spring mvc and spring security with Vaadin.
thanks a lot for any feedback!
Archie,
Absolutely wonderful. I just started investigating Vaadin, and I did NOT like the idea of having to rework my entire application just to integrate it. Right now, everything in my app goes through Spring Framework, Spring MVC and Spring Security, and I didn't want to have to invert things by making a Vaadin-based servlet be the main dispatcher. I only plan on sprinkling parts of my application with Vaadin and leaving everything else alone, so by doing it your way I get the best of both worlds. IMHO, it should go like this: Spring -> Vaadin, and not Vaadin -> Spring.
Thank you so much for the integration work.
Regards,
Michael
Thanks for the idea!
Here's the same for Portlet 2.0 env.
package foo.bar;
import javax.portlet.*;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.web.portlet.context.PortletApplicationContextUtils;
import com.vaadin.Application;
import com.vaadin.terminal.gwt.server.AbstractApplicationPortlet;
public class AutowiringApplicationPortlet extends AbstractApplicationPortlet {
private ApplicationContext springContext;
private Class<? extends Application> applicationClass;
@Override
public void init(PortletConfig config) throws PortletException {
super.init(config);
springContext = PortletApplicationContextUtils.getRequiredWebApplicationContext(config.getPortletContext());
final String applicationClassName = config.getInitParameter("application");
if (applicationClassName == null) {
throw new PortletException("Application not specified in portlet parameters");
}
try {
applicationClass = (Class<? extends Application>) getClassLoader().loadClass(applicationClassName);
} catch (final ClassNotFoundException e) {
throw new PortletException("Failed to load application class: "+applicationClassName);
}
}
protected ApplicationContext getSpringContext() {
return springContext;
}
protected final AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws PortletException {
try {
return getSpringContext().getAutowireCapableBeanFactory();
} catch (IllegalStateException e) {
throw new PortletException("Containing context "+getSpringContext()+" is not autowire-capable", e);
}
}
@Override
protected Class<? extends Application> getApplicationClass() {
return applicationClass;
}
@Override
protected Application getNewApplication(PortletRequest request) throws PortletException {
Class<? extends Application> clazz = getApplicationClass();
try {
return (Application) getAutowireCapableBeanFactory().createBean(clazz);
} catch (BeansException e) {
throw new PortletException(e);
}
}
}
And to portlet.xml
<portlet>
<portlet-name>foo</portlet-name>
<display-name>bar</display-name>
<portlet-class>[b]foo.bar.AutowiringApplicationPortlet[/b]</portlet-class>
<init-param>
<name>application</name>
<value>foo.bar.ApplicationClass</value>
</init-param>
<init-param>
<name>widgetset</name>
<value>com.vaadin.portal.gwt.PortalDefaultWidgetSet</value>
</init-param>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<supported-locale>en-US</supported-locale>
<supported-locale>fi</supported-locale>
</portlet>
(Sorry for reviving this thread, if anyone takes offense)
What about the scope of these Vaadin components when you have them managed by Spring? Surely they'd have to be scoped on "prototype" in order not to share component state across sessions? Will everything be cleaned up correctly when sessions expire?
Tom Bruggeman: (Sorry for reviving this thread, if anyone takes offense)
That's fine. Forum is open for everyone and everyone is welcomed to comment.
What about the scope of these Vaadin components when you have them managed by Spring? Surely they'd have to be scoped on "prototype" in order not to share component state across sessions? Will everything be cleaned up correctly when sessions expire?
Indeed you are right here. Although the original approach (configuration files, AutowiringApplicationServlet) aim to populate application-wide beans (like services) into Vaadin application. But of course you can use Spring to create session-wide beans, and you need "prototype" option for these beans. In my application I need to create several objects per session, so I use "ApplicationContext" injected into my application and create beans manually.
I hope the once day the real support for "session" type will be added.
Hi,
I'm happily using session scoped beans in Vaadin.
All I've done is added spring's RequestContextListener to web.xml, defined the bean to be injected with the scope of session in my spring beans file, and marked it as autowired in the code.
Example :
web.xml:
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
application-context.xml:
<bean scope="session" class="org.bushe.swing.event.ThreadSafeEventService"/>
WindowWithEventService.java:
@Configurable(preConstruction = true, dependencyCheck = true)
protected class WindowWithEventService extends Window {
@Autowired(required = true)
protected transient EventService eventService;
}
So far, it's worked like a dream.
Cheers,
Charles
Charles Anthony: Hi,
I'm happily using session scoped beans in Vaadin.
All I've done is added spring's RequestContextListener to web.xml, defined the bean to be injected with the scope of session in my spring beans file, and marked it as autowired in the code.
Example :
web.xml: <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener> application-context.xml: <bean scope="session" class="org.bushe.swing.event.ThreadSafeEventService"/> WindowWithEventService.java: @Configurable(preConstruction = true, dependencyCheck = true) protected class WindowWithEventService extends Window { @Autowired(required = true) protected transient EventService eventService; }
Hi Charles,
Thank you for example. I believe, you also have org.springframework.web.context.ContextLoaderListener in your web.xml to create Spring application context on Web application startup. I am not familiar with RequestContextListener, but from Javadocs I got that this class exposes the request attributes (e.g. HttpServletRequest and HttpSession objects) to application via thread local variable so that they are available within the lifespan of request. I have not found any direct relation between that class and support of "session"-scoped beans. One need something that will create WebApplicationContext instance and I know only one class capable to do this: org.springframework.web.servlet.DispatcherServlet. So:
- If you use DispatcherServlet in your web.xml and forward the requests to Vaadin servlet, then everything is clear. But you don't need ContextLoaderListener then.
- If you don't use it and dispatch all requests to Vaadin -- there is some magic behind. I wonder, who creates the Web Context then?
Hi Dmitry,
Dmitry Katsubo:
I believe, you also have org.springframework.web.context.ContextLoaderListener in your web.xml to create Spring application context on Web application startup.
Yes, this is true.
If you use DispatcherServlet in your web.xml and forward the requests to Vaadin servlet, then everything is clear.
We don't.
If you don't use it and dispatch all requests to Vaadin -- there is some magic behind. I wonder, who creates the Web Context then?
I'm pretty sure it's the RequestContextListener but I could be wrong. [1]
Honestly, in my simple world (!), I just
a) added the ContextLoaderListener & RequestContextLoaderListener to web.xml
b) configured the ContextLoaderListener with the spring XML files
c) added the autowire stuff to my code
And away I went.
I am using loadtime weaving, if that's relevant. Not sure it is, though... Maybe I should knock together a simple project.
Cheers,
Charles.
[1] Some Time Later
I can confirm that it is the RequestContextListener that's sprinkling some magic pixie dust over the setup. If I comment it out of my web.xml, I get the following exception - which is clearly where I found out that I had to add the RequestContextListener!
java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:123)
org.springframework.web.context.request.SessionScope.get(SessionScope.java:90)
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:325)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:844)
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:786)
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703)
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478)
org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:283)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:374)
org.springframework.beans.factory.wiring.BeanConfigurerSupport.configureBean(BeanConfigurerSupport.java:140)
org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect.configureBean(AnnotationBeanConfigurerAspect.aj:59)
org.springframework.beans.factory.aspectj.AbstractDependencyInjectionAspect.ajc$before$org_springframework
Just to (hopefully) clarify a little bit...
The ContextLoaderListener is a servlet context listener that associates a Spring application context with your servlet context and makes it accessible to other Spring classes. Typically this is defined via an applicationContext.xml file that sits in WEB-INF.
The RequestContextListener is a servlet filter that, at the start of each request, stuffs a reference to the request object etc. in a private ThreadLocal variable so that other Spring classes that want to answer the question "what is the current HTTP request associated with this thread?" can get the answer to that question by invoking the appropriate static method.
The DispatcherServlet is a regular Java servlet that Spring provides. Each such servlet has its own Spring application context - distinct from, though a "child" of, the one mentioned above associated with the ContextLoaderListener. If your servlet is named foobar then the default XML file name is foobar-servlet.xml.
The autowiring of your Vaadin application using the AutowiringApplicationServlet can be done at either level, i.e., using the ContextLoaderListener context or using the DispatcherServlet context. Examples of both are given in previous posts to this thread (here and here, respectively).
Regarding session scope, this is supported by Spring and works just fine, and does not have any direct interaction with whether you are using Vaadin or not. Of course, Vaadin applications are also "session scoped", so there is a natural usage correspondence.
In my own experience, I have not used session scoped Spring beans much. Instead, I usually end up having almost all beans be stateless singletons, such as DAO's and service beans.
Thanks for providing that clarity, Archie :)
For what it's worth I, too, have only found a limited use for session beans - in fact, just the one so far : an event bus for all views/presenters involved with a Vaadin Application. Note, not an web-application-wide event bus.
As far as I can see, everything else Spring configured is going to be a singleton.
Cheers,
Charles
Archie Cobbs: The autowiring of your Vaadin application using the AutowiringApplicationServlet can be done at either level, i.e., using the ContextLoaderListener context or using the DispatcherServlet context. Examples of both are given in previous posts to this thread (here and here, respectively).
Thanks for the samples, by the way.
The only thing I thought could be better about them is if they contained a very simple example of how you could wire Spring beans into more than just the Vaadin application. For example: how you would approach wiring Spring managed services into a Vaadin custom component.
Hello!
Thanks for this clean example! I'm new to Vaadin and I'm going to integrate it into my web applications I'm developing for my company.
I'm already using Spring, but there's a thing I don't understand of your example (demo2.zip).
The question is: is it necessary to use AutowireCapableBeanFactory?
If Spring is correctly configured in applicationContext.xml, when you get the WebApplicationContext with WebApplicationContextUtils.getRequiredWebApplicationContext you should be able to extract the MyApplication bean directly from it, no? Provided all injection via annotation and so on was correctly activated in the applicationContext itself.
Thanks in advance for any hint.
Cheers,
Fabio
Tom Bruggeman:
Archie Cobbs: The autowiring of your Vaadin application using the AutowiringApplicationServlet can be done at either level, i.e., using the ContextLoaderListener context or using the DispatcherServlet context. Examples of both are given in previous posts to this thread (here and here, respectively).
Thanks for the samples, by the way.
The only thing I thought could be better about them is if they contained a very simple example of how you could wire Spring beans into more than just the Vaadin application. For example: how you would approach wiring Spring managed services into a Vaadin custom component.
For what I know, since you get the Application object created and injected by Spring itself, you get all other dependent object from there.
I mean: you define a custom component, marked for injection (via annotation) or declared in applicationContext and injected into the main Application bean.
Then, you can get that instance directly from the main Application code, isn't it? And all Spring facilities should work as expected, for example the @Transactional annotation.
Fabio Da Soghe:
The question is: is it necessary to use AutowireCapableBeanFactory?If Spring is correctly configured in applicationContext.xml, when you get the WebApplicationContext with WebApplicationContextUtils.getRequiredWebApplicationContext you should be able to extract the MyApplication bean directly from it, no? Provided all injection via annotation and so on was correctly activated in the applicationContext itself.
I don't doubt that there may be a simpler way to do this.
Here is my (limited) understanding: The problem is that Vaadin requires you to extend Vaadin's ApplicationServlet, which knows nothing of Spring. Every time ApplicationServlet needs a new Application instance, it invokes ApplicationServlet.getNewApplication(). This happens many times during the course of your web server's life. This is the point at which we create Application instances, not when the application context is created. So what we have to do is create the Application instance using Spring at that time. That's what the current code does.
Now it may be possible to define your bean as a scope="prototype" (or scope="session" more correctly) bean in the application context and have the BeanFactory get the bean by name instead of creating it explicitly. Then all the wiring would be done normally and implicitly. But you would also have to explicitly declare your Application bean in the application context. I guess it's 6 one/half-dozen the other.
Archie Cobbs: Here is my (limited) understanding: The problem is that Vaadin requires you to extend Vaadin's ApplicationServlet, which knows nothing of Spring. Every time ApplicationServlet needs a new Application instance, it invokes ApplicationServlet.getNewApplication(). This happens many times during the course of your web server's life. This is the point at which we create Application instances, not when the application context is created. So what we have to do is create the Application instance using Spring at that time. That's what the current code does.
Now it's all clear, thank you :-)
But my question remains: why do you use AutowireCapableBeanFactory? Couldn't you use directly WebApplicationContext, calling getBean() on it?
Now it may be possible to define your bean as a scope="prototype" (or scope="session" more correctly) bean in the application context and have the BeanFactory get the bean by name instead of creating it explicitly. Then all the wiring would be done normally and implicitly. But you would also have to explicitly declare your Application bean in the application context. I guess it's 6 one/half-dozen the other.
Ok, maybe I'm getting to the point. I thought you can activate (as you did) Spring's AOP-based configuration and then declare which beans are managed by Spring with annotations. So, besides putting @Autowired onto MyApplication's fields, declaring the whole class as a Spring's bean (with @Component, for example).
Anyway, the only reason you used AutowireCapableBeanFactory is to construct and correctly inject the MyApplication object, without the need to declare it in the applicationContext.xml?
Fabio Da Soghe: Anyway, the only reason you used AutowireCapableBeanFactory is to construct and correctly inject the MyApplication object, without the need to declare it in the applicationContext.xml?
Correct. This is the first approach. In retrosepct, the second approach probably makes more sense and is more "Spring-like", i.e., less of a hack. At the time I was just trying to make the dumb thing work :-)
Archie Cobbs: Correct. This is the first approach. In retrosepct, the second approach probably makes more sense and is more "Spring-like", i.e., less of a hack. At the time I was just trying to make the dumb thing work :-)
I see. Thank you. Please don't misunderstand me: your example was illuminating, I was getting lost into all the documentations, javadocs and so on so you saved my weekend ;-)
I would expect that your Autowire servlet will be integrated directly into Vaadin distribution, in the main package or in an integration package, ready to use.
Cheers and thank you again!
Fabio
Archie Cobbs: This is the cleanest and simplest way to do it I've found... are there even better/cleaner ways out there? Thanks.
Here's my take on Vaadin Spring integration http://psponcoding.blogspot.com/2011/03/vaadin-spring-integration.html. Depending on who you ask, but it might be a bit cleaner approach. The cleanest way would probably require some modifications to the core Vaadin implementation as suggested in the article.
I'm noticing that all approaches here are calling directly (one way or another) the Spring applicationContext for getting their beans through explicit invocation of the injection process.
Could it be possible to have Spring create every Vaadin component? So the DI would be done by Spring itself, without helper classes.
The only one I see necessary is the first Application creation (because of the lack of component creation listener). For this there's need of the AutowiringApplicationServlet.
But from there on, couldn't Spring be enough? If the main application object has all its dependencies injected by Spring itself and the main bean is Spring manager, what is missing?
Fabio Da Soghe: Could it be possible to have Spring create every Vaadin component? So the DI would be done by Spring itself, without helper classes.
The only one I see necessary is the first Application creation (because of the lack of component creation listener). For this there's need of the AutowiringApplicationServlet.
But from there on, couldn't Spring be enough? If the main application object has all its dependencies injected by Spring itself and the main bean is Spring manager, what is missing?
Sure, that should work. E.g., you could have something like:
public class MyApp extends Application {
@Autowired
private Panel panel1;
....
where the Panel comes from the application context.
Fabio Da Soghe: Could it be possible to have Spring create every Vaadin component? So the DI would be done by Spring itself, without helper classes.
What you need to achieve this is load-time weaving: a way to inject dependencies into non-Spring managed beans.
Archie Cobbs:
Fabio Da Soghe:
The question is: is it necessary to use AutowireCapableBeanFactory?If Spring is correctly configured in applicationContext.xml, when you get the WebApplicationContext with WebApplicationContextUtils.getRequiredWebApplicationContext you should be able to extract the MyApplication bean directly from it, no? Provided all injection via annotation and so on was correctly activated in the applicationContext itself.
I don't doubt that there may be a simpler way to do this.
...
Now it may be possible to define your bean as a scope="prototype" (or scope="session" more correctly) bean in the application context and have the BeanFactory get the bean by name instead of creating it explicitly. Then all the wiring would be done normally and implicitly. But you would also have to explicitly declare your Application bean in the application context. I guess it's 6 one/half-dozen the other.
This got me wondering and indeed there is a simpler way to do it as described above. With this scheme, no AutowireCapableBeanFactory is necessary (just WebApplicationContext) and your Application bean is declared explicitly inside the Spring application context (with scope="session" of course).
See attached ZIP file.
Archie Cobbs: This got me wondering and indeed there is a simpler way to do it as described above. With this scheme, no AutowireCapableBeanFactory is necessary (just WebApplicationContext) and your Application bean is declared explicitly inside the Spring application context (with scope="session" of course).
See attached ZIP file.
Doh! You were faster then me :-)
I've just built a skeleton application exactly as your last example.
This way Spring and Vaadin integrates very smoothly!
Again, thank you for your support.
Best regards,
Fabio
Hi,
Thank you guys for resources provided here, and thanks for samples also.
In what situation I need load time weaving?
Let's say I have SomeScreen class extending VerticalLayout in my app.
I have defined my main Application class as session scoped bean as in provided examples, but I create instance of SomeScreen with constructor during application lifecycle (not as spring bean).
I want use my repository bean from root app context as property inside SomeScreen
I tried following without load time weaving it doesn't work. I receive NullPointerException for repository.
@Configurable(preConstruction = true,dependencyCheck=true)
public class SomeScreen extends VerticalLayout {
@Autowired(required = true)
private SomeRepository repository;
root-context with :
<context:annotation-config />
<context:spring-configured />
<context:component-scan />
<bean id="someRepository" class="example.WSSomeRepository"></bean>
<bean scope="session" class="MyVaadinApplication"/>
How can I achieve this without load time weaving? Or is it possible?
If not, do I need to define SomeScreen as another session scoped bean
Matúš Ferko: In what situation I need load time weaving?
In my experience with Spring I've never had occasion to use load time weaving, and moreover I'm not sure that I completely understand when or why it's needed (that's a statement about my own ignorance, not the usefulness of load-time weaving).
In any case, you should be able to figure out why your example doesn't work by continuously morphing it into my example (demo3.zip) until it starts working.
Problem I encounter is that I can't inject spring beans in any object except main application class.
I guess I need to define every object (mainly layouts) as spring bean?
@configurable in such classes doesn't work :(, but I see it works in SpringApplication sample app in vaadin incubator repository.
I forgot to put aspectj compile time weaver plugin into pom, my fault.
Archie,
The servlet does not compile for me :
return this.getWebApplicationContext().getBean(applicationClass);
getBean expects a String not a class. Not sure what was intended there ..
Jorg