PEAT Online Course -
Test-Driven Development
using Kotlin

£79.99
  • Theory 'n' practice
  • Test-driven method
  • Acceptance criteria
  • Learn to code mastery
  • Ace that job interview
  • Free updates
AVAILABLE NOW
VIMEO ON-DEMAND

Upgrade DeltaSpike, Gradle and CDI Container with Test Module

16 February 2016 Comments off

5 minutes

1072

I am puzzled by the Java EE 7 Developer Handbook that I wrote about two years ago. Well I researched it in 2013 and published it. I was looking at the code for Chapter 2, which has an old example of Apache DeltaSpike, JBoss Weld and Gradle. I want to upgrade it to work with the latest stable releases circa 2016.

So where am I? I am stuck for once, because I received this exception whilst executing gradle build --stacktracer.

 

Feb 16, 2016 2:50:34 PM org.apache.deltaspike.testcontrol.api.junit.CdiTestSuiteRunner$LogRunListener testFailure
INFO: [failed] je7hb.standalone.CreditProcessorTest#null message: WELD-ENV-002000: Weld SE container STATIC_INSTANCE is already running!

java.lang.IllegalStateException: WELD-ENV-002000: Weld SE container STATIC_INSTANCE is already running!

	at org.jboss.weld.environment.se.WeldContainer.initialize(WeldContainer.java:138)
	at org.jboss.weld.environment.se.Weld.initialize(Weld.java:562)
	at org.apache.deltaspike.cdise.weld.WeldContainerControl.boot(WeldContainerControl.java:68)
	at org.apache.deltaspike.cdise.weld.WeldContainerControl.boot(WeldContainerControl.java:76)
	at org.apache.deltaspike.testcontrol.api.junit.CdiTestRunner$ContainerAwareTestContext.applyBeforeClassConfig(CdiTestRunner.java:463)
	at org.apache.deltaspike.testcontrol.api.junit.CdiTestRunner$BeforeClassStatement.evaluate(CdiTestRunner.java:366)
	at org.apache.deltaspike.testcontrol.api.junit.CdiTestRunner$AfterClassStatement.evaluate(CdiTestRunner.java:393)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.apache.deltaspike.testcontrol.api.junit.CdiTestRunner.run(CdiTestRunner.java:142)
	at org.junit.runners.Suite.runChild(Suite.java:128)
	at org.junit.runners.Suite.runChild(Suite.java:27)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

 

They say always run on the command line, and so I did. I also verified this also issue inside IDEA 15.0.3.

The unit test code is actually the simplest in the book:

 

package je7hb.standalone;

import org.apache.deltaspike.testcontrol.api.junit.CdiTestRunner;
import org.junit.Test;
import org.junit.runner.RunWith;

import javax.inject.Inject;

import static org.junit.Assert.*;

@RunWith(CdiTestRunner.class)
public class CreditProcessorTest {
    private @Inject @Economy CreditProcessor agent;

    @Test
    public void shouldInjectStreetCredit() {
        assertNotNull(agent);
        agent.check("12354678");
        System.out.printf("agent=%s\n", agent );
    }
}

 

I threw out my older AbstractCdiContainerTest implementation, because Delta Spike has replaced it with a new JUnit 4 Runner implementation. I upgraded to JBoss Weld 2.3.2 against Delta Spike 1.5.2.

At the moment, I am refactoring the Gradle build into a proper MULTI-MODULE build for all the students. There is something strange going on? The codebase is help on GitHub.

Extract of the build file is:

archivesBaseName = 'ch02-cdi-standalone'

dependencies {    
    compile     "javax:javaee-api:${javaeeVersion}"

    compile     "org.slf4j:slf4j-simple:${slf4jVersion}"
    compile     "org.apache.deltaspike.cdictrl:deltaspike-cdictrl-api:${deltaspikeVersion}"
    compile     "org.apache.deltaspike.cdictrl:deltaspike-cdictrl-weld:${deltaspikeVersion}"

    compile     "org.jboss.weld.se:weld-se-core:${weldSEVersion}"
    compile     "org.apache.deltaspike.modules:deltaspike-test-control-module-api:${deltaspikeVersion}"

    testCompile     "org.apache.deltaspike.modules:deltaspike-test-control-module-impl:${deltaspikeVersion}"
}

