/ SPRING, VAADIN

Chicken and egg problem with Spring and Vaadin

The more I dive into Vaadin, the more I love it: isolation from dirty plumbing, rich components, integration with portlets, Vaadin has it all.

Anyway, the more you explore a technology, the bigger the chances you fall down the proverbial rabbit hole. I found one just yesterday and came up with a solution. The problem is the following: in Vaadin, application objects are tied to the session. Since I’m a Spring fanboy, it does make sense to use Spring to wire all my dependencies. As such, I scoped all application-related beans (application, windows, buttons, resources, …​) with session like so:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:aop="http://www.springframework.org/schema/aop"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">
  <context:annotation-config />
  <bean id="application" scope="session">
  <aop:scoped-proxy />
...
</beans>

This works nicely, until you happen to use DI to wire further. By wire further, I mean wiring windows into application, button into windows and then resources (icons) into buttons. It is the last  step that cause a circular dependency. Icon resources are implemented in Vaadin by com.vaadin.terminal.ClassResource. This class has two constructors that both needs an application instance.

The dependency cycle is thus: application → window → button → resource → application. Spring don’t like it and protests energically to it by throwing an exception which is labeled like so Requested bean is currently in creation: Is there an unresolvable circular reference?

I think, in this case, that the design of the ClassResource is not adapted. That’s whyI designed a class aligned with Spring deferred instantiation: since the application is session-scoped, Spring uses a proxy that defers instantation from application start (Spring normal behaviour) to session use. The point is to implement the ApplicationResource interface, which needs an interface, but to set application only when needed:

public class DeferredClassResource implements ApplicationResource {

  private static final long serialVersionUID = 1L;

  private int bufferSize = 0;
  private long cacheTime = DEFAULT_CACHETIME;
  private Class<?> associatedClass;
  private final String resourceName;
  private Application application;

  public DeferredClassResource(String resourceName) {
    if (resourceName == null) {
      throw new IllegalArgumentException("Resource name cannot be null");
    }
    this.resourceName = resourceName;
  }

  public DeferredClassResource(Class<?> associatedClass, String resourceName) {
    this(resourceName);
    if (associatedClass == null) {
      throw new IllegalArgumentException("Associated class cannot be null");
    }
    this.associatedClass = associatedClass;
  }

... // standard getters

  @Override
  public String getFilename() {
    int index = 0;
    int next = 0;
    while ((next = resourceName.indexOf('/', index)) > 0
      && next + 1 < resourceName.length()) {
      index = next + 1;
    }
    return resourceName.substring(index);
  }

  @Override
  public DownloadStream getStream() {
    final DownloadStream ds = new DownloadStream(associatedClass
      .getResourceAsStream(resourceName), getMIMEType(),
      getFilename());
    ds.setBufferSize(getBufferSize());
    ds.setCacheTime(cacheTime);
    return ds;
  }

  @Override
  public String getMIMEType() {
    return FileTypeResolver.getMIMEType(resourceName);
  }

  public void setApplication(Application application) {
    if (this.application == application) {
      return;
    }
    if (this.application != null) {
      throw new IllegalStateException("Application is already set for this resource");
    }
    this.application = application;
    associatedClass = application.getClass();
    application.addResource(this);
  }
}

DeferredClassResource is just a copy of ClassResource, but with adaptations that let the application be set later, not only in constructors. My problem is solved, I just need to let application know my resources so it can call setApplication(this) in a @PostConstruct annotated method.

Nicolas Fränkel

Nicolas Fränkel

Developer Advocate with 15+ years experience consulting for many different customers, in a wide range of contexts (such as telecoms, banking, insurances, large retail and public sector). Usually working on Java/Java EE and Spring technologies, but with focused interests like Rich Internet Applications, Testing, CI/CD and DevOps. Also double as a trainer and triples as a book author.

Read More
Chicken and egg problem with Spring and Vaadin
Share this