JSF Tip #31 - Migrate your @ManagedProperty annotations

If you read the blog entry about migrating to @Named annotation you might wonder how you would migrate your @ManagedProperty annotations.

Since CDI is a specification on its own, it does not deal with JSF specific artifacts. However with very little work you can have a very similar setup.

First we define our own custom annotation @ManagedProperty


    package test.managedproperty;

    import java.lang.annotation.Retention;
    import java.lang.annotation.Target;
    import javax.enterprise.util.Nonbinding;
    import javax.inject.Qualifier;
    import static java.lang.annotation.ElementType.FIELD;
    import static java.lang.annotation.ElementType.METHOD;
    import static java.lang.annotation.ElementType.PARAMETER;
    import static java.lang.annotation.ElementType.TYPE;
    import static java.lang.annotation.RetentionPolicy.RUNTIME;

    @Qualifier
    @Retention(RUNTIME)
    @Target({METHOD, FIELD, PARAMETER, TYPE})
    public @interface ManagedProperty {

        @Nonbinding String value() default "";
    }
        

Next we define a producer method that knows about our own @ManagedProperty annotation


    package test.managedproperty;

    import javax.el.ELContext;
    import javax.el.ExpressionFactory;
    import javax.el.ValueExpression;
    import javax.enterprise.context.Dependent;
    import javax.enterprise.inject.Produces;
    import javax.enterprise.inject.spi.InjectionPoint;
    import javax.faces.application.Application;
    import javax.faces.context.FacesContext;

    public class ManagedPropertyProducer {

        @Produces @ManagedProperty("") @Dependent
        public String getStringManagedProperty(InjectionPoint injectionPoint) {
           return (String) getObjectManagedProperty(injectionPoint, String.class);
        }

        private Object getObjectManagedProperty(InjectionPoint injectionPoint, Class expectedType) {
           String value = injectionPoint.getAnnotated().getAnnotation(ManagedProperty.class).value();
           FacesContext context = FacesContext.getCurrentInstance();
           Application application = context.getApplication();
           ExpressionFactory ef = application.getExpressionFactory();
           ELContext elContext = context.getELContext();
           ValueExpression ve = ef.createValueExpression(elContext, value, expectedType);
           return ve.getValue(elContext);
        }
    }
        

Third we use it


    @Inject
    @ManagedProperty("#{param.param1}")
    private String param;

    public String getParam() {
        return param;
    }

    public String getParam() {
        return param;
    }
        

Note this particular implementation only allows you to have @ManagedProperty fields that are Strings, and this is because the producer methods are safely typed.

Posted November 1, 2013

Up