Test EJB’s met JUnit: OpenEJB

 
15 april 2011

Wanneer je wel eens met EJB’s hebt gewerkt, weet je net als ik hoe moeilijk het is om deze te (unit) testen. De code op zich is gewoon Java-code, maar er wordt veel gebruik gemaakt van annotaties zoals @PersistenceContext en @Resource. Hiermee is het onder andere mogelijk om te communiceren met een database of om berichten te versturen naar een Message Driven Bean. Omdat de code is verweven met referenties naar deze resources, is het vrijwel onmogelijk om dit te testen met bijvoorbeeld JUnit. Er zal altijd een container nodig zijn die EJB’s ondersteund om dit voor elkaar te krijgen. En dit is alles behalve wenselijk!

OpenEJB is hier een goede oplossing voor. In plaats van een enorme container als JBoss AS heb je alleen een kleine EJB container die ook nog eens in de code gestart kan worden. Behalve dat deze erg klein is, is OpenEJB ook snel gestart en alleen gemaakt voor EJB’s. OpenEJB biedt een uitstekende ondersteuning voor JUnit en is daarom uitermate geschikt om te gebruiken bij een unit test. Daarnaast is het ook mogelijk om OpenEJB als EJB server te gebruiken of om deze te embedded in bijvoorbeeld Tomcat.

Inhoud

Vooraf

In deze blog leg ik uit hoe je EJB’s kunt unit testen met JUnit. Kennis van JUnit is daarom handig om te hebben. In tegenstelling tot wat je misschien mag denken, is kennis van EJB’s niet nodig. Het gaat in deze blog namelijk alleen maar over het testen van EJB’s. Voor een JUnit test is een EJB niets meer dan gewone Java code (kennis van Java is dus ook handig ;-)). Om de uitleg zo simpel mogelijk te maken, maak ik gebruik van de voorbeelden van OpenEJB zelf. Tot slot maak ik gebruik van Eclipse als ontwikkelomgeving.

Ik ga in deze blog niet in op de voorbeelden van OpenEJB zelf. Deze laat ik open om zelf mee te spelen.

OpenEJB als Local container

Download de volgende zip bestanden en pak deze uit:

Dit is alles wat we nodig hebben. Start Eclipse en ga naar File>New>Java Project. We maken in dit voorbeeld gebruik van een simpel voorbeeld genaamd “Simple Stateless”. Geef deze naam op als Project name (mag ook iets anders zijn). Vervolgens vink je de optie “Use default location” uit en klik je op “Browse”. Ga naar de map waarin je de Examples van OpenEJB hebt uitgepakt, klik op de map “simple-stateless” en klik op OK. Als het goed is heb je nu het volgende:

OpenEJBLocal1

Klik nu niet op Finish, maar op Next! Er moet namelijk nog een paar dingen gedaan worden en het is aanzienlijk makkelijker om dat nu gelijk te doen, dan om hier later op terug te komen. Selecteer nu src/main/resource en klik op “Use as Source Folder” (zie de volgende afbeelding).

OpenEJBLocal2

Deze map wordt op deze manier in de classpath gezet. Dit is nodig, omdat in deze resources map het bestand ejb-jar.xml staat die door OpenEJB gebruikt wordt. OpenEJB zoekt deze in de classpath.

Ga nu naar de tab Libraries. Er moeten namelijk nog een tweetal libraries toegevoegd worden. Klik op Add Library en kies voor JUnit. Standaard staat deze op JUnit 3. Je mag het op 4 zetten, maar dit is niet nodig. OpenEJB werkt met beide. Klik op Finish.

Tot slot moeten we OpenEJB zelf nog toevoegen als Library. Klik weer op Add Library, maar kies nu voor User Library. Klik vervolgens op User Libraries… en klik op New… Geef een naam op en klik op Ok, maar laat System library uitgevinkt!! De naam die ik gebruikt heb is, heel verrassend, “OpenEJB”.

Selecteer nu de Library die je net hebt toegevoegd en klik op Add JARs…

OpenEJBLocal3

Ga naar de locatie waar je OpenEJB hebt uitgepakt en ga naar de lib map. Selecteer alle JARs die daarin staan en klik op Open. Alle JARs worden nu toegevoegd en we zijn klaar. Klik op Ok, vink de nieuw aangemaakte Library aan en klik twee keer op Finish. Het project is nu aangemaakt en klaar voor gebruik.

Wanneer je nu het project runt als JUnit test case dan krijg je een groene balk. Alle tests gaan nu goed. Wanneer je iets anders krijgt, dan ben je waarschijnlijk iets vergeten. Probeer de fouten op te lossen of verwijder het project en probeer het nog een keer.

Zie ook http://vimeo.com/6149008

OpenEJB als Remote container

Download de volgende zip bestanden en pak deze uit:

Start Eclipse en ga naar Help>Install New Software. Het hangt er hier een beetje vanaf welke versie van Eclipse gebruikt, maar op de volgende site staat de Eclipse plugin van OpenEJB: http://people.apache.org/~jgallimore/update-site/. De installatie kan even duren.

Open de tab Servers, klik met je rechter muisknop en ga naar New>Server.

OpenEJBRemote1

