CDI Utils add-on

Hi, so when you close a browser window/tab it doesn’t automatically close your application. You can open your active Vaadin app by just re-entering the application url to the browser.
Apparently the first entry of this forum thread still contains some outdated information: The AbstractCdiApplication is no longer a @SessionScoped, but a @VaadinScoped bean.

Tomi

The problem with @Asynchronous methods is that they run in a separate thread from the one that’s processing the original httprequest. And as VaadinContext relays on data wrapped in a @RequestScoped bean which in turn relays on ThreadLocal variables, @VaadinScoped beans can’t be referenced from asynchronous methods.

dereferenceBeanInstance automatically handles the presenter bean as well when you’re dereferencing a view but this is simply for convenience. Manually dereferencing both the view and the presenter ends up in the same exact result.

Can VaadinContext not use @SessionScoped to relay the information ? The session is consistent over @Asynchronous methods…

I’ll play a bit with cdi-util source code to see if I can make it work. (though I would prefer to use an unmodified version of your library…)

The problem with using a SessionScoped bean for this purpose is that all the Vaadin applications in one http session would then share the same instance. Though in most cases this would work just fine, problems might occur when running multiple parallel Vaadin applications in a single session. However, this being such a rare case I may need to consider dropping the support for it altogether to allow (most likely more needed functionality for) accessing VaadinScoped beans in separate threads.

Perhaps you can support both… This would give the end user the choice if they want to build multiple applications per session or one application ( that supports accessing the beans from separate threads ) per session ?

I don’t think it will be possible to support @RequestScoped beans from @Asynchronous methods , by definition the Request is no longer in scope … But for applications where separate threads is not an issue @RequestScoped beans would also be nice , I think this is addressed a bit differently in Vaadin 7. But I have only skimmed over Vaadin 7 implications so far.

Hello there,

I’m using the CDI Utils addons since 1 week and i wanted to use the animator addons (in vaadin addon repo).
But i cant make it work … It says that :

Do i have to configure something to make the addons work with CDI utils addon ?

Thx in advance for your answers.

Hi Tomi,

for a prototype application I started building a basic framework which also works with CDI. The purpose is to ease development of a Vaadin JavaEE 6 (mainly CDI and JPA) based application.
The main focus for me was to create forms and tables easily from my persistent enties. Unfortunately I cannot use the JPAContainer (half-commercial with no budget :frowning: ), so I have also built a very basic EntityContainer to bridge from Vaadin to JPA.

The CDI part of my addon is quite simple. I already started with looking at the cdi utils for migrating my stuff to it. If you like maven, I mavenized the cdiutils here: https://github.com/thomasletsch/cdiutils. The thing which prevents me from migrating is that I started with Vaadin 7 and they have quite some differences in the Application and Window codes. Did you already had a chance to look at the current Vaadin 7 development?

For anyone interested, the JavaEE Addon code is accessible under https://github.com/thomasletsch/javaee-addon with an example on how to use it here: https://github.com/thomasletsch/javaee-addon-sample.

Its still just work started.

Regards,
Thomas

Hi Frédéric

