Spring integration helper class

You need to upgrade to Spring 3.0.x.

That method is documented
here
.

HI,
firstly I used simpler approach without MVC, but I need to change it now. Do you have some example with MVC + some controllers and jsp-s?

Veyr nice post! Thank you.

Is it possible to integrate this with Spring-security and allow to change locale from login.form (select combo and onchange reload) ? Similar way as LocaleChangeInterceptor - eg. add parameter ?lang=en_US for example …

I won’t be able to do it. Using custom filter I am able to change vaadin locale and spring security messages, but spring:message in login.jsp still in browser locale :frowning:

Hi,

Im using Vaadin for just few days so I dont know much of the Vaadin internals, but Im wondering why not to do this like Wicket framework do ?

In Wicket:
1)Each component (including custom components) inherit from Component class.
2)Component class has default constructor which calls someting like getApplication().notifyComponentInstantiationListeners(this);
3)When you configure your application in Wicket (similar like you do this in Vaadin) you can register IComponentInstantiationListener which is notified about each wicket component creation
4)Wicket provides SpringComponentInjector which do the rest (auowire Component with spring beans)

This solution has many adventages:
1)simplicity, just one line in yout Application.init() method to configure
2)pure Java, no AspectJ, load time weaving etc required
3)all components are autowired - not only Application objects

Unfortuatly as far as I know Vaadin does not provide ComponentInstantiationListeners, so to let it work following changes should be done in Vaadin:
1)Add something similar to getApplication().notifyComponentInstantiationListeners(this); in AbstractComponentClass
2)Implement somehow (ThreadLocal?) getApplication() method
3)Write somethind similar to SpringComponentInjector

How about that ?

Regards Daniel

Here is an example of AddressBook example refactored to use Spring.
In this example all Vaadin components are created and injected by Spring without any instantiation listeners or helper classes, custom injectors etc.

Hope this helps

[added later]

Personally I don’t see any problems with using AspectJ but if you do, you can always use bean implementing ApplicationContextAware interface with static access to Spring context and get only one bean from there (MainWindow in this example)
12004.zip (13.4 KB)

OK, now I’ve done some more work on this Vaadin and Spring stuff. Here’s the latest result, which is finally getting close to the way I think it should work.

Up until now there still have been several problems with Vaadin+Spring relating to “scope mismatch”.

For example, if you have a Vaadin application object that registers as a listener on a persistent (non-Vaadin application) singleton, then that listener registration becomes a memory leak when the Vaadin application closes… not to mention the fact that your listener needs to find and synchronize on its associated Vaadin application instance before doing anything… but you can’t autowire in the associated Vaadin application instance because until now there’s no
scope=“vaadinApplication”
(using
scope=“session”
almost works… until you need your users to run more than one Application instance at a time).

Using Spring’s
@Configurable
annotation helps but has a similar problem if the bean being configured has a destroy method, because that method will never be called when the Vaadin application closes. Typically destroy methods are where you would unregister listeners so this is yet another opportunity for memory leaks.

So here is my attempt to address all these issues (these classes live in my
dellroad-stuff
project):



  • ContextApplication

    is a Vaadin application sub-class that provides some needed infrastructure, namely:
    [list]
  • Access to the currently running Vaadin application (via a private ThreadLocal)
  • A way to safely interact with a Vaadin application from a background thread (via the

    invoke(Runnable)

    method)
  • Support for Vaadin application close event notification

    [/list]


  • SpringContextApplication

    (sub-class of
    ContextApplication
    ) that creates a new Spring application context for each new Vaadin application instance. The parent context is the application context associated with the overall servlet context. This is analogous to what Spring’s
    DispatcherServlet
    does.
  • A new AOP aspect that works on
    @Configurable
    beans, allowing them to be autowired by the
    SpringContextApplication
    application context associated with the current Vaadin application instance (note:
    not
    the parent context).


  • ContextApplicationFactoryBean

    , a Spring factory bean that allows the
    SpringContextApplication
    Vaadin application to itself appear within (and be autowired by) its associated application context

  • VaadinApplicationScope
    , which adds a custom Spring scope so you declare beans with
    scope=“vaadinApplication”
    .

An example of this stuff is
on github here
. When you run the demo you’ll see three beans displaying their properties:


  • MyBean
    - a bean in the usual Spring web application context associated with the servlet context (does not change when the Vaadin application restarts)

  • MyApplicationBean
    - a bean in the per-Vaadin application context (you get a new one each time the Vaadin application restarts)

  • ConfigurableBean
    - a
    @Configurable
    bean created in
    MyApplicationBean
    with a
    new ConfigurableBean()
    statement and automagically autowired by the AOP aspect

I’m interested to hear of other people’s thoughts, especially regarding the AOP stuff and serialization issues, as I’m still learning about the subtleties.

-Archie

FYI, I’ve also created an
addon
for this.

-Archie

Hi, great work.