Open de map Apache en selecteer OpenEJB x.x.x. Wanneer je op Next klikt krijg je een lijst met poort nummers. De default is goed genoeg voor deze blog, maar je hebt hier de mogelijkheid om het een en ander aan te passen. Wanneer je nog een keer op Next klikt, krijg je de mogelijkheid om een project toe te voegen. Op dit moment hebben we die nog niet, dus we klikken op Finish. Er is nu een remote container aangemaakt en klaar voor gebruik. Start de server en zie hoe snel die is!

Het aanmaken van een project is vrijwel hetzelfde als bij de Local container. Ga naar File>New>EJB Project. In dit voorbeeld gebruik ik een EJB Project. Dit is het simpelste voorbeeld. Geef een naam en locatie op (van bijvoorbeeld Simple Stateless of Simple Statefull wanneer je iets anders wilt proberen). De Target runtime staat als het goed is op OpenEJB x.x.x. Als dit niet het geval is, verander het dan zodat het er wel staat. Klik vervolgens weer op Next. Wijzig de naam van de folder ejbModule in src/main/java. Klik op Finish.

Omdat we dit keer andere opties hebben gehad moeten we nog het een en ander wijzigen. Klik met je rechter muisknop op het net aangemaakte project en ga naar Build Path>Configure Build Path… Voeg de JUnit Library weer toe aan je project en ga vervolgens naar Source>Add Folder. Vink hier de volgende twee mappen aan: src>main>resources en src>test>java.

OpenEJBRemote2

Het project is nu klaar voor gebruik. Zet de server aan en run de test (voeg eerst het project toe aan de server en run de test als een JUnit test case). Wanneer de server uit staat krijg je een error. Het is ook mogelijk om de server in de debug mode te starten.

Zie ook http://vimeo.com/7393498.

JUnit

De JUnit test case voor OpenEJB verschilt niet veel van de normale JUnit test case. Opvallend is dat er geen @Test boven de methodes hoeft komen te staan. Wanneer je kijkt naar de voorbeelden van OpenEJB zie je dat er een setUp() methode is en een InitialContext veld. In de setUp() methode wordt de container gestart (dit gebeurd 1x). Een belangrijk regel is de volgende:

properties.setProperty( Context.INITIAL_CONTEXT_FACTORTY, “org.apache.openejb.client.LocalInitialContextFactory” );

Dit is voor de Local container (LocalInitialContextFactory). Logischerwijs moet er voor de Remote container RemoteInitialContextFactory staan. Waar de Local container wel een remote interface kan aanroepen, kan de remote container geen local interface aanroepen! Zorg daarom dat in het voorbeeld bij de Remote container de methode met de Local aanroep wordt uitgecommentarieerd.

Voor de Remote container is de volgende regel nodig:

properties.setProperty(Context.PROVIDER_URL, “ejbd://localhost:4201”);

4201 is de default poort nummer. Als je deze gewijzigd hebt, moet je dat hier ook goed doen. Uiteraard is localhost hier de locatie van de server.

Het laatste waar ik het over zal hebben is de koppeling met een database. Binnen EJB, en dan met name de Entities, is persistence erg handig. Het bestand persistence.xml is hiervoor te gebruiken, maar deze verwijst naar een datasource bestand (die dus op de server staat).

Hier onder staat een stukje uit persistence.xml.

<persistence-unit name=”puName”>
    <provider>
        org.hibernate.ejb.HibernatePersistence
    </provider>
    <jta-data-source>
        java:/datasourceName
    </jta-data-source>

    // Overige code is weggelaten
</persistence-unit>

De provider is normaal gesproken optioneel, maar in het geval van OpenEJB is het verplicht! Anders krijg je verschillende errors. Nu we dit voorbeeld hebben kunnen we kijken naar de JUnit test:

properties.put( Context.INITIAL_CONTEXT_FACTORTY, “org.apache.openejb.client.LocalInitialContextFactory” );
properties.setProperty( “datasourceName”, “new://Resource?type=DataSource” );
properties.setProperty( “datasourceName.JdbcDriver”, “org.h2.Driver” );
properties.setProperty( “datasourceName.JdbcUrl”, “jdbc:h2:mem:dbName” );

In het bovenstaande voorbeeld maak ik gebruik van een H2 embedded database. Deze database wordt “in memory” gebruikt en blijft open staan gedurende de gehele JUnit test. LET OP: hij blijft open staan, dus wat je in test 1 erin zet, is bij test 2 ook te benaderen! De database is niet per test verschillend. Het is wel mogelijk om dit in de tearDown() methode te regelen door bijvoorbeeld de gehele database te legen.

Andere properties die in te stellen zijn, zijn onder andere .UserName en .Password. Let hierbij goed op hoofdletters!

Zoals ik vooraf al heb aangegeven, ga ik niet in op de voorbeelden van OpenEJB. Het beste is om er zelf eens mee te spelen en om ook andere voorbeelden te proberen.

Conclusie

OpenEJB is een zeer krachtige EJB container die snel toe te passen is. Er zijn veel voorbeelden van te vinden op de site van OpenEJB, die ook nog eens eenvoudig te begrijpen zijn. Al met al een fijne container om mee te testen!


Werken met ?
Kijk dan bij onze mogelijkheden voor starters en/of ervaren IT'ers.


Categorieën: Development, Java (EE), Open Source

Tags: , , , ,