If you’re using Servlet 3.0 api, you can define the widgetset within the annotation like so:
@WebServlet(urlPatterns = “/*”, initParams = { @WebInitParam(name = “widgetset”, value = “org.vaadin.virkki.cdiutils.ui.MyCoolWidgetset”) })

Tomi

Hi Thomas

I personally like Maven but not everyone does so I’ve decided to keep the project non-mavenized in the repository. For now at least.
CDI Utils is currently only designed for Vaadin 6 apps but at some point I’ll have to start porting it to V7 as well. Vaadin 6 and 7 differ quite a bit so expect major changes to CDI Utils.

Tomi

Thanks for the add-on. I’m running into issues, and time permitting I’ll try to debug them or at least put together test cases to help address them. In the mean time, here’s what I’m hitting.

I’ve been trying to use it in JBoss AS 7.1.1.Final, and have run into a few hiccups that’re preventing me from getting far.

I replaced my custom CDI-enabled Vaadin servlet with yours and altered my Vaadin app class to extend AbstractCdiApplication, then redeployed. The deployment succeeded, but access to the application immediately failed with a somewhat inscrutable error “java.lang.NoClassDefFoundError: org/jboss/weld/util/reflection/Formats$6” (see below) that almost seems internal to Weld, but didn’t occur without the cdi utils extension. I’m looking at putting together a self-contained test case, as the code in question is a bit big to paste.

Before deployment I’d tried to change my @SessionScoped components to @VaadinScoped(VaadinScope.APPLICATION), but found that deployment would then fail with errors about circular dependencies: “WELD-001443 Pseudo scoped bean has circular dependencies”. It appears that CDI wasn’t recognising the @VaadinScoped annotation as a valid scope (or it’s a pseudo-scope) and wasn’t able to inject proxied instances to handle circular dependencies, so it was failing. See https://issues.jboss.org/browse/WELD-1152 .

I worked around that by decoupling the circular dependency via CDI events ( @Inject Event and @Observes ), which is a bit cleaner anyway. I’m not convinced the VaadinScope is actually doing what it’s meant to, though.

During testing, I noticed that AbstractCdiApplication isn’t proxyable because it has final methods. While it’s a real PITA that CDI can’t proxy final methods, until/unless the JVM is fixed that’s the case, so final methods should be avoided for classes that might need to be proxied. Since the Vaadin application may well need to be proxied to be injected into components that need to reference it, this should probably be fixed.

Anyhow, I can’t seem to get it working, so roll back to my custom CDI-enabled Vaadin servlet and to using @SessionScoped beans. Since the CDI utils have a 1:1 session-to-application mapping this isn’t really very different to @VaadinScoped(APPLICATION). I’ll be interested in testing out any ideas you have and, time permitting, will see if I can produce a test case for the below:


exception

javax.servlet.ServletException: java.lang.NoClassDefFoundError: org/jboss/weld/util/reflection/Formats$6
	com.vaadin.terminal.gwt.server.AbstractApplicationServlet.handleServiceException(AbstractApplicationServlet.java:1010)
	com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:548)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
	org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:62)

root cause

java.lang.NoClassDefFoundError: org/jboss/weld/util/reflection/Formats$6
	org.jboss.weld.util.reflection.Formats.formatAsFormalParameterList(Formats.java:137)
	org.jboss.weld.introspector.jlr.WeldMethodImpl.toString(WeldMethodImpl.java:183)
	org.jboss.weld.exceptions.WeldExceptionKeyMessage.<init>(WeldExceptionKeyMessage.java:55)
	org.jboss.weld.exceptions.WeldException.<init>(WeldException.java:65)
	org.jboss.weld.bean.AbstractClassBean.defaultPostConstruct(AbstractClassBean.java:518)
	org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget.postConstruct(ManagedBean.java:174)
	org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:291)
	org.jboss.weld.context.unbound.DependentContextImpl.get(DependentContextImpl.java:61)
	org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:616)
	org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:681)
	org.jboss.weld.injection.FieldInjectionPoint.inject(FieldInjectionPoint.java:118)
	org.jboss.weld.util.Beans.injectBoundFields(Beans.java:703)
	org.jboss.weld.util.Beans.injectFieldsAndInitializers(Beans.java:712)
	org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget$1$1.proceed(ManagedBean.java:161)
	org.jboss.weld.injection.InjectionContextImpl.run(InjectionContextImpl.java:48)
	org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget$1.work(ManagedBean.java:157)
	org.jboss.weld.bean.ManagedBean$FixInjectionPoint.run(ManagedBean.java:131)
	org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget.inject(ManagedBean.java:153)
	org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:290)
	org.vaadin.virkki.cdiutils.application.VaadinContext$VaadinContextImpl.doGet(VaadinContext.java:86)
	org.vaadin.virkki.cdiutils.application.VaadinContext$VaadinContextImpl.get(VaadinContext.java:74)
	org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:616)
	org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:643)
	org.vaadin.virkki.cdiutils.application.AbstractCdiApplicationServlet.getNewApplication(AbstractCdiApplicationServlet.java:43)
	org.vaadin.virkki.cdiutils.application.AbstractCdiApplicationServlet.getNewApplication(AbstractCdiApplicationServlet.java:1)
	com.vaadin.terminal.gwt.server.AbstractApplicationServlet.createApplication(AbstractApplicationServlet.java:984)
	com.vaadin.terminal.gwt.server.AbstractApplicationServlet.findApplicationInstance(AbstractApplicationServlet.java:807)
	com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:456)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
	org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:62)

Hi Craig

I’ve been using CDI Utils with JBoss AS 7 since I released it and haven’t ran into any problems yet. The Weld-specific error you got does not have anything to do with CDI Utils as it’s provider agnostic. Try out the example application (
https://github.com/tomivirkki/cdiutils-addressbook
) and see if you can reproduce the issues mentioned. The application has a hidden test-view (accessible with alt-c) for testing bean life cycles.


Here are the two main arguments against using @SessionScoped Applications (or any other session scoped beans for that matter) in Vaadin 6 apps:

[b]

  1. HttpSession lifecycle does not equal to that of Vaadin Application’s:
    [/b]

Whenever Application.close() is called, you should end up with a new fresh Application instance even though the session hasn’t changed. With @SessionScoped Application you’ll always end up having the same instance throughout the session lifecycle. You could go and try to artificially limit the session lifecycle within the Application class (as was done in earlier versions of CDI-Utils) but a scope that actually matches Vaadin Application lifecycle is much cleaner an approach.


2. AbstractCommunicationManager uses an Application instance as a monitor object for synchronized blocks:

AbstractCommunicationManager class in Vaadin 6 uses application-variable as the monitor object in many methods. This is fine for regular applications because each Application instance is individual. However, @SessionScoped being a normal scope uses beans trough a proxy object that in most cases seems to be common for all instances of the bean. This means that the synchronized blocks would actually be using the proxy (shared by ALL applications) as the monitor object. If a user would then make a request that takes a long time to process, all other users would then have to wait for the process to finish before receiving any response to their own requests from the server. The issue was discussed in
https://vaadin.com/forum/-/message_boards/view_message/963494
.

@VaadinScoped tackles both of these issues because 1. it has a unique lifecycle that matches the lifecycle of Vaadin Applications and 2. it’s a pseudo-scope and thus accesses the bean instances directly (not trough a proxy).

Tomi

Thanks for your comments and for explaining about the scoping issues, I really appreciate it.

I’ll do some more testing to try to isolate the issue. I shouldn’t really have assumed it was the addon without at least testing the demo project, sorry about that. I won’t be too surprised if it’s tripping over another dependency in the project. More digging to follow. Sorry I didn’t check properly before posting.

I’ll have to check and see if the AbstractCommunicationManager has changed for 7.x or can be changed - unless you’ve been down that path already? Not being able to proxy the Application is a pain. Using a dedicated monitor object in the application shouldn’t be a significant cost. Being able to have VaadinScope as a NormalScope not a pseudo-scope for 7.x would be rather handy.

Hmm. I can’t reproduce the issues after mavenizing the address book demo and importing all my main project’s dependencies. Frustrating.

I’ll dig further and see if I can find out what’s going on.

Oddly, I can no longer reproduce the internal Weld exceptions when adding cdi-utils to my main project. Bizarre.

I’ve managed to get things working, but working with a pseudo-scope is certainly interesting and makes things quite a bit more complicated at times. Heavy use of Instance to explicitly proxy objects helps, but so far it’s been a bit frustrating and has some oddities compared to using normal scopes. CDI doesn’t seem to be able to detect issues and fail the deployment as well. I haven’t worked with CDI pseudo-scopes much so part of the issue is my own inexperience in the area.

It would’ve improved my experience of porting over to cdi-utils a LOT if the fact that @VaadinScoped is a pseudo-scope, and some of the limitations involved with that, were documented along with how they’re worked around. Once I have a bit of a better understanding of this I’ll be happy to write appropriate documentation so the next guy doesn’t get as confused+frustrated as I was.

While reading the addressbook example code, trying to figure out why it worked and mine didn’t, I noticed a few things I wanted to ask about, things that might want to be clarified in the addressbook example sources:

  • In the addressbook demo MainViewImpl, why do you inject Instance, Instance, Instance and Instance, but directly inject HelpWindow and SharingOptions? All four are @VaadinScoped and appear to be owned by the MainViewImpl. Is this just for lazy initialization? If I convert all of them to directly injected it seems to work OK, so I’m guessing it’s just lazy init, but wanted to be sure.

  • Why do you have to inject Instance into AddressBookApplication and use mainView.get() ? If I modify it to inject directly the injection site is silently left null, causing an NPE on startup. The object has been enriched by the time init() runs, otherwise the Instance would be null. My (admittedly limited) understanding of CDI says that “@Inject T t” should be functionally equivalent to using an unqualified@Inject Instance t;” and “Instance.get()” but clearly it isn’t in the case of @VaadinScoped, though it seems to be for dependent scope and for the normal scopes. Is this because @VaadinScoped is an unproxyable pseudo-scope so CDI can’t inject proxies where scopes are mismatched, like @VaadinScoped(APPLICATION) of AddressBookApplication and @VaadinScoped(WINDOW) of MainViewImpl? If so, shouldn’t there be a deployment error not a silent injection failure / null injection site in this case? What obvious thing am I missing here?

Has something changed there in Vaadin 7?

Hi There,

I started using the MVP component from the CDI addon.
I encountered one issue when using Interceptors in combination with the AbstractPresenter class.

If you specify the execution of a interceptor in a concrete AbstractPresenter implementation, the ViewInterface instance cannot be retrieved due to the fact that the annotation ViewInterface is not specified as @Inherited. Maybe you can fix this or present another solution to this problem.

thanks!
Wilco

Hi Craig
Yes I’ve used Instance to lazily inject beans in various places. Especially beans that take more time to initialize.
For now all VaadinScoped beans that are injected directly to the Application must use Instance for injection. This is because DI on the AbstractCdiApplication class is executed soon after its instantiation and we have no change to assign RequestData fields before that. I’ll possibly look into this later on but all this will change anyway in the upcoming 2.0 version for Vaadin 7.

Hi Sebastian
Take a look at the ticket by Craig Ringer at
http://dev.vaadin.com/ticket/9156

I just released a stable 1.0 version of CDI Utils for Vaadin 6 series. The beta period has been ongoing since the end of March and for the new release I’ve fixed the couple of issues that have come up since then.

Awesome 2.0 version for Vaadin 7 is also on the way and is currently available as source code at
https://github.com/tomivirkki/cdiutils/tree/vaadin7
(Requires Vaadin nightly build from 25.8.2012!)
As Vaadin 7.0 is still under development, I feel it’s too early to publish it on Vaadin Directory now but once V7 starts to look mature enough I’ll unleash CDI Utils 2 as well.