2

I am using Vaadin Spring 1.0.0 and trying to figure out how could I inject beans that are available only within UI scope (when the user has the page opened) into classic spring @Component beans. Simple, let's have classes:

@Component
public class A {

    @Inject
    private IB b;
}

@UIScope
@SpringComponent
public class B implements IB {
}

And obviously during startup:

Caused by: java.lang.IllegalStateException: No VaadinSession bound to current thread

What is the normal way how to do it? I understand the whole concept, that beans are initialized on startup when UI scope is not available, but I use common libraries which are implemented in Spring with @Component and I want to implement some of the interfaces, but I can do it only in UI scope and not during startup.

Jason Marsh
  • 380
  • 4
  • 11
Mejmo
  • 2,363
  • 9
  • 35
  • 54
  • 1
    Class `A` needs to be UIScope as well. – Mark Rotteveel Oct 14 '15 at 10:39
  • In addition to @MarkRotteveel's comment, [the vaadin wiki](https://vaadin.com/wiki?p_p_id=36&p_p_lifecycle=0&p_p_state=normal&p_p_mode=view&_36_struts_action=%2Fwiki%2Fview&_36_pageResourcePrimKey=9364598&p_r_p_185834411_nodeName=vaadin.com+wiki&p_r_p_185834411_title=II+-+Injection+and+Scopes+with+Vaadin+Spring) also explains the reason: `...Anything injected with that annotation will get the same instance while within the same UI. Load a different UI and you'll get a different instance. If the session expires or the UI is closed, the instances will be cleaned up.` – Morfic Oct 14 '15 at 11:06
  • @MarkRotteveel Yeah, it is possible, but the `A` class is from common-lib and uses tens of other classes. It means that I have to add `@UIScope` to every dependent class in common lib. However this common-lib is also used in spring boot applications where there is no UI scope or Vaadin. – Mejmo Oct 14 '15 at 11:44
  • Ok, I assigned UIScope only for some classes that really needed it and it should work now. – Mejmo Oct 14 '15 at 11:53
  • @Mejmo Then you will probably need to subclass it so you can annotate it with ViewScope, or define a specific named bean with the annotation that you use instead of the discovered component. – Mark Rotteveel Oct 14 '15 at 11:54
  • Hey Mejmo, were you able to solve this? I can't inject UIScope annotated classes into RestControllers – Enoobong Jul 27 '19 at 14:23
  • Yes I solved it - removing any spring annotations for my UI classes. I just inject all needed components in my Main UI class and call it with `UI.getInstance().getSomeBean()`. Its hacky way, but next time I would not use spring/vaadin integration at all. – Mejmo Jul 27 '19 at 19:21

2 Answers2

1

Try injecting an aop scoped proxy instead.

For example:

@Scope(value="vaadin-ui", proxyMode=ScopedProxyMode.INTERFACES)
@SpringComponent
public class B implements IB {
}

I think that should work.

Jose Luis Martin
  • 10,459
  • 1
  • 37
  • 38
-1

You need to get it from ApplicationContext itself:

@Component
public class A {

      @Autowired
      private ApplicationContext context;

      public B getCurrentB(){
            return context.getBean(B.class);
      }
}

Note that it will throw exception if there is no UI bound to the current thread (normally). In other words, you MUST make sure this method only gets called during a UI request. Any kind of listener in Vaadin should be OK, as long as you're in the same thread with the request.

bekce
  • 3,782
  • 29
  • 30