How to filter (substitute) env-entry values in ebj-jar.xml for unit tests with embedded enterprise bean container (GlassFish)?

StackOverflow https://stackoverflow.com/questions/17301960

Question

I need several profiles for deployment. In the Maven POM I have defined a profile "dev" and a property "theHost" (as localhost):

<profiles>
  <profile>
    <id>dev</id>
    <activation>
      <activeByDefault>true</activeByDefault> <!-- use dev profile by default -->
    </activation>
    <build>
    </build>
    <properties>
      <theHost>localhost</theHost>
    </properties>
  </profile>
...

I have activated filterDeploymentDescriptor on the maven-ejb-plugin in order to tell it to filter (substitute) values in ejb-jar.xml:

<plugins>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-ejb-plugin</artifactId>
    <version>2.3</version>
    <configuration>
      <ejbVersion>3.1</ejbVersion>
-->   <filterDeploymentDescriptor>true</filterDeploymentDescriptor>
    </configuration>
</plugin

Finally, in ejb-jar.xml I refer to ${theHost} to obtain the desired profile-specific value for the @Resource attribute "host":

<session>
  <ejb-name>MongoDao</ejb-name>
  <ejb-class>com.coolcorp.MongoDao</ejb-class>
  <session-type>Stateless</session-type>
  <env-entry>
    <env-entry-name>host</env-entry-name>
    <env-entry-type>java.lang.String</env-entry-type>
    <env-entry-value>${theHost}</env-entry-value>
  </env-entry>
...

This all works great with a regular Maven build. But when I run an EJB unit test using the Embedded Enterprise Bean Container of GlassFish [EJBContainer.createEJBContainer()], the maven-ejb-plugin seems to ignore filterDeploymentDescriptor=true. The EJB sees "${theHost}" instead of "localhost" although I run maven with the same "dev" profile.

mvn.bat -Pdev test

Does anybody have an idea why the substitution does not work when running a unit test? Is there something more I have to define especially for the unit test so that filtering of ejb-jar.xml occurs? Or a better approach to unit testing EJBs if different profiles exist?

Was it helpful?

Solution

Ideally, you would be able to specify an external "binding" for the env-entry. I know that's possible to do with WebSphere Application Server (via EnvEntry.Value properties), but I don't know if it's possible with Glassfish.

As a workaround, you could declare the env-entry for injection, and then check in PostConstruct whether any value was injected by the container (i.e., don't specify env-entry-value until you're deploying into the server). If you're using JNDI only, you can do the same thing with try/catch(NameNotFoundException).

@Resource(name="host")
private String host;

@PostConstruct
public void postConstruct() {
  if (host == null) {
    // Not configured at deployment time.
    host = System.getProperty("test.host");
  }
}

OTHER TIPS

Workaround based on bkail's suggestion: Set a system property only for unit tests and discover it in postConstruct:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.14.1</version>
            <configuration>
                <skip>false</skip>
                <argLine>-Xmx1g -XX:MaxPermSize=128m</argLine>
                <reuseForks>false</reuseForks> <!-- with reuse the EJB timer service would fail -->
                <systemPropertyVariables>
                    <is.unittest>true</is.unittest>
                </systemPropertyVariables>
            </configuration>
        </plugin>

And then in the Java method annotated with @PostConstruct:

    // Override values that were not substituted in ejb-jar.xml
    if (Boolean.getBoolean("is.unittest")) {
        host = "localhost";
        port = "27017";
        authenticationRequired = false;
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top