Is CDI add-on maintained?

Hi,

There are around 30 tickets for CDI add-on v.1.0.2. However, at least for last 6 months I have not seen any activity. I am a little disappointed since this plug-in is the main connection hub for Vaadin and JEE world.
For example, PreDestroy method not invoked on UI object is an important one as otherwise we can not clean the resources before scope is destroyed. Another problem with Websocket usage with CDI add-on. With v.1.0.2 my deployement to GF with Push support started failing and I had to drop push support to continue.
Every software might have issues and prioritization of these issues might change. However, no actitvy >6 months does not look like normal for such an important add-on.

I’m not sure the push (WebSocket) issue can be solved easily. Try to use longpolling or streaming.

If you have a Pro account you can prioritise an issue BTW.

I am using vaadin-cdi
v1.0.3
in my application.
Only Vaadin version 7.5.x is compatible with WebSocket support in Glassfish, WildFly, WebLogic.

[url=https://vaadin.com/download/release/7.5/7.5.5/release-notes.html#enhancements]
Enhancements in Vaadin 7.5

  • JSR 356 WebSocket support has been refactored to improve compatibility with Wildfly and WebLogic
    [/url]

For resources cleaning I am using
detach()
method of UI.

As noted by Dmitry, 1.0.3 is the latest version, but has very small changes compared to 1.0.2. Vaadin Ltd is very committed to developing Vaadin CDI, but we have bit limited resources. The same team that built Vaadin CDI has been concentrating on Vaadin Spring lately, so that is why it might look the development has stalled.

BTW. All community contributions are welcome. If some certain issues are important for you, creating tickets or even just cc:n yourself into the trac ticket gives us valuable feedback where to concentrate next. Even better if you have provide some patches.

BTW2. With the Vaadin Spring project we have learned noticed the same thing as with Vaadin CDI: websocket with certain other web technologies are still rather problematic. Today the fact is taht you’ll just sometimes have to make tradeoffs between websocket communication and e.g. some security technologies (that typically work with servlet filters and http headers). We are trying hard to find good workarounds, but please do present all good ideas.

@Matti Thank you for the clear explanation. It is good to know development has not stalled. I appreciate the diffuculties with the development of websocket based technologies as it changes well grounded HTTP request/response lifecycle.

Could you add a line to
https://vaadin.com/wiki/-/wiki/Main/Working+around+push+issues
about CDI+Websocket problem?

I assume we can use CDI+Streaming (i.e. @Push(transport = Transport.STREAMING)) combination as a workaround?

@Dmitry, thank you for the detach() suggestion. In this case I assume we need to call Predestroy methods of the injected beens ourselves. However, it might get tedious as every injected bean might have some other injected beans.Hence we need to iterate the whole bean tree. Another problem how do we know that we should call the predestroy method? For example bean might be session scope but detach method is called when a component is removed from a layout. Then we should not call predestroy.

In addition to that Henri commented the below description in
https://vaadin.com/forum/#!/thread/1409950


"Also note that the method is not called when the component is removed indirectly or e.g. the session expires, so you should not rely on it for clean-up of background threads or connections to external systems and similar tasks
."

@Matti & Dmitry :even though predestroy method is not called, I assume any reference to bean is released so that it can be garbage collected?

Thanks again guys!

I think yes, the fact that predestroy method is not called does not affect the garbage collecting.
About the method [b]
detach
/b i trust the JavaDoc. :slight_smile: You can override this method or add DetachListener.

And, IMHO, i found the cause of failure.
There are errors in
AbstractVaadinContext
and
ViewScopedContext
classes.

AbstractVaadinContext.java:

    void dropSessionData(VaadinSessionDestroyEvent event) {
        long sessionId = event.getSessionId();
        getLogger().fine("Dropping session data for session: " + sessionId);

!!!>    SessionData sessionData = storageMap.remove(sessionId);
        if (sessionData != null) {
            synchronized (sessionData) {
                Map<Integer, UIData> map = sessionData.getUiDataMap();
                for (UIData uiData : new ArrayList<UIData>(map.values())) {

!!!>                // This method tries to get sessionData that already removed from storageMap
!!!>                dropUIData(sessionData, uiData);

                }
            }
        }
    }

Call stack:

com.vaadin.cdi.internal.AbstractVaadinContext.getSessionData(AbstractVaadinContext.java:178)
com.vaadin.cdi.internal.ViewScopedContext.getContextualStorage(ViewScopedContext.java:69)
org.apache.deltaspike.core.util.context.AbstractContext.destroy(AbstractContext.java:139)
com.vaadin.cdi.internal.AbstractVaadinContext.dropUIData(AbstractVaadinContext.java:214)
com.vaadin.cdi.internal.AbstractVaadinContext.dropSessionData(AbstractVaadinContext.java:200)
com.vaadin.cdi.internal.VaadinExtension.sessionClose(VaadinExtension.java:122)
...

ViewScopedContext.java:

   synchronized void viewChangeCleanup(long sessionId, int uiId) {
        getLogger().fine("ViewChangeCleanup for " + sessionId + " " + uiId);
        SessionData sessionData = getSessionData(sessionId, true);
        UIData uiData = sessionData.getUIData(uiId, true);
        if (uiData == null) {
            return;
        }

        uiData.validateTransition();
        String activeViewName = uiData.getActiveView();

!!!>    Map<Contextual<?>, ContextualStorage> map = sessionData.getStorageMap();
        for (Entry<Contextual<?>, ContextualStorage> entry : new ArrayList<Entry<Contextual<?>, ContextualStorage>>(
                map.entrySet())) {
            ViewContextual contextual = (ViewContextual) entry.getKey();
            if (contextual.uiId == uiId
                    && !contextual.viewIdentifier.equals(activeViewName)) {
                getLogger().fine(
                        "dropping " + contextual + " : " + entry.getValue());

!!!>            map.remove(contextual);
!!!>            // this method tries to get contextual storage that already removed
!!!>            destroy(contextual);

            }
        }
    }

Call stack:

com.vaadin.cdi.internal.AbstractVaadinContext$SessionData.getStorageMap(AbstractVaadinContext.java:134)
com.vaadin.cdi.internal.ViewScopedContext.getContextualStorage(ViewScopedContext.java:108)
org.apache.deltaspike.core.util.context.AbstractContext.destroy(AbstractContext.java:139)
com.vaadin.cdi.internal.ViewScopedContext.viewChangeCleanup(ViewScopedContext.java:155)
com.vaadin.cdi.internal.VaadinExtension.navigationChanged(VaadinExtension.java:150
...