Hi Folks.
I integrated Vaadin Spring and it works pretty well.
I use Spring managed UIs and Views. For my lagacy code I wrote the following class:
package com.myapp.app_base.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringBeans implements ApplicationContextAware
{
/**
* The applicationContext
*/
private static ApplicationContext applicationContext;
/**
* Searches for the bean with the passed name.
*
* @param name
* - The name to search for in the application context.
*
* @return An instance of the bean.
*/
public static Object getBean( String name )
{
return applicationContext.getBean( name );
}
/**
* Searches for the bean with the passed class.
*
* @param clazz
* - The class search for in the application context.
*
* @return An instance of the bean.
*/
public static <T> T getBean( Class<T> clazz )
{
return applicationContext.getBean( clazz );
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
SpringBeans.applicationContext = applicationContext;
}
}
With this class I’m able to access Spring managed beans in my lagacy code. This works fine within the current UI and it’s subcomponents.
Now I start a Job via
[code]
scheduledTaskRegistrar.getScheduler().schedule(task.getRunnable(), new Trigger(){
@Override
public Date nextExecutionTime(TriggerContext triggerContext)
{
if(triggerContext.lastCompletionTime() == null)
{
return new Date();
}
return null;
}
})
[/code]Where scheduledTaskRegistrar is an instance of org.springframework.scheduling.config.ScheduledTaskRegistrar
This snippet triggers a one time job in a new Thread. If I try to run this I get the following exception:
16:06:03,705 ERROR TaskUtils$LoggingErrorHandler :95 - Unexpected error occurred in scheduled task.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'appointmentBC': Scope 'vaadin-ui' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No VaadinSession bound to current thread
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:354)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:219)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:332)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1057)
at com.myapp.app_base.util.SpringBeans.getBean(SpringBeans.java:39)
at com.myapp.util.AppointmentGenerator.createICSAppointments(AppointmentGenerator.java:806)
at com.myapp.app_base.jobs.AppointmentGeneratorJob.generateAppointmentsInternal(AppointmentGeneratorJob.java:64)
at com.myapp.app_base.jobs.AppointmentGeneratorJob.generateAppointments(AppointmentGeneratorJob.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: No VaadinSession bound to current thread
at com.vaadin.spring.internal.UIScopeImpl$VaadinSessionBeanStoreRetrievalStrategy.getVaadinSession(UIScopeImpl.java:128)
at com.vaadin.spring.internal.UIScopeImpl$VaadinSessionBeanStoreRetrievalStrategy.getUIStore(UIScopeImpl.java:139)
at com.vaadin.spring.internal.UIScopeImpl$VaadinSessionBeanStoreRetrievalStrategy.getBeanStore(UIScopeImpl.java:168)
at com.vaadin.spring.internal.UIScopeImpl.getBeanStore(UIScopeImpl.java:105)
at com.vaadin.spring.internal.UIScopeImpl.get(UIScopeImpl.java:81)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:339)
... 22 more
This is why the new Thread does not have any reference to the current UI and current vaadin session which are needed in UIScopeImpl to retrieve the proper instances from the spring application context.
I could pass a reference of UI.getCurrent() to the runnable and use UI.setCurrent(…) whichin it. Wouls you guys recommend this solution?
Question:
How do I solve this problem and whats the best practice for that?
If I want to change the UI there is UI.getCurrent().access…
Is there a solutution for my case?
Thank you very much.
Christoph