We’re currently stuck with IBM WAS 6.1 running on jdk 1.5, will your classes work/compile with 1.5?

br
Svante

Hey Archie,

Great to see this, I will enjoy checking out your addon.
I have often wondered creating an addon that caters for all the combined wisdom that has been
accumulated on getting spring and vaadin playing well together, so good job.

Hi Archie,

Great work. I look forward to using this add-on.

I have some questions regarding its use.

First, I would like to be able to use the @Service, @Component, @Repository, etc. annotations for spring beans instead of declaring them in the application context. Are there any limitations on being able to do that?

How about adding controllers using @Controller?

You also mention communicating with Vaadin on background threads. Can you provide a use case and code sample of what you mean by this? I am very intrigued and think I have use for it if it is what I think it is.

Any thoughts on integrating with Spring Security?

Thanks again for your work.

Regards,
Tom

I don’t know of any reason why it shouldn’t work. If you run the demo application, you will need to change the “1.6” to “1.5” in the

ant task.

Let me know if you run into any problems and what workarounds you found if so.

-Archie

That stuff should all work normally. Same thing for
@Controller
.

An example would be a timer running on the server, where when the timer expires you want to change the appearance of some widget.

Of course, the change would not be immediately visible unless you are also doing server push (e.g., using the
serverpush
add-on).

Should work the same.

-Archie

Reason I ask is that we get an exception when trying to reach our servlet:
Br /Svante


[Servlet Error]
-[admin]
: java.lang.UnsupportedClassVersionError: (org/dellroad/stuff/vaadin/SpringContextApplication) bad major version at offset=6
	at java.lang.ClassLoader.defineClassImpl(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:258)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:151)
	at com.ibm.ws.classloader.CompoundClassLoader._defineClass(CompoundClassLoader.java:562)
	at com.ibm.ws.classloader.CompoundClassLoader.findClass(CompoundClassLoader.java:514)
	at com.ibm.ws.classloader.CompoundClassLoader.loadClass(CompoundClassLoader.java:388)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:597)
	at java.lang.ClassLoader.defineClassImpl(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:258)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:151)
	at com.ibm.ws.classloader.CompoundClassLoader._defineClass(CompoundClassLoader.java:562)
	at com.ibm.ws.classloader.CompoundClassLoader.findClass(CompoundClassLoader.java:514)
	at com.ibm.ws.classloader.CompoundClassLoader.loadClass(CompoundClassLoader.java:388)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:597)
	at com.vaadin.terminal.gwt.server.ApplicationServlet.init(ApplicationServlet.java:68)
	at com.ibm.ws.webcontainer.servlet.ServletWrapper.init(ServletWrapper.java:227)
	at com.ibm.ws.wswebcontainer.servlet.ServletWrapper.init(ServletWrapper.java:340)
	at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:435)
	at com.ibm.ws.wswebcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:524)
	at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3548)
	at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:269)
	at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:818)
	at com.ibm.ws.wswebcontainer.WebContainer.handleRequest(WebContainer.java:1478)
	at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:125)
	at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:458)
	at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:387)
	at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:267)
	at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:214)
	at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.complete(NewConnectionInitialReadCallback.java:113)
	at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
	at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
	at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
	at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:136)
	at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:196)
	at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:751)
	at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:881)
	at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1497)

Hi Archie,

I’m trying to use your Spring add-on and I have a couple of questions.

First, I am using STS and creating a Spring Roo project. Then I layer on Vaadin. I am using Spring 3.0.6.

My project structure is:


src
   main
       java
           com
               ......
       resources
           META-INF
                 spring
                        applicationContext.xml

My applicationContext.xml is:



<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans 	xmlns="http://www.springframework.org/schema/beans" 
		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:tx="http://www.springframework.org/schema/tx" 
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
		xmlns:p="http://www.springframework.org/schema/p"
		xsi:schemaLocation="http://www.springframework.org/schema/aop 
							http://www.springframework.org/schema/aop/spring-aop-3.0.xsd         
							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/jee 
							http://www.springframework.org/schema/jee/spring-jee-3.0.xsd         
							http://www.springframework.org/schema/tx 
							http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

   <context:property-placeholder location="classpath*:META-INF/spring/*.properties"/>

    <context:spring-configured/>

    <context:component-scan base-package="com.presidio">
        <context:exclude-filter expression=".*_Roo_.*" type="regex"/>
        <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>
    
    <!-- Activate Spring annotation support -->
    <context:annotation-config/>
    
    <bean class="org.dellroad.stuff.vaadin.ContextApplicationFactoryBean" p:autowire="true"/>
    
    /* Vaadin application bean */
    <bean class="com.presidio.web.Presidio3Application"/>

</beans>

My web.xml is:


