CDI Utils add-on

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.

Hi Tom,

I’m getting the following error on JBoss 7.1


11:12:21,358 ERROR [org.jboss.msc.service.fail]
 (MSC service thread 1-3) MSC00001: Failed to start service jboss.deployment.unit."com.stuff.ui-0.0.1-SNAPSHOT.war".WeldService: org.jboss.msc.service.StartException in service jboss.deployment.unit."com.stuff.ui-0.0.1-SNAPSHOT.war".WeldService: org.jboss.weld.exceptions.UnproxyableResolutionException: WELD-001437 Normal scoped bean class org.vaadin.virkki.cdiutils.application.AbstractCdiApplication is not proxyable because the type is final or it contains a final method public final com.vaadin.ui.Window org.vaadin.virkki.cdiutils.application.AbstractCdiApplication.getWindow(java.lang.String) - Managed Bean [class com.stuff.ui.StuffApplication]
 with qualifiers [@Any @Default]
.
	at org.jboss.as.weld.services.WeldService.start(WeldService.java:83)
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811) [jboss-msc-1.0.2.GA.jar:1.0.2.GA]

	at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746) [jboss-msc-1.0.2.GA.jar:1.0.2.GA]

	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [classes.jar:1.6.0_33]

	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [classes.jar:1.6.0_33]

	at java.lang.Thread.run(Thread.java:680) [classes.jar:1.6.0_33]

Caused by: org.jboss.weld.exceptions.UnproxyableResolutionException: WELD-001437 Normal scoped bean class org.vaadin.virkki.cdiutils.application.AbstractCdiApplication is not proxyable because the type is final or it contains a final method public final com.vaadin.ui.Window org.vaadin.virkki.cdiutils.application.AbstractCdiApplication.getWindow(java.lang.String) - Managed Bean [class com.stuff.ui.StuffApplication]
 with qualifiers [@Any @Default]
.
	at org.jboss.weld.util.Proxies.getUnproxyableClassException(Proxies.java:225)
	at org.jboss.weld.util.Proxies.getUnproxyableTypeException(Proxies.java:178)
	at org.jboss.weld.util.Proxies.getUnproxyableTypesExceptionInt(Proxies.java:193)
	at org.jboss.weld.util.Proxies.getUnproxyableTypesException(Proxies.java:167)
	at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:111)
	at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:127)
	at org.jboss.weld.bootstrap.Validator.validateBeans(Validator.java:346)
	at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.java:331)
	at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:366)
	at org.jboss.as.weld.WeldContainer.start(WeldContainer.java:83)
	at org.jboss.as.weld.services.WeldService.start(WeldService.java:76)
	... 5 more

My app code is (more or less):


@SessionScoped
public class StuffApplication extends AbstractCdiApplication
{
    @Override
    public void init()
    {
        final Window window = new Window("My Vaadin Application");
        setMainWindow(window);
        Button button = new Button("Click Me");
        button.addListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
                window.addComponent(new Label("Thank you for clicking"));
            }
        });
        window.addComponent(button);
        
    }
}

@WebServlet(urlPatterns={"/*", "/VAADIN/*"}, initParams = @WebInitParam(name = "application", value = "com.stuff.ui.StuffApplication"))
public class StuffApplicationServlet extends CdiApplicationServlet {
    
    @Override
    protected Application getNewApplication(HttpServletRequest request) throws ServletException {
        Application app = super.getNewApplication(request);
//        Principal principal = request.getUserPrincipal();
//        if (principal == null) {
//            throw new ServletException("Access denied");
//        }
//
//        if (request.isUserInRole(UserRoles.ROLE_DIRECTOR)) {
//            app.setUserRole(UserRoles.ROLE_DIRECTOR);
//        } else if (request.isUserInRole(UserRoles.ROLE_PAYROLL_ASSISTANT)) {
//            app.setUserRole(UserRoles.ROLE_PAYROLL_ASSISTANT);
//        } else if (request.isUserInRole(UserRoles.ROLE_PROJECT_MANAGER)) {
//            app.setUserRole(UserRoles.ROLE_PROJECT_MANAGER);
//        } else {
//            throw new ServletException("Access denied");
//        }
//
//        app.setUser(principal);
        return app;
    }
}

Maybe org.vaadin.virkki.cdiutils.application.AbstractCdiApplication.getWindow(java.lang.String) shouldn’t be final?

Cheers,
Dino

Hi Dino
Appears that StuffApplication has been declared @SessionScoped in your code. The container tries to proxy it and fails because of the final methods.
AbstractCdiApplication is a @VaadinScoped bean per se and thus does not require proxies (@VaadinScope is a pseudo-scope). Removing the @SessionScoped declaration from your application class should do the trick.

After my talk to Ville, I decided to give you CDI-Utils a chance.
We wrote some kind of annotation-based component generation framework like you did with @Preconfigured - without knowing about your addon at all :smiley:

There are some things I’m missing in your addon:

