Saturday, March 27, 2010

Integration Testing JPA and EJB 3 with Arquillian and GlassFish Embedded

By default, the Arquillian container for GlassFish embedded creates a temporary instance every time you run the Arquillian test. So how do we go about setting up JNDI datasources for GlassFish embedded? Well, for now you could make a tiny change to GlassfishEmbeddedContainer.java (in arquillian-glassfish-embedded-30 maven artifact) so it'll setup your embedded instance at a permanent location. Then, you can setup all the datasources you want in the instance's domain.xml file.

Make the changes to GlassfishEmbeddedContainer.java and rebuild the jars to your local maven repository

public GlassFishEmbeddedContainer() {
                final Server.Builder builder = new Server.Builder(GlassFishEmbeddedContainer.class.getName());

                final EmbeddedFileSystem.Builder embeddedFsBuilder = new EmbeddedFileSystem.Builder();

                // final EmbeddedFileSystem embeddedFs = embeddedFsBuilder.build();
                final EmbeddedFileSystem embeddedFs = embeddedFsBuilder.
                    instanceRoot(new File("src/test/glassfish")). // set the instance root
                build();
                builder.embeddedFileSystem(embeddedFs);
                server = builder.build();

                server.addContainer(ContainerBuilder.Type.all);
            }

        

@Override
    public void start() throws LifecycleException {
        try {
            for (EmbeddedContainer contianer : server.getContainers()) {
                // do not bind the embedded glassfish to any port
                // instead, the instance will use the port specified in the domain.xml file
                //contianer.bind(server.createPort(port), "http");
                contianer.start();
            }
        } catch (Exception e) {
            throw new LifecycleException("Could not start container", e);
        }
    }

Here's a screenshot of directory and files generated by the Glassfish embedded when you run the test. However, you have to create your own domain.xml and place it under the config folder. You can copy this file from your GlassFish v3 installation and modify it accordingly.


Sample datasource setup in domain.xml


    
    
        
        
        
        
        
    


The test

@RunWith(Arquillian.class)
public class TicketFacadeTest {

    @EJB
    private TicketFacade ticketFacade;

    @Deployment
    public static JavaArchive createDeployment() {
        return Archives.create("test.jar", JavaArchive.class).
                addClasses(
                Ticket.class, // be sure to include your JPA entities, else Glassfish embedded will not pick it up
                TicketFacade.class,
                TicketFacadeBean.class).
                addManifestResource(new File("src/main/resources/META-INF/persistence.xml"));
    }

    @Test
    public void shouldBeAbleToInjectEJB() throws Exception {
        Ticket ticket = new Ticket();
        ticket.setDescription("This is a new ticket.");
        ticket.setPriority(Priority.SEVERE);
        ticket.setStatus(Status.NEW);
        ticketFacade.create(ticket);

        List tickets = ticketFacade.findAll();
        Assert.assertEquals(1, tickets.size());

    }
}


Download the project.