Question

I use Arquillian to test an stateless session bean that has an explicit local and remote interface. But in the test Arquillian does not "inject" anything in a field that has the type of the local interface, but it works for the remote interface.

@Stateless
public class TestServiceImpl implements TestServiceLocal, TestServiceRemote {
    public String greet() {
        return "hallo";
    }
}

The remote interface:

@Remote
public interface TestServiceRemote {
    public String greet();
}

The locale interface:

@Local
public interface TestServiceLocal {
    public String greet();
}

And this is the test:

@RunWith(Arquillian.class)
public class GenericEntityDaoEjbIntegrationTest {

    @Deployment
    public static JavaArchive createTestArchive()
                  throws UnsupportedEncodingException {
        return ShrinkWrap.create(JavaArchive.class, "test.jar")
                .addClasses(
                        TestServiceLocal.class,
                        TestServiceRemote.class,
                        TestServiceImpl.class);
    }

    @EJB
    private TestServiceLocal testServiceLocal;

    @EJB
    private TestServiceRemote testServiceRemote;

    //Will Fail
    @Test
    public void testTestServiceLocal() {
        assertNotNull(this.testServiceLocal);
    }

    //Success    
    @Test
    public void testTestServiceRemote() {
        assertNotNull(this.testServiceRemote);
    }    
}

I am using arquillian-glassfish-embedded 1.0.0.CR2, glassfish-embedded-all 3.1 and arquillian-junit-container 1.0.0.CR5 The relevant part of my pom is:

    <!-- arquillian test -->
    <dependency>
        <groupId>org.jboss.arquillian.junit</groupId>
        <artifactId>arquillian-junit-container</artifactId>
        <version>1.0.0.CR5</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.jboss.arquillian.container</groupId>
        <artifactId>arquillian-container-spi</artifactId>
        <version>1.0.0.CR5</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.jboss.arquillian.container</groupId>
        <artifactId>arquillian-glassfish-embedded-3.1</artifactId>
        <version>1.0.0.CR2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.glassfish.extras</groupId>
        <artifactId>glassfish-embedded-all</artifactId>
        <version>3.1</version>
        <scope>test</scope>
    </dependency>

This is the relevant part of the log file (it does not contain any exception):

10.04.2012 15:38:16 com.sun.ejb.containers.BaseContainer initializeHome
INFO: Portable JNDI names for EJB TestServiceImpl : [java:global/test/TestServiceImpl!de.test.service.TestServiceRemote, java:global/test/TestServiceImpl!de.test.service.TestServiceLocal]
10.04.2012 15:38:16 com.sun.ejb.containers.BaseContainer initializeHome
INFO: Glassfish-specific (Non-portable) JNDI names for EJB TestServiceImpl : [de.test.service.TestServiceRemote, de.test.service.TestServiceRemote#de.test.service.TestServiceRemote]
10.04.2012 15:38:16 com.sun.enterprise.web.WebApplication start
INFO: WEB0671: Loading application [test] at [/test]
10.04.2012 15:38:16 org.glassfish.deployment.admin.DeployCommand execute
INFO: test was successfully deployed in 11.844 milliseconds.

What is my mistake? What do I need to change the get an instance injected for locale interface too?

Was it helpful?

Solution

You could use one of the following:

  • Add a beans.xml file to the deployment:

    return ShrinkWrap.create(JavaArchive.class, "test.jar")
                    .addClasses(
                            TestServiceLocal.class,
                            TestServiceRemote.class,
                            TestServiceImpl.class)
                    .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
    

    This enables the CDITestEnricher of Arquillian, which is far more capable than the EJBTestEnricher. It can handle @Inject annotations (obviously), but also @Resource and @EJB annotations as well (see the section on Resources injection in the CDI spec). The container then treats both the @EJB annotated fields in your test class instance as injection points and injects the dependencies.

  • Specify the mappedName property for the @EJB annotation for the field with the portable JNDI name of the deployed bean. In your case, it will look something like:

    @EJB(mappedName="java:global/test/TestServiceImpl!com.acme.TestServiceLocal")
    private TestServiceLocal testServiceLocal;
    

    You'll need to ensure that the portable JNDI name is the same as that the one generated for your deployment. I've merely specified the one that was generated for my "com.acme.TestServiceLocal" interface.

OTHER TIPS

In addition to the answers you must also ensure you use the correct @Deployment setting is correct. To inject locally you must ensure you have @Deployment(testable=true) (note that this is the default).

From Aquillian docs:

In-container mode: @Deployment(testable = true)

As we mentioned above, we need to repackage your @Deployment, adding some Arquillian support classes, to run in-container. This gives us the ability to communicate with the test, enrich the test and run the test remotely. In this mode, the test executes in the remote container; Arquillian uses this mode by default.

See the Complete Protocol Reference for an overview of the expected output of the packaging process when you provide a @Deployment.

Client mode: @Deployment(testable = false)

Now this mode is the easy part. As opposed to in-container mode which repackages and overrides the test execution, the as-client mode does as little as possible. It does not repackage your @Deployment nor does it forward the test execution to a remote server. Your test case is running in your JVM as expected and you're free to test the container from the outside, as your clients see it. The only thing Arquillian does is to control the lifecycle of your @Deployment.

Here is an example calling a Servlet using the as client mode.

This does not help the OP (they had the correct settings) but I hope it helps those arriving from Google, as I did.

Try to change TestServiceImpl->TestServiceBean it looks that embedded glassfish have specific requirements to bean name

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top