[size=4]


@Preconfigured(margin=boolean)

[/size]
You should be able to set all sides seperatly. You could request a boolean and analyse the given boolean values in it - something like:

All sides’ margins are true

Top & bottom margins are true
Left & right margins are false

Apply your default MarginInfo settings :wink:

[size=4]


@Preconfigured(styleName=String)

[/size]
Same for styleName - would be better to request a String array.

@Preconfigured(styleName = Styles.MENU_BAR_NAVIGATION + " " + Styles.WHAT_EVER)

is ugly and cascading String is not the best choise.

@Preconfigured(styleName = {Styles.MENU_BAR_NAVIGATION, Styles.WHAT_EVER})

Is cool! yay… :smiley:

[size=4]


Compatibility with Navigator7

[/size]
Is there any way to add support for the Navigator7 plugin?

Hi Matthias
Thanks for the suggestions for Preconfigured. I’ll add them to the next minor version of CDI Utils.

I haven’t looked into Navigator 7 before but at first glance it seems cool. Getting it to function with current version of CDI Utils would require some modifications.
The upcoming vaadin-cdi package for Vaadin 7 has some similar features, take a look at
https://github.com/vaadin/vaadin-cdi-integration

Missing check. (v1.0.0)
If a Presenter does not have a @ViewInterface() Annotation it causes a null pointer, It would be better to throw an exception indicating the presenter is missing an annotation…

WARNING: StandardWrapperValve[domain]
: PWC1406: Servlet.service() for servlet domain threw exception
java.lang.NullPointerException
	at org.vaadin.virkki.cdiutils.mvp.MvpExtension$1.getObservedQualifiers(MvpExtension.java:54)
	at org.jboss.weld.resolution.TypeSafeObserverResolver.matches(TypeSafeObserverResolver.java:41)
	at org.jboss.weld.resolution.TypeSafeObserverResolver.matches(TypeSafeObserverResolver.java:30)
	at org.jboss.weld.resolution.TypeSafeResolver.findMatching(TypeSafeResolver.java:107)
	at org.jboss.weld.resolution.TypeSafeResolver.access$000(TypeSafeResolver.java:42)
	at org.jboss.weld.resolution.TypeSafeResolver$ResolvableToBeanSet.apply(TypeSafeResolver.java:53)
	at org.jboss.weld.resolution.TypeSafeResolver$ResolvableToBeanSet.apply(TypeSafeResolver.java:44)
	at com.google.common.collect.ComputingConcurrentHashMap$ComputingValueReference.compute(ComputingConcurrentHashMap.java:355)
	at com.google.common.collect.ComputingConcurrentHashMap$ComputingSegment.compute(ComputingConcurrentHashMap.java:184)
	at com.google.common.collect.ComputingConcurrentHashMap$ComputingSegment.getOrCompute(ComputingConcurrentHashMap.java:153)
	at com.google.common.collect.ComputingConcurrentHashMap.getOrCompute(ComputingConcurrentHashMap.java:69)
	at com.google.common.collect.ComputingConcurrentHashMap$ComputingMapAdapter.get(ComputingConcurrentHashMap.java:393)
	at org.jboss.weld.resolution.TypeSafeResolver.resolve(TypeSafeResolver.java:92)
	at org.jboss.weld.manager.BeanManagerImpl.resolveObserverMethods(BeanManagerImpl.java:450)
	at org.jboss.weld.manager.BeanManagerImpl.fireEvent(BeanManagerImpl.java:585)
	at org.jboss.weld.event.EventImpl.fire(EventImpl.java:69)
	at org.vaadin.virkki.cdiutils.mvp.ViewComponent.fireViewEvent(ViewComponent.java:45)
	at org.vaadin.virkki.cdiutils.mvp.AbstractView.openView(AbstractView.java:35)
	at com.bluedigital.ui.main.MainViewImpl.setView(MainViewImpl.java:94)
	at com.bluedigital.ui.main.MainViewImpl.initView(MainViewImpl.java:73)
	at org.vaadin.virkki.cdiutils.mvp.AbstractView.openView(AbstractView.java:30)
	at com.bluedigital.ui.BluedigitalApplication.init(BluedigitalApplication.java:77)
	at com.vaadin.Application.start(Application.java:551)
	at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.startApplication(AbstractApplicationServlet.java:1219)
	at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:484)
	at com.bluedigital.ui.BluedigitalApplication$BluedigitalServlet.service(BluedigitalApplication.java:193)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:770)
	at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
	at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
	at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
	at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
	at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
	at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
	at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
	at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
	at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
	at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
	at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
	at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
	at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
	at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
	at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
	at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
	at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
	at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
	at java.lang.Thread.run(Thread.java:722)

Thanks Tomi :slight_smile:

Thanks :slight_smile:

Hello Tomi,

what is the reason why you don’t support portlets in CDI-Utils yet?
Is it because you simply don’t need the portlet support although it would be possible to integrate it, or is it because there are technical issues that prevent CDI-Utils to work with portlets.

