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.
Vaadin Spring + Multithreaded Environment
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
scheduledTaskRegistrar.getScheduler().schedule(task.getRunnable(), new Trigger(){
@Override
public Date nextExecutionTime(TriggerContext triggerContext)
{
if(triggerContext.lastCompletionTime() == null)
{
return new Date();
}
return null;
}
})
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
Hello Christoph,
Currently, there is no built in way of making the current UI and session available to another thread. Personally, I normally pass the UI instance to the thread and access it directly. Any updates to the UI would go through the UI.access(...) method. This method will also take care of populating the current session and UI, so the scopes should work as well.
-Petter-
Hi Petter.
Thanks for the reply. OK, I could pass around the reference to the current UI. But is it save to:
1) pass the reference to the runnable (you suggested this) AND
2) do the following in the runnable.run()
UI.setCurrent(theUIReference);
Doing this I would have two threads referencing the same UI via the CurrentInstance way.
And UIScopeImpl would work because UI.getCurrent() would not return null.
Thanks,
Christoph
I assume you mean the runnable that is passed to UI.access(). You don't need to call UI.setCurrent() inside that runnable, because Vaadin already does that for you.
-Petter-
Hi Peter.
No, I didn't mean the runnable for UI.access. I know that in that case vaadin does all the plumping for me.
I mean to write an own runnable, put that to the taskscheduler which starts that runnable in a seperated thread using Spring. There is no Vaadin. But when try to use @Autowired in that runnable which references an UIScope'd Bean the UIScopeImpl will complain that there is no current UI. And thats my Question:
Is it save to do UI.setCurrent(theUIReference); in that own runnable?
Thanks a lot for your time.
Christoph
The UIScopeImpl is locking the session before accessing it, so IMO it should be safe to call UI.setCurrent(theUIReference) inside that runnable.
Hi Petter.
This awnsers my question. Thank you very much for your time :)
Cheers,
Christoph