Tuesday, October 28, 2008

naive EJB testing

EJB can't and shouldn't be tested as POJO's. It would contradict with the simple concept of 'container managed bean'. Plus, if you use injection for PersistanceContext, UserTransaction, SessionContext etc, no container will be there to inject values and you will be happy if you only see 'Null Pointer Exceptions'.

Still, for simplicity, you can test EJB outside the container, provided that you manually call methods that are marked as Life-Cycle Callbacks (@PostConstruct, @PrePassivate etc.). Also, I will describe a way for injecting a PersistenceContext outside of the container.

First of all, you normally declare an EntityManager something like this:

private EntityManager entityManager;
private EntityMangerFactory emf;

Now, to be able to set a value to it when it is running outside the contianer, I suggest providing a setter for it. In the test class, you first instantiate an EntityManager like this:

EntityManagerFactory emf = javax.persistence.Persistence.createEntityManagerFactory("testPU");

The testPU referenced has to have a RESOURCE_LOCAL transaction type, that is a non-jta datasource. Also, the datasource has to be reachable from the project (e.g. not be defined in the application server config files). The short solution would be to declare it using the element, by provind the url, username, password, driver. TopLink configuration would look something like this:

<property name="toplink.jdbc.driver" value="org.postgresql.Driver"/>
<property name="toplink.jdbc.url" value="jdbc:postgresql://localhost:5432/huddi"/>
<property name="toplink.jdbc.password" value="super"/>
<property name="toplink.jdbc.user" value="postgres"/>