<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    
    <display-name>Presidio3</display-name>
    
    <description>Roo generated Presidio3 application</description>

    
    <!-- Vaadin production mode -->
    <context-param>
        <param-name>productionMode</param-name>
        <param-value>false</param-value>
    </context-param>
    
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:META-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>
    
    <servlet>
        <servlet-name>Presidio3 Vaadin Application Servlet</servlet-name>
        <servlet-class>com.vaadin.terminal.gwt.server.ApplicationServlet</servlet-class>
        <init-param>
            <param-name>application</param-name>
            <param-value>com.presidio.web.Presidio3Application</param-value>
        </init-param>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>Presidio3 Vaadin Application Servlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

I am getting an exception on startup:


2011-11-30 08:39:23,092 [Thread-13]
 ERROR org.springframework.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.dellroad.stuff.vaadin.ContextApplicationFactoryBean#0' defined in file 
[/Users/tgregory/springsource/vfabric-tc-server-developer-2.6.1.RELEASE/spring-insight-instance/wtpwebapps/Presidio3/WEB-INF/classes/META-INF/spring/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: no current application found
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1420)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:192)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:567)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
	at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:282)
	at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:204)
	at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
	at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4723)
	at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5226)
	at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5221)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
	at java.util.concurrent.FutureTask.run(FutureTask.java:138)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:680)
Caused by: java.lang.IllegalStateException: no current application found
	at org.dellroad.stuff.vaadin.ContextApplication.get(ContextApplication.java:260)
	at org.dellroad.stuff.vaadin.ContextApplicationFactoryBean.getContextApplication(ContextApplicationFactoryBean.java:78)
	at org.dellroad.stuff.vaadin.ContextApplicationFactoryBean.createInstance(ContextApplicationFactoryBean.java:52)
	at org.dellroad.stuff.vaadin.ContextApplicationFactoryBean.createInstance(ContextApplicationFactoryBean.java:27)
	at org.springframework.beans.factory.config.AbstractFactoryBean.afterPropertiesSet(AbstractFactoryBean.java:130)
	at org.dellroad.stuff.vaadin.ContextApplicationFactoryBean.afterPropertiesSet(ContextApplicationFactoryBean.java:59)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)
	... 20 more

I’ve reviewed your code in Github and I do have a question.

In your WEB-INF directory, you have two spring configuration XML files. However, in the web.xml, you don’t reference either one. How does spring get initialized without referencing them in your web.xml?

Does the delroad stuff need to be in a separate initialization file?

You help on this would be greatly appreciated.

Thanks,
Tom

Hello, I try to run the example and I got java.lang.ClassCastException exception as follows:


java.lang.ClassCastException: com.vaadin.terminal.gwt.server.ApplicationServlet
	at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1087)
	at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:824)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:135)
	at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:181)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:463)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:852)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:120)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
	at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:257)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
	at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1764)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:909)
	at java.lang.Thread.run(Thread.java:662)

The tomcat failed to start.
My application server is Tomcat 7.0.19 under Eclipse 3.6
Spring Framework 3.0.0 (also tried 3.1.0 & 2.5.6)
dellroad-stuff-vaadin 1.0.189

Did I do anything wrong?

Problem solved. If you use maven, please exclude the dependency of Servlet API!

Sorry for the slow response. For some reason I thought I was subscribed to this thread but actually was not…

The problem here is that you need to create a separate Spring application context for your application bean, and your ContextApplicationFactoryBean should live there.

To do this, create a file Presidio3Application.xml in your WEB-INF and put all per-Application beans, including ContextApplicationFactoryBean, in there. That context will have the normal servlet-wide Spring context as its parent. See

SpringContextApplication

for details.

Both files are given their default names.

For Spring,
classpath:WEB-INF/applicationContext.xml
is the default location that
ContextLoaderListener
looks for the servlet-wide context.

For SpringContextApplication,
classpath:WEB-INF/
ApplicationName
.xml
is the default location (in your case, it would be
classpath:WEB-INF/Presidio3Application.xml
).

Hello Archie,

I am confused with the @Vaadinconfigurable annotation. I have a bean with some autowired properties. Some of the them are defined in applicationContext.xml, the others are defined in MyApp.xml. It turns out both @Vaadinconfigurable & @Configurable will have same effect. For instance, I use Spring’s @Configurable for this bean, and those properties defined in MyApp.xml will still be autowired on this bean. What’s the difference between @Vaadinconfigurable and @Configurable?

Hi Archie,

thanks for your work!

Can you please provide more documentation how to use your addon especially the more advanced features? I was able to use the addon but I’m interested in the more sophisticated features like event listeners, background thread communication etc.

Unfortunately my Spring background is not strong enough ( especially the Spring Web MVC stuff ) to read the sourcecode and to understand all the features.

In the end I would like to be able to create an application where services, model and view are separated and the view only communicates with the services and the model firing events, the view should update by changing the model.

Do you think there is any chance you create such a step-by-step documentation?

Regards,
Christoph

Quick step by step documentation would be greatly appeciated! :lol: