Can @ManagedBean and @XxxScope be placed in a base class?

1.8k views Asked by At

I have two @ManagedBean (javax.faces.bean.ManagedBean), parent and child. The parent managed bean is not abstract because we have to give liberty to the developer to use the parent if enough or inherit it with a child that holds specifically funcionality.

I have problems with the injections bean and the @PostConstruct annotated method in the parent bean.

The following code is the only way I found it works.

@ManagedBean(name = "myBean")
@SessionScoped
public class BaseBean implements Serializable {
    @ManagedProperty(value = "#{serviceManagerController}")
    protected ServiceManagerController serviceManagerController;

     @PostConstruct
     public void init() {
       //do things
     }
}

And the child bean

public class ChildBean extends BaseBean {
    @PostConstruct
    public void init() {
       super.init();
    }
}

To override the "myBean" bean and force to the app to use the child bean when needed I have had to declare the child bean in faces-config.xml

<managed-bean>
    <managed-bean-name>myBean</managed-bean-name>
    <managed-bean-class>package.ChildBean</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
    <managed-property>
        <property-name>serviceManagerController</property-name>
        <property-class>package.ServiceManagerController</property-class>
        <value>#{serviceManagerController}</value>
    </managed-property>
</managed-bean>

That is the only way all works and I don´t understand some things.

  1. If I don´t declare the child bean in faces-config.xml then the beans container always uses the parent bean implementation though @ManagedBean is inherited.
  2. The injections in parent bean, like serviceManagerController are not performed unless I declare the <managed-property> in the faces-config.xml child bean declaration.
  3. The @PostConstruct method is not executed in the parent child, just the @PostConstruct child. Because of that I have to call super.init() in an empty @PostConstruct mehtod in the child bean

Why do I have to do this three steps to make injections and postConstruct in the parent work?

Of course, if in my app I don´t want to inherit BaseBean and want to use this bean in the facelets all work without problems.

Regards

1

There are 1 answers

3
BalusC On BEST ANSWER

The BaseBean is wrongly designed. Bean management annotations are not inherited. It does technically not make any sense to have multiple instances of different subclasses registered on the very same managed bean name/identifier. The BaseBean class must be abstract and not have any bean management annotations (so that neither you nor JSF can "accidentally" instantiate it). Put those bean management on ChildBean instead. Your faces-config.xml "fix" does basically exactly that.

public abstract class BaseBean implements Serializable {

    @ManagedProperty("#{serviceManagerController}")
    protected ServiceManagerController serviceManagerController;

    @PostConstruct
    public void init() {
        // ...
    }

    // ...
}
@ManagedBean("myBean")
@SessionScoped
public class ChildBean extends BaseBean {
    // ...
}

Managed property and post construct / pre destroy annotations are however inherited, provided that you didn't already override them in the subclass. So you don't need to redefine them.

See also: