1

I am new to EJB technology and I am currently reading the Oracle Guide trying to put into practice what I read. I have created to this effect a simple JSF application in Eclipse with JBoss application Server, using a Managed Bean as backing Bean. I want to initialize the data in the Managed Bean by the aid of a Singleton Bean, just to feel how Dependency Injection works. I follow the relevant instructions, but I cannot manage to initialize the Singleton Bean. The application throws a NPE in the constructor of Hello Managed Bean. I anticipate that my code probably lacks something but I cannot find out it. Where is the defect in the following Bean classes? :

@Startup
@Singleton
public class LaunchBean {

private List<String> custs;

public List<String> getCusts() {
    return custs;
}

public void setCusts(List<String> emps) {
    this.custs = emps;
}

@PostConstruct
void init() {       //in the guide the () after init is missed, but the code does not compile when omitting it
    custs = new ArrayList<String>();
    custs.add("Cust1");
    custs.add("Cust3");
    custs.add("Cust2");
    custs.add("Cust4"); 
}

}  


@ManagedBean
@SessionScoped
public class Hello implements Serializable{
@EJB
private LaunchBean dBean;


private static final long serialVersionUID = 1L;
private List<String> customers;
private String customersSelect;

public Hello(){
    customers = dBean.getCusts();
}

public List<String> getCustomers() {
    return customers;
}

public String getCustomersSelect() {
    return customersSelect;
}

public void setCustomersSelect(String customersSelect) {
    this.customersSelect = customersSelect;
}

}
arjacsoh
  • 8,932
  • 28
  • 106
  • 166

2 Answers2

4

You can inject EJBs using the @EJB annotation only into other EJBs. The Hello bean is not an EJB. Neither the @ManagedBean nor the @SessionScoped annotations make it one. In order to make it one, you can, for example, add a @Stateless or a @Stateful annotation to it.

Alternatively, you could use CDI to inject an EJB into a non-EJB, using the @Inject annotation. Be advised however that you will not be able to take advantage of some EJB features with an EJB bean that is injected via CDI.

EDIT I have just noticed another issue with the code. It is not only the injection that is wrong. There will always be an NPE in the constructor of the Hello bean if you try to access your injected members there. The members are injected after the construction of the object and are thus not available to the constructor. To work with the injected members as soon as they are injected, use a method, annotated with @PostConstruct.

EDIT 2 I have done a bit of SO digging and it seems like EJB injection indeed works for ManagedBeans. So while you cannot inject EJBs into a POJO with the EJB annotation, ManagedBeans are not to be considered POJOs in this case :). I am sorry for the inconvenience.

Community
  • 1
  • 1
kostja
  • 60,521
  • 48
  • 179
  • 224
  • if I add the annotation @Stateless or Stateful however, is it Ok to use it as backing Bean to a JSF file? What can I use in general as backing Bean to JSF? – arjacsoh Mar 06 '13 at 10:14
  • @arjacsoh Sure, an EJB can be used as a backing bean without any issues. This is not always possible, because the JSF frontend often runs on a servlet container like Tomcat without EJB support. But if your frontend runs on a Java EE application server - go for it. – kostja Mar 06 '13 at 10:29
  • I have tried it (change to Stateless), but it does not work properly. It presents the ListBox empty, without data. After clicking the button to remove to the next page it throws error: ="#{hello.customersSelect}": Target Unreachable, identifier 'hello' resolved to null. – arjacsoh Mar 06 '13 at 10:39
  • @arjacsoh I am using `Stateful` EJBs as controllers myself, so this does work and EL expressions are resolved peroperly. Try changing the annotation to `Stateful`, perhaps I am wrong about `Stateless`. Your bean does not look stateless BTW - it has at least two fields that can be set from the outside and change the state. So it would not be correct to make it a stateless EJB. – kostja Mar 06 '13 at 10:54
  • @arjacsoh - did you downvote the answer because of the EL resolution issue? I find it unnecessary. Even if it was my fault, why not ask first? – kostja Mar 06 '13 at 11:07
  • @kostja I down voted your answer, because you can inject EJB from inside a manged bean, same as you can from a Servlet – greenkode Mar 06 '13 at 11:12
  • @arjacsoh please see my answer, you don't have to make your ManagedBean an EJB. – greenkode Mar 06 '13 at 11:13
  • @arjacsoh - I see, Umoh considers the answer to be wrong for some reason. See [this question](http://stackoverflow.com/questions/2021370/ejb-3-1-ejb-injection-into-pojo) and decide for yourself :) – kostja Mar 06 '13 at 11:24
  • @kostja - I noticed your reference to this (similar) question, but I am still confused. I have just tried to inject the LaunchBean within the Hello Bean using the @ EJB annotation and it works.. rather fine. Is it not an evidence that the injection is fulfilled? – arjacsoh Mar 06 '13 at 11:31
  • @arjacsoh it seems that there are some differences in EJB 3.1. I can't comment on that because I don't have enough information. you can do yourself a favour and do some more research. in the meantime, mark the question as answered. Thanks. i'm out. – greenkode Mar 06 '13 at 11:38
  • @arjacsoh - I may be wrong after all. I did not read know the specs on this issue, so it is still a bit of a mistery. Please see my second edit. – kostja Mar 06 '13 at 11:45
2

@kostja, A managed bean sits on top of the Servlet context, so you CAN inject EJBs from inside a Managed Bean. @arjacsoh. you need to include the code customers = dBean.getCusts(); inside the @PostConstruct Method. You can't do it inside the constructor because the managedbean has not been created yet. the @PostConstruct method happens immediately after the Bean is created.

greenkode
  • 4,001
  • 1
  • 26
  • 29
  • As of EJB 3.1 you cannot inject EJBs using the `EJB` annotation [see this question](http://stackoverflow.com/questions/2021370/ejb-3-1-ejb-injection-into-pojo). You can however inject them with CDI or JNDI. As for the `@PostConstruct` - I have noticed the issue too late, but I have already posted the advice before you have posted the answer, see my edit. – kostja Mar 06 '13 at 11:13
  • @Umoh - I didn't have the intention to make the ManagedBean EJB but I am still curious if it possible. Can JSF use an EJB as backing Bean? – arjacsoh Mar 06 '13 at 11:26
  • @kostja. I looked at that question, it seems more like a discussion than anything conclusive. I've upvoted your answer for picking up the `@PostConstruct`. I was still editing my answer, so I didn't see it. I'm still not convinced about the Injection thing though. I'll do more research into it. – greenkode Mar 06 '13 at 11:29
  • @arjacsoh I've never done that, so I'm not sure if that is possible. but look at this interesting article http://www.adam-bien.com/roller/abien/entry/ejb_3_1_killed_the – greenkode Mar 06 '13 at 11:33
  • @Umoh +1 and you may be right after all :) I have just found [this question](http://stackoverflow.com/questions/8626291/jsf-managed-bean-ejb-injection) where it seems to work. I'm a bit confused now. – kostja Mar 06 '13 at 11:47