I was interested in using CDI-Utils in my project but I do portlet development so I’d need the portlet support…

If integrating the portlet support is just creating a CDI version of the Vaadin portlet class (like you did with the application) maybe I could have a look at the code and possibly contribute this. If there are other technical issues that make the portlet support too complicated, I can’t afford spending that much time on this and I would have to look at a different direction.

Please let me know what you think about portlet support and let’s figure out where we can go from here.

Kind regards,

Alex

Hi Alex

Originally I implemented CDI Utils for servlets merely because I didn’t see as much benefits in it for smaller applications such as portlets.

But that doesn’t mean it couldn’t work in such an environment. Making it tick might be as simple as implementing the CdiApplicationPortlet just like the existing CdiApplicationServlet or it might require some further tweaking. I would guess that beans cannot be directly injected to portlets so at least it’d require executing a JNDI-lookup for the BeanManager and doing the necessary injections to CdiApplicationPortlet “manually”.

The best bet might be to run Liferay bundled with a Java EE 6 compatible server such as JBoss AS or GlassFish.

Hi,

I try to use CDI Utils to inject UI components and EJBs. Everything works fine including the MVP pattern, but at some point it seem that objects are no longer injected. Is there good way to figure out why an injection doesn’t take place.

For example currently I have the following issue:

  • Create the application
  • View is injected (MVP, actions can trigger the view change; all views are injected and views are using EJBs)
  • One view opens a subwindow - subwindow is also injected
  • The window shows a wizard using the Wizard AddOn - the wizard is also injected
  • The wizard should add several steps, but the steps are always null (@Inject - @EJB etc. instances are always null)

Any idea how to solve that issue?

I run the application on JBoss.

Any support is welcome.

Thanks.

Karsten

Hi Tomi

In many cases “beanStore” is not initialized in our context. I had to modify the code as

instead of

in AbstractCdiApplication. The application server reports that there is a memory leak because it could not be removed properly.

Fyi.

Could someone please explain why there are two scopes and which one to chose in which situation? I am a bit confused.

Thank you!

Hi there,

intresting Addon for using CDI in a VaadinApplikation.
Was wondering if there are any Plans to also Support the Vaadin Touchkit?
I personly do think it would be nice to be able to use CDI also for a Mobile-UI so I could Inject the Same Beans as I would use for a Desktop Version.

Marc

Window scope is to support single application instance over multiple browser tabs (it is discussed somewhere up in this thread if I’m not mistaken) .
Application scope would be the same instances over multiple browser tabs ( not advised for gui components ) .

Usually you should be using Window scope for all gui related components like views, and other view components and Application scope for application state that is independent from the gui…

If you look at Tomi’s demo application you will see the TextBundle implementatin org.vaadin.virkki.cdiutils.addressbook.util.Lang is Application scoped since you want only one instance of it for the Application instance, but most ( if not all the Components ) default to Window Scope .

Hi Marc
At least for the Vaadin 6 version this might be tricky as both Cdi Utils and TouchKit require a custom servlet. The new Cdi Utils 2 (for Vaadin 7) no longer requires its own servlet so at least in theory you could combine them. I haven’t tried it out myself though.

Hi,
i have started to use CDIUtils addon for my project and it seems interesting.

The only problem i have “stumbled” upon is when i need to change the locale of the Vaadin application.
As far as i know one way to change the locale dynamically is to recreate my widgets (i use some buttons and labels in my layout).
Specifically i create the different layouts in separate classes like the following :


@VaadinScoped
public class MyView extends VerticalLayout 
{
      @EJB
      SomeService myService;

      Button aButton = new Button();
  ....
	public LoginView() 	
	{ 
		builtLayout();
	}

     public void builtLayout() 
     {
        addComponent(aButton);
          ....
     }
}

which I inject in the Vaadin Application using


@Inject
Instance<MyView> myView;

Since all the “views” (layouts) have been injected and created how is it possible to recreate them when the user changes the locale?
I use Vaadin 6.8.x

P.S. Ok this question might be not 100% related to the CDIUtils addon so I apologize in advance.

In my opinion you have two possibilities to achieve this. When you directly inject via

@Inject 
MyClass myClass

you can use producers that you call every time you whish to ge a new Instance or you inject dynamically via

@Inject
Instance<MyClass> myClass

and get everytime a new Instance when you call myClass.get()

Hi Filip and the rest of you interested in this issue.

I18n is actually pretty easy to implement for Vaadin Components using CDI so I decided to include this feature in the newest CDI Utils release.
If you’ve used the @Preconfigured “captionKey” and “labelValueKey” features to get texts for your Components, then all you need to do to update the component captions/label values to a new language is to fire a localization event inside your app. This will not re-initialize your views but only update the visible texts.
You can find an example of this in the
CDI Utils Address Book project
. Check it out and see what you think.

Thanks Tomi,
I will give it a try!