users@glassfish.java.net

Re: Inconsistent behaviour between JSF2 and CDI injection in @FacesConverter . Possible Glassfish bug?

From: Dominik Dorn <dominik.dorn_at_gmail.com>
Date: Fri, 20 Aug 2010 12:42:44 +0200

Hello Craig,

I came up with this a few months ago. The answer I got was that it's
not a bug in
the implementation but in the specification that does not specify how
far CDI and JSF
should work together.

kind regards,
dominik

On Fri, Aug 20, 2010 at 11:16 AM, Craig Ringer
<craig_at_postnewspapers.com.au> wrote:
> [I've CC'd Sivakumar because of the similarity between this and the
> earlier issue I reported, as both involve inconsistencies between Weld
> and JSF2 injection in Glassfish. Hope you don't mind.]
>
>
> Hi
>
> I'm using the Mojarra JSF2 RI embedded in Glassfish 3.0.1 with CDI(weld)
> in a new project, and I seem to have hit another odd inconsistency
> between CDI and JSF2 injection. The previous one was a glassfish bug,
> but I'm not sure if this one is a bug or me doing something silly.
>
> I need to access a DAO facade (a @Stateless EJB) from a JSF2
> @FacesConverter. As apparently JSF2 doesn't support DI in converters
> (sigh) I have to look the EJB up via JNDI or obtain it indirectly via an
> EL lookup on an object that contains a reference to it.
>
> If I do an EL lookup via FacesContext in the converter, I can obtain the
> @SessionScoped model bean that has the @Stateless DAO EJB injected into
> it. This works fine whether using JSF2 or CDI.
>
> If the model bean is managed using CDI (ie @Named
> @javax.enterprise.context.SessionScoped and inject with @Inject), the
> field into which the DAO EJB is injected is null when the model bean is
> looked up via EL from the FacesConverter, even though it was non-null at
> @PostConstruct time in the same object.
>
> If I use JSF2 (ie use @ManagedBean @javax.faces.bean.SessionScoped and
> inject with @EJB), the injected dao ejb field is always non-null and can
> be accessed and used as expected.
>
> I've produced a self-contained test case in source-code and deployable
> war form to demonstrate this inconsistency. It can be found here:
>
> http://www.postnewspapers.com.au/~craig/public_files_keep/ErrorDemo2.war
> http://www.postnewspapers.com.au/~craig/public_files_keep/ErrorDemo2.zip
>
> Is this another CDI integration bug? Or is this not meant to work?
>
>
> A boiled-down outline of the code is that this works:
>
>
> @ManagedBean
> @javax.faces.bean.SessionScoped
> public class ModelBean implements Serializable {
>    private static final long serialVersionUID = 99L;
>
>    @EJB DemoEJB demoEJB;
>
>    @PostConstruct
>    protected void postConstruct() {
>        if (demoEJB == null) throw new IllegalStateException("NoEJB");
>    }
>
>    // blah blah
>
>    @FacesConverter(forClass=EntityObject.class)
>    public static class EntityObjectConverter implements Converter {
>
>        @Override
>        public Object getAsObject(FacesContext context, UIComponent
>                      component, String value) {
>            ModelBean modelBean =
>                (ModelBean)context.getApplication()
>                .getELResolver().getValue(
>                     context.getELContext(), null, "modelBean"
>                );
>            System.err.println("(EL) modelBean is " + modelBean +
>                 ", modelBean.demoEJB is " + modelBean.demoEJB);
>            return modelBean.demoEJB.getEntityForKey(value);
>        }
>    }
> }
>
>
>
> but this throws a NullPointerException when accessing members of
> ModelBean.demoEJB:
>
>
>
> @Named
> @javax.enterprise.context.SessionScoped
> public class ModelBean implements Serializable {
>    private static final long serialVersionUID = 98L;
>
>    @Inject DemoEJB demoEJB;
>
>    @PostConstruct
>    protected void postConstruct() {
>        if (demoEJB == null) throw new IllegalStateException("NoEJB");
>    }
>
>    // blah blah
>
>    @FacesConverter(forClass=EntityObject.class)
>    public static class EntityObjectConverter implements Converter {
>
>        @Override
>        public Object getAsObject(FacesContext context, UIComponent
>                              component, String value) {
>            ModelBean modelBean =
>                (ModelBean)context.getApplication().getELResolver()
>                    .getValue(
>                        context.getELContext(), null, "modelBean"
>                    );
>            // Note that "modelBean.demoEJB" is null here. WTF?
>            // It was a suitable EJB proxy object in @PostConstruct...
>            System.err.println("(EL) ModelBean is " + modelBean + ",
>                 modelBean.demoEJB is " + modelBean.demoEJB);
>            return modelBean.demoEJB.getEntityForKey(value);
>        }
>
>    }
>
> }
>
>
>
> --
> Craig Ringer
>
> Tech-related writing: http://soapyfrogs.blogspot.com/
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_glassfish.dev.java.net
> For additional commands, e-mail: users-help_at_glassfish.dev.java.net
>
>



-- 
Dominik Dorn
http://dominikdorn.com
http://twitter.com/domdorn
Tausche Deine Lernunterlagen auf http://www.studyguru.eu !