getUI null after attachEvent fired

In my application I use a Guava EventBus to propagate messages. Within my view, I only subscribe in an AttachListener, with the expectation that my view and components are connected, and I can safely call getUI().access() to make changes on events.

However, in some cases, I get a NullPointerException from the fact the UI is not attached, even though the method can only be called after I get the AttachEvent. Looking at the Vaadin 7.4.5 code which fires the AttachEvent (com.vaadin.server.AbstractClientConnector, line 581-592), I see this:

[size=2]
[font=courier new]
@Override
public void attach() {
markAsDirty();

    getUI().getConnectorTracker().registerConnector(this);

    fireEvent(new AttachEvent(this));

    for (ClientConnector connector : getAllChildrenIterable(this)) {
        connector.attach();
    }
}

[/font]
[/size]

The event is fired before the connector is attached. IMO the event should only be fired
after
it is attached, as with this construct, I have to wrap all my getUI().access() methods in a if (isAttached()) clause, which seems superfluous as they will only be called after the AttachEvent.

Or is there a different safe way to get a callback whenever the component is completely attached?

addAttachListener

As stated, I use an attachlistener. Some ripped apart code:

import javax.validation.constraints.*;

import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.Component;
import org.vaadin.spring.events.*;
import org.vaadin.spring.events.EventBus.*;
import org.vaadin.spring.events.annotation.*;

import com.vaadin.data.util.*;
import com.vaadin.event.*;
import com.vaadin.spring.annotation.*;
import com.vaadin.ui.*;

@Component
@UIScope
public class MyCustomComponent extends CustomComponent
{
    @NotNull private final UIEventBus theUIEventBus;

    @Autowired
    public MyCustomComponent(@NotNull EventBus.UIEventBus aUIEventBus)
    {
        theUIEventBus = aUIEventBus;

        // Create something as CompositionRoot

        setCompositionRoot(myContent);

        addAttachListener((AttachEvent aEvent) ->
        {
            theUIEventBus.subscribe(this);
        });
    }

    @EventBusListenerMethod
    public void onEvent(@NotNull MyEvent aEvent)
    {
        if (isAttached())
        {
            // NPE is thrown here
            getUI().access(() -> update(aEvent));
        }
    }

    private void update(@NotNull MyEvent aEvent)
    {
        ...
    }
}

I wonder why the if(isAttached()) is neccesary, as I would expect getUI() to always be available using this construct. I do have several nested customcomponents, so the UI might be further up the chain. I’m not sure how that administration is handled.

Hi Claudio,

Yes, getUI() should always be non-null in an attach listener. Indeed, in the AbstractClientConnector code you refer to, there’s an apparently successful getUI call just before the listeners are invoked. So unless another attach listener actually detaches the component I can’t see how the UI could be null inside one.

Apologies if it’s just a typo in the example code, but the following seems suspect:

        addAttachListener((AttachEvent aEvent) ->
        {
            theUIEventBus.subscribe(this);
        });

I don’t know much about Spring, but subscribing in an event handler feels wrong. It seems to me you should subscribe in the constructor and then call EventBus.publish() in the attach listener.

Is the event bus asynchronous? Could it be that somehow the component is already detached by the time onEvent is invoked? Vaadin only guarantees that getUI is non-null when inside the actual attach listener and any synchronous method calls there.

If I subscribe in the constructor, I get events before the UI is attached, which is exactly what I was trying to avoid.

What I am trying to achieve is a subscribe-select on the backend repository, e.g. loading the current content from the repository and get all future updates through the event mechanism, without any possible gap in the middle due to missed events. I was using the AttachListener, so any event coming in can modify the stored data in the component in a thread-safe way. If the subscription is earlier, I cannot process the events because I can’t access the UI in a thread-safe fashion, leaving a gap between the select and subscribe.

As for the subscription itself, they are two different event mechanisms, Vaadin itself does not use this eventbus, it is only for my own communication inside my application (e.g. communication from the backend repository to the UI and within the same UI).

There is nothing that adds a different attachListener to this component, all my custom components are self-subscribing in this fashion. It only happened once, but it happened for all events for that session rendering the complete session broken. Maybe the UI was not constructed properly due to some internal race condition, similar to
https://dev.vaadin.com/ticket/16929
, which I see quite often as well.

Ah, now I understand. It still seems to me the most likely alternative that for some reason you got an event after the component was detached, not before it was attached.