CDI MVP add-on

Good things are happen here.
I’m studding vaadin and working on a Java EE application, I use MVP to make one simple view, and was thinking how to implement this pattern in cdi, to cut down the effort of wire Model View Presenter Layouts Applications and CDI Services toggetther.

I think this approach is in development, but Do someone know some article or tutorial to get started? I will use the example.
How stable is this approach right now, in terms of API changes? I’m planning to build an production application not so complex and with low concurrent with this archtecture.

I see that problems like the same view instance per client, where the same view instance is served for the client (one form or window by example) are solved in this case, by giving the View @UIScoped. Another good thing is the Lazy instantiation.

Hi guys,

I’ve a problem with CDI. Injection is only working sometimes…

@UIScoped
public class CalendarComponent extends ViewComponent {

    @Inject // Working
    private CustomCalendar calendar; // CustomCalendar only extends Calendar, nothing else

@Inject // Not working
private Calendar cal;

@Inject // Not working
    private Label label;

    @Inject // Working
    @LabelProperties(immediate = false, id = "3")
    private Label label;
    
    ...
}

Here’s the error I got when injection doesn’t work :

SEVERE: Exception while loading the app : WELD-001408 Unsatisfied dependencies for type [Label]
 with qualifiers [@Default]
 at injection point [[field]
 @Inject private com.project.ui.component.calendar.CalendarComponent.label]
org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Label]
 with qualifiers [@Default]
 at injection point [[field]
 @Inject private com.project.ui.component.calendar.CalendarComponent.label]

The weird thing is it does work when it’s my component, or when using a component with @XXProperties, but not for others.

I suspect it has something related to beans.xml, because I think CDI 1.0 needs this file and the vaadin-client.jar/META-INF doesn’t contains a beans.xml

I’m using Glassfish 3.1.2.2, Netbeans 7.3.1 and Java EE 6.

Any suggestions ?

Thanks a lot,

Cédric

Hi Cedric

Only the modules containing beans.xml descriptor file are scanned for CDI beans. Your own module most likely contains the file and that’s why CustomCalendar is recognized as an injectable bean. However, Calendar and Label come from Vaadin jar archives that don’t have the marker file included and thus are not scanned for beans by the container.

Vaadin core component injected to a field with @XXProperties -annotation works because the container discovers a producer method for it in the CDI Properties add-on jar (which in turn does have a beans.xml descriptor).

All this behaviour is defined by the CDI specification. The first Q/A at
http://www.cdi-spec.org/faq/
explains the rationale behind beans.xml in short.

The add-on was formerly part of a plugin called CDI Utils. CDI MVP was extracted as an individual add-on a month ago due to various reasons and the API was partially changed/cleaned up in the process. Applied changes stem mostly from the user feedback and better insight gained in personal use.

From the users’ point of view the current API should be quite stable. I might add some functionality regarding the compatibility with Vaadin Navigator (as discussed earlier in this thread) but any future change should not invalidate the existing API.

Sounds strange indeed. Really can’t say what can cause such behaviour on your staging server.
Anyway, I’ll change the beans.xml to the simple version for the next release to avoid this in the future.

Thanks for the Navigation source files. I’ll take a look asap.

Hi Tomi,

Thanks for the explanation, everything is clear for me now.
Is the beans.xml planned to be integrated to the official release ?

Because right now, I have no choice but recompile myself de vaadin-client with the beans.xml right ?

I don’t think Vaadin core libraries will nor should contain the beans.xml file. Wouldn’t recommend compiling a custom build of the libraries just for this purpose either.

However, if you do want to @inject a Vaadin core component in your project, there are some options:

[b]

  1. Create producers in your own project
    [/b]
@Produces
public Button createButton(){
    return new Button();
}

This allows you to change the injected Button later on if you wish (by adding a styleName for all you buttons at once or changing the implementation to NativeButton etc.). Like so:

