GF 4.1 Junit und EJB

Hi,

ich habe zwei Maven Module. In einem ist das Model (die Hibernate Entity Klassen) im anderen ist das WebProjekt (mit Jersey und JavaEE).

Ich möchte nun meine Entity Klassen mit EJB und Junit testen. Ich orientiere mich dabei an: jpa - Testing an EJB with JUnit - Stack Overflow

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package code.elephant.model;

import code.elephant.facade.CourseFacade; //aus maven modul model klasse
import code.elephant.facade.CourseFacadeLocal; //aus maven modul model klasse
import javax.ejb.embeddable.EJBContainer;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import junit.framework.TestCase;

import org.junit.AfterClass;
import static org.junit.Assert.assertNotNull;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 *
 * @author martin
 */
public class CourseUnitTest extends TestCase {

    private Context ctx;
    private EJBContainer ejbContainer;

    @BeforeClass
    @Override
    public void setUp() {
        ejbContainer = EJBContainer.createEJBContainer();
        System.out.println("Opening the container");
        ctx = ejbContainer.getContext();
    }

    @AfterClass
    @Override
    public void tearDown() {
        ejbContainer.close();
        System.out.println("Closing the container");
    }

    @Test
    public void testFindAll() throws NamingException {

        CourseFacadeLocal converter = (CourseFacadeLocal) ctx.lookup("java:global/classes/CourseFacadeLocal");
        assertNotNull(converter);
        // success, it did all of the above!
    }
}

Im Stackoverflow Beitrag steht auch noch ich muss die Dependecy org.glassfish.main.extras hinzufügen.

