Home > JavaEE > Chicken and egg problem with Spring and 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:




  

  
  
...

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.

email
Send to Kindle
Categories: JavaEE Tags: ,
  1. May 5th, 2010 at 16:45 | #1

    I am surprised that a framework focused on UI produces buttons as span elements… http://demo.vaadin.com/sampler#ButtonPush

  2. May 5th, 2010 at 18:31 | #2

    He he, depends on the theme you choose. Nothing prevents you from using a theme that produces native UI components. The rendering is not as sexy though…

  3. June 4th, 2010 at 14:52 | #3

    Nice to see someone working so closely with Vaadin and Spring. I’m just getting started with Vaadin and so far I’m very pleased and enthused. Building a little recipe book app with Vaadin and db4o, let’s see how it all goes. Nice post!

  1. No trackbacks yet.