Skip to main content

JSF Tip #31 - Migrate your @ManagedProperty annotations

Posted by mriem on November 1, 2013 at 5:49 AM PDT

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. If you want to support more types you will have to add a new producer method for each additional type.

And that is it.

Enjoy!

Related Topics >>