Search code examples
jsfcdiinjectmanaged-property

CDI Replacement for @ManagedProperty


I'm trying to convert some code from Richfaces 4 showcase to use CDI instead of JSF annotations.

I understand that I can use @Named to replace @MangedBean and @Inject to replace @ManagedProperty. But I'm having some trouble. I'm trying to convert the RichFaces Tree example specifically.

I have made the following changes and I know this is not correct so please don't use this:

//@ManagedBean
//@ViewScoped
@Named
@SessionScoped
public class TreeBean implements Serializable {
    private static final long serialVersionUID = 1L;
//    @ManagedProperty(value = "#{cdsParser.cdsList}")
//    private List<CDXmlDescriptor> cdXmlDescriptors;
    @Inject
    private Instance<CDXmlDescriptor> cdXmlDescriptors;
// I also Tried :
//  @Inject
//    private CDParser cdsParser;
//    private List<CDXmlDescriptor> cdXmlDescriptors = cdsParser.getCdsList();

........

Then I added (and I'm not sure this is needed):

@Named
@SessionScoped
public class CDXmlDescriptor implements Serializable { ...

and changed:

//@ManagedBean(name = "cdsParser")
@Named("CDParser")
//@Named
@SessionScoped
public class CDParser implements Serializable{
    
    /**
     * 
     */
    private static final long serialVersionUID = 3890828719623315368L;
    @Named
    private List<CDXmlDescriptor> cdsList;

I cannot figure out the proper way to replace @ManagedProperty(value = "#{cdsParser.cdsList}") using CDI?


Solution

  • On JSF 2.3+ you can use javax.faces.annotation.ManagedProperty for this. It works the same way as the old and since JSF 2.3 deprecated javax.faces.bean.ManagedProperty, you only need to add @Inject to it.

    Example:

    import javax.faces.annotation.ManagedProperty;
    ...
    @Inject
    @ManagedProperty(value = "#{cdsParser.cdsList}")
    private List<CDXmlDescriptor> cdXmlDescriptors;
    

    If you're not on JSF 2.3+ yet, then you need a producer field or a producer method to make it injectable.

    Example for producer field:

    import javax.enterprise.inject.Produces;
    ...
    @Named 
    @Produces 
    private List<CDXmlDescriptor> cdsList;
    

    Example for producer method:

    import javax.enterprise.inject.Produces;
    
    private List <CDXmlDescriptor> cdsList;
    ...
    @Named("cdsList") 
    @Produces 
    public List<CDXmlDescriptor> getCdsList {
      return cdsList;
    };
    

    This works if there is no other producer field or producer method that returns the same bean type. Otherwise you need to introduce a special qualifier for your producer field to resolve ambiguity:

    import static java.lang.annotation.ElementType.TYPE;
    import static java.lang.annotation.ElementType.FIELD;
    import static java.lang.annotation.ElementType.PARAMETER;
    import static java.lang.annotation.ElementType.METHOD;
    import static java.lang.annotation.RetentionPolicy.RUNTIME;
    import java.lang.annotation.Retention;
    import java.lang.annotation.Target;
    import javax.inject.Qualifier;
    
    
    @Qualifier
    @Retention(RUNTIME)
    @Target({METHOD, FIELD, PARAMETER, TYPE})
    public @interface CdsList {
    }
    

    with

    @Named @Produces @CdsList
    private List<CDXmlDescriptor> cdsList;