Das habe ich auch gemacht pom.xml:

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>code.elephant</groupId>
        <artifactId>main</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <groupId>code.elephant</groupId>
    <artifactId>webapi</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>webapi Jersey Webapp</name>
    <properties>        
        <jersey.version>2.22.2</jersey.version>
        <glassfish.version>3.1.1</glassfish.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.glassfish.jersey</groupId>
                <artifactId>jersey-bom</artifactId>
                <version>${jersey.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.glassfish.jersey.containers</groupId>
                <artifactId>jersey-container-servlet</artifactId>
                <version>2.5.1</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-grizzly2-http</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.glassfish.jersey.bundles.repackaged</groupId>
                    <artifactId>jersey-guava</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.21</version>
        </dependency>

        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4.7</version>
        </dependency>

        <!-- uncomment this to get JSON support: -->
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-moxy</artifactId>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <!-- JWT -->
        <dependency>
            <groupId>org.bitbucket.b_c</groupId>
            <artifactId>jose4j</artifactId>
            <version>0.5.1</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.9</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>model</artifactId>
            <version>1.0-SNAPSHOT</version>
            <type>ejb</type>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>model</artifactId>
            <version>1.0-SNAPSHOT</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.glassfish.main.extras</groupId>
            <artifactId>glassfish-embedded-all</artifactId>
            <version>4.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>7.0</version>
            <type>jar</type>
        </dependency>
    </dependencies>

    <build>
        <finalName>webapi</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <inherited>true</inherited>
                <version>2.3</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>          
            </plugin>  
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <webXml>src/main/webapp/WEB-INF/web.xml</webXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.glassfish</groupId>
                <artifactId>maven-embedded-glassfish-plugin</artifactId>
                <version>${glassfish.version}</version>
                <dependencies>
                    <dependency>
                        <groupId>org.glassfish.jersey</groupId>
                        <artifactId>jersey-servlet</artifactId>
                        <version>${project.version}</version>
                    </dependency>
                    <dependency>
                        <groupId>javax.servlet</groupId>
                        <artifactId>javax.servlet-api</artifactId>
                        <version>3.0.1</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <goalPrefix>embedded-glassfish</goalPrefix>
                    <app>${user.home}\Documents\NetBeansProjects\elephant\main\main/target/${project.build.finalName}.war</app>
                    <autoDelete>true</autoDelete>
                    <port>8080</port><!--Simon: 8282, 8383 Admin 4949-->
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Ich erhalte aber immer im Junit in der Zeile ejbContainer = EJBContainer.createEJBContainer(); die Exception:

Running code.elephant.model.CourseUnitTest
Mai 27, 2016 2:31:38 PM org.glassfish.ejb.embedded.EJBContainerProviderImpl getValidFile
WARNING: EJB6008:Specified or calculated application server instance [C:\Users\martin\.m2\repository\org\glassfish\main\extras\glassfish-embedded-all\domains\domain1] does not exist.
Mai 27, 2016 2:31:38 PM org.glassfish.ejb.embedded.EJBContainerProviderImpl createContainer
INFO: [EJBContainerProviderImpl] Using runtime class: class com.sun.enterprise.glassfish.bootstrap.StaticGlassFishRuntime
Mai 27, 2016 2:31:40 PM org.glassfish.ejb.embedded.EJBContainerProviderImpl createEJBContainer
SEVERE: EJB6001:Caught exception instantiating EmbeddedContainer.
java.lang.NoSuchMethodError: org.glassfish.hk2.utilities.ClasspathDescriptorFileFinder.<init>(Ljava/lang/ClassLoader;Ljava/lang/String;)V

Hat jemand eine Idee wie ich das lösen kann? PS: Ich verwende Glassfish 4.1. Gibt es sonst noch eine gute Möglichkeit meine Models gegen die DB zu testen?

Hi,

ich habe ab und zu Arquillian im Einsatz. Ansonsten kann glaube ich auch https://github.com/guhilling/cdi-test Tests für EJB.

Die Frage ist halt, ob Du wirklich für solche Tests den Glassfish immer embedded starten möchtest (so habe ich das jetzt verstanden).

Hi,

danke für die Rückmeldung.

Wie muss ich meinen Junit Test bauen, damit ich keinen GF brauche?

Im Model Maven Projekt habe ich ja die persisentce.xml. Die sieht so aus:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="manager" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>java/jboss/datasources/MysqlDSElephant</jta-data-source>
    <class>code.elephant.model.Category</class>
    <class>code.elephant.model.Answer</class>
    <class>code.elephant.model.Course</class>
    <class>code.elephant.model.Language</class>
    <class>code.elephant.model.Question</class>
    <class>code.elephant.model.User</class>
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
    <properties>
      <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
      <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
    </properties>
  </persistence-unit>
</persistence>

Aber mit der jta-data-source habe ich ja wieder eine Abhänigkeit auf meinen GF oder?

Kann ich die persistence.xml im Model Projekt irgendwie so gestalten, dass ich dafür nicht die jta-data-source benötige?

Dann hätte ich nämlich einfach eine neue Instanz von meiner Facade Klasse erstellt und damit auf die DB zugegriffen.

Die sieht so aus:

@Stateless
public class CourseFacade extends AbstractFacade<Course> implements CourseFacadeLocal {
    @PersistenceContext(unitName = "manager")
    private EntityManager em;
    @Override
    protected EntityManager getEntityManager() {
        return em;
    }
    public CourseFacade() {
        super(Course.class);
    }
    
}

Und im Test hätte ich dann halt

CourseFacade courseFacade = CourseFacade ()
gemacht.

Eine Abhängigkeit hast Du zu JPA und CDI/EJB und nicht zum AppServer selbst. Du musst also ein Test-Framework verwenden, dass Dir am besten einen schnellen Server zur Verfügung stellt, der EJB und CDI unterstützt. Ich habe dazu halt häufiger Arquillian in Verwendung. Das ist allerdings mit einer größeren Einstiegshürde versehen. Hier kann man “schnell” etwas mit dem weld-se-container zusammen bauen.

Ansonsten würde ich Dir empfehlen, mal https://github.com/guhilling/cdi-test genauer zu betrachten. Vielleicht hilft Dir das weiter.