9

I have a BaseBean with a @PostConstruct, and a bean extending it on which i would like to call another @PostConstruct. I have read several places where it said it was possible, however, it seems the @postConstruct on the extending class is called first (if the second is called at all). I then get a NPE on "context" because I'm assuming the super bean's PostConstruct has already been called.

Is this do-able? If so what am I doing wrong?

Base bean:

@ManagedBean
@RequestScoped
public class BaseBean {
@ManagedProperty(value = "#{contextBean}")
  private ContextBean contextBean;
  Context context;
@PostConstruct
public void setupContext() {
    context = getContextBean().getContext();
}

Extending bean:

@ManagedBean
@RequestScoped
public class SmartBoxSearchBean extends BaseBean {
@PostConstruct
public void setUp() {
    jsonHelper = context.get(SmartBoxJsonHelper.class);
}

Thanks, Yotam.

Yotam Soen
  • 305
  • 1
  • 3
  • 6
  • @YotamSeon I have a very similar problem [here](http://stackoverflow.com/q/29787068/330457). Did you concluded that the accepted suggestion is the only solution you could? – Jin Kwon Apr 22 '15 at 03:42

1 Answers1

10

The @PostConstruct of the superclass of a backing bean is not called at all when the managed bean is constructed. It's only called when a completely separate managed bean instance of that superclass is been constructed by e.g. using #{baseBean} in EL in your case. You effectively end up with two entirely separate instances #{baseBean} and #{smartBoxSearchBean} wherein the class' own @PostConstruct method is invoked independently on the managed bean class itself.

This design is somewhat strange. A superclass of a backing bean is normally not to be used as a managed bean at all.

I suggest to revise your approach as follows:

public abstract class BaseBean {

    @ManagedProperty("#{contextBean}")
    private ContextBean contextBean;

    public Context getContext() {
        return contextBean.getContext();
    }

}

and

@ManagedBean
@RequestScoped
public class SmartBoxSearchBean extends BaseBean {

    @PostConstruct
    public void setUp() {
        jsonHelper = getContext().get(SmartBoxJsonHelper.class);
    }

}

Or maybe this, if you don't need ContextBean for other purposes at all

public abstract class BaseBean {

    @ManagedProperty("#{contextBean.context}")
    private Context context;

    public Context getContext() {
        return context;
    }

}

Note that @ManagedProperty works just fine when declared in a superclass this way.


Update: depending on the functional requirements, you can also decouple the beans and just inject the #{baseBean} in the {smartBoxSearchBean}.

@ManagedBean
@RequestScoped
public class BaseBean {

    @ManagedProperty("#{contextBean}")
    private ContextBean contextBean;
    private Context context;

    @PostConstruct
    public void init() {
        context = contextBean.getContext();
    }

}

and

@ManagedBean
@RequestScoped
public class SmartBoxSearchBean {

    @ManagedProperty("#{baseBean}")
    private BaseBean baseBean; 

    @PostConstruct
    public void setUp() {
        jsonHelper = baseBean.getContext().get(SmartBoxJsonHelper.class);
    }

}
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    Thanks BalusC for the super quick answer. Your solution would work, except for one issue - In the BaseBean's PostConstruct i also initialize other members, that the extending beans use... – Yotam Soen Jun 26 '12 at 19:43