test {
    testLogging.showStandardStreams = true

    // set heap size for the test JVM(s)
    minHeapSize = "128m"
    maxHeapSize = "768m"

    // Ensure that the working directory for the test is the same as the project directory in order to run the Spike Delta container tests
    // *PP* 11/02/2016
    workingDir = project.projectDir
}

The dependencies are now set in the root Gradle project. Here is the extract:

allprojects {
    apply plugin: 'java'
    apply plugin: 'maven'
    apply plugin: 'eclipse'
    apply plugin: 'idea'

    // Define equivalent Maven GAV coordinates.
    group = 'uk.co.xenonique.javaee7handbook'
    version = '1.0-SNAPSHOT'

    ext {
        arquillianVersion                   = "1.1.11.Final"
        arquillianJunitVersion              = "1.1.11.Final"
        arquillianPersistenceVersion        = "1.0.0.Alpha6"
        arquillianGlassfishEmbeddedVersion  = "1.0.0.Final-SNAPSHOT"
        arquillianGlassfishManagedVersion   = "1.0.0.CR4"
        arquillianGlassfishRemoteVersion    = "1.0.0.CR4"
        deltaspikeVersion                   = "1.5.2"
        glassfishVersion                    = "4.1"
        hamcrestVersion                     = "1.3"
        javaeeVersion                       = "7.0"
        jodaTimeVersion                     = "2.2"
        junitVersion                        = "4.12"
        ozarkVersion                        = "1.0.0-m01"
        mockitoVersion                      = "1.10.19"
        shrinkWrapVersion                   = "1.0.1"

        //'org.slf4j:slf4j-api:1.7.14'
        slf4jVersion                        = "1.7.14"
        weldEEEmbeddedVersion               = "1.0.0.CR3" 
        weldSEVersion                       = "2.3.2.Final"
    }

    repositories {
        mavenLocal()
        mavenCentral()
        maven {
            url 'https://maven.java.net/content/groups/promoted'
        }
        maven {
            url 'https://repository.jboss.org/nexus/content/groups/public'
        }        
    }

    // Java version compatibility to use when compiling Java source 
    sourceCompatibility = '1.8'
    // Java version to generate classes
    targetCompatibility = '1.8'
...
}

This failure is a complete mystery, why code that worked in 2013 and no longer executes in 2016. However, I am sure that it will be revealed.

UPDATE

I was chatting on the DeltaSpike IRC and @os890 informed me about a trick that works around the issue.

You can also find a description in the Java EE 7 Tutorial about the @Priority annotation and Alternatives.


“The alternatives that you specify in the beans.xml file apply only to classes in the same archive. Use the @Priority annotation to specify alternatives globally for an application that consists of multiple modules …”

And also


“The alternative with higher priority value is selected if several alternative beans that implement the same interface are annotated with @Priority. You do not need to specify the alternative in the beans.xml file when you use the @Priority annotation.”

To work around the issue, I use the @Priority and Gradle builds everything fine.

@Alternative
@Priority(Interceptor.Priority.APPLICATION+100)
public class XenoniqueFoodProcessor implements FoodProcessor {
    @Override
    public String sayBrand() {
        return "Xenonique";
    }
}

I added the above annotation to the Weld specific project, then I executed the test successfully.

I do not believe DeltaSpike is broken and so the question remains, is the Java EE 7 reference implementation of CDI 1.1 specification correct or incorrect with respect with Alternative configured in a beans.xml?

I also created source code to exercise Open Web Beans container as a parallel sub-project, see standalone-owb in Github. Indeed removed the @Priority annotation from the XenoniqueFoodProcessor bean and Gradle builds successfully! Ah ha this is an issue with JBoss Weld 1.5.3! It is not respecting @Alternatives as CDI 1.0 specification according to my examples.

 

+PP+

 

Hey all! Thanks for visiting. I provide fringe benefits to interested readers: checkout consultancy, training or mentorship Please make enquiries by email or
call +44 (0)7397 067 658.

Due to the Off-Payroll Working plan for the UK government, I am enforcing stricter measures on contracts. All potential public sector GOV.UK contracts engagements must be approved by QDOS and/or SJD Accounting. Please enquire for further information.