@Produces
public Button createButton(){
    Button button = new NativeButton();
    button.addStyleName("mybutton");
    return button;
}

(Using a qualifier wouldn’t hurt here either)


2. Create a Button extension in your project

public class MyButton extends Button{...}


3. Use the @XXProperties qualifier (CDI Properties contains the necessary producers)

@Inject
@ButtonProperties
private Button button;

That’s great, thank you for your help Tomi !

Hi,

I’m trying to use sub-windows in my app to modify some values.
I’m using CDIViews and using the fireViewEvent(…) method to call my EJB and I would also like to use this method in my own subwindows.

The problem is I need to extends Window therefore I can’t extends ViewComponent too.
Any ideas how I can reach the presenter class using fireViewEvent(…) from a subwindow using the MVP Pattern ?

Thanks a lot,

Cédric

The Content you want to display should be a View or extends ViewComponent.

I prefere to display a separate View imlementation in my SubWindows, but note there is a pitfall you should take care when displaying a View in a SubWindow , Views are currently UIScoped and thus you have one instance per UI, you cannot have two windows displaying the same View …

Usually I dont even create a subclass of Window, I simply initialize the window from where I want to display it…

    @Inject
    private Instance<WorkOrderEntryEditView> editView;

@Override
    public void editWorkOrderEntry(final AbstractWorkEntry entry) {
        final com.vaadin.ui.Window pop = new com.vaadin.ui.Window();
        pop.setCaption("Equipment Entry");
        final WorkOrderEntryEditView view = editView.get();
        view.enter();
        view.setWorkOrderEntry(entry);
        pop.setWidth(600.f, Unit.PIXELS);
        pop.setContent(view);
        pop.setClosable(false);
        pop.center();
        pop.setResizable(false);
        pop.addCloseListener(this);
        pop.setModal(true);
        UI.getCurrent().addWindow(pop);
    }

Great idea, I haven’t thought about doing it that way.
Thanks a lot !

Hi,

I’m using this addon in addition to the other vaadin-cdi-add-ons. Works like a charme.
Now I want to test my application. Here I run in a lot of problems. Which test-framework can you recommend? I tried CDI-Unit.

Hi Dennis

Haven’t tried CDI-Unit myself so can’t say much about that. But in general, for testing CDI applications I’d go with Arquillian (
http://arquillian.org/
).

Hi Tomi,

is there a way to use “@XXProperties qualifiers” with subclasses of the vaadin components?

Can I do something like:
@Inject @TextFieldProperties(captionKey = “someKey”)
protected MyTextField someString;

If that does not work: where can I find the source code of org.vaadin.addon.cdiproperties.producer.ComponentProducers?

Thanks a lot in advance,
Jürgen

Hello Jürgen
You may use the TextFieldProperties annotations with subclasses as well but then you’ll need to specify the “implementation” -property.
Also, the field must be of type TextField

@TextFieldProperties(captionKey = “someKey”, implementation = MyTextField.class)
protected TextField someString;

Tomi

Great, thank you! That was what I was looking for!

By the way: I couldn’t find the code for org.vaadin.addon.cdiproperties.producer.ComponentProducers on github. Is it available somewhere else?

Thanks again,
Jürgen

ComponentProducers is a generated java file so it’s not committed to the repository.

Hi Tomi,

while I got the “implementation”-property working, it seems that Injection into implementation classes does not work (also: @PostConstruct is not executed).

Are those implementation instances created with “new”? Is there a way to use CDI with implementation classes?

Thank you,
Jürgen

That’s correct. It won’t work as a cdi-bean as it’s instantiated with reflection.

Hi,
it seams to me, that the CDI-MVP package is broken, since Vaadin CDI 1.0.0.beta4.
On @UIscoped CDIVIEWs the presenter get’s a different View injectet than the one that is used for the user interaction.
I also tried to update to the version from git that should work with 1.0.0.beta4 but in this package the navigation test fails with the same issue.

Any hints how to get this working again ?

Stefan