Injecting Resources Into UIComponent (aka does CDI work here?)
Asked Answered
D

3

7

I am writing a (composite) component that needs to interact with my DAO. Here is how the Java part is declared:

@FacesComponent(value="selectLocation")
public class SelectLocation extends UINamingContainer {

To get the DAO object, I tried the CDI annotation:

    @Inject private LocationControl lc;

And that didn't work so I tried the Faces annotation:

    @ManagedProperty (value = "@{locationControl}") private LocationControl lc;

Both cases nothing happens -- the property lc ends up as null after the constructor finishes.

I use CDI in all my backing beans and it all works. This would be using Weld inside GlassFish 3.1.1. Any suggestions on how to get the resource?

Dabster answered 23/8, 2011 at 20:30 Comment(3)
Dang I thought you were onto something there -- I tried java.inject.Named but still no joy.Dabster
Adding a @RequestScoped causes the application to be unable to deploy: WELD-001437 Normal scoped bean class javax.faces.component.UIComponent is not proxyable because the type is final or it contains a final method public final javax.faces.component.TransientStateHelper javax.faces.component.UIComponent.getTransientStateHelper().Dabster
The created component allows the user to select a Location object by browsing through a data base (JPA) of such objects. For that I need access to the DAO either directly or indirectly. But my DAOs are no different from my other CDI-managed beans -- they just have JPA annotations inside them like @PersistenceContext in them. I am reading the CDI specification now to see if there is something in beans.xml that can help.Dabster
D
5

I have a work-around for now, which is to basically put in the boiler-plate code that CDI et. al. is supposed to do away with. I now have this method:

public LocationControl getLocationControl() {
    if (lc != null) return lc;
    FacesContext fc = getFacesContext();
    Object obj = fc.getApplication().evaluateExpressionGet(fc, "#{locationControl}", LocationControl.class);
    if (obj instanceof LocationControl) lc = (LocationControl) obj;
    return lc;
}

I would like to know if anyone has a better solution.

Dabster answered 23/8, 2011 at 21:44 Comment(0)
S
3

There is a way to do this work without workarounds?

Yes, just use a backing bean the usual way.

<x:someComponent value="#{someBean.someProperty}" />

Wrap if necessary in a reusable tagfile/composite to keep it DRY:

<my:someComponent />
Spike answered 4/6, 2013 at 12:50 Comment(0)
H
2

I don't know if it also works for components, but with CDI + MyFaces CODI you have @Advanced to mark e.g. Phase-Listeners which should be able to use @Inject. If it doesn't work, you could create a feature request in their JIRA. They are pretty fast and there are frequent releases.

Or you use: MyBean myBean = BeanManagerProvider.getInstance().getContextualReference(MyBean.class); manually.

Housing answered 23/8, 2011 at 23:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.