桜技録

🐈🐈🐈🐈🐘

CDI-UnitでJAX-RS 2.1 (Java EE 8)

まとめ

  • CDI-Unit 4.0.2 (執筆時点最新版) はJAX-RS実装としてRESTEasy 3.0.14に依存
  • RESTEasy 3.0.14はJAX-RS 2.0 (Java EE 7) の実装
  • よってJAX-RS 2.1 (Java EE 8) のサービスが動かせないことがある
  • RESTEasyを3.5.0以降に上げることで回避可能

検証

単にHTTP OKを返すだけのWebサービスをテストクラスから呼んでみる。

@RequestScoped
@Path("hoge")
public class HogeService {

    @POST
    @Path("new")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response add(@Valid Hoge hoge) {
        return Response.ok().build();
    }

}
@RunWith(CdiRunner)
@SupportJaxRs
class HogeServiceTest {

    @Inject
    private HogeService sut

    @Test
    @InRequestScope
    void new_hoge() {
        def request = newRequest()
        def response = sut.add(request)
        assertThat(response.status, is(Response.Status.OK.statusCode))
    }

}

何も考えずにCDI-Unitをdependenciesに含めてみる。

// ✗ NG
dependencies {
    providedCompile 'javax:javaee-web-api:8.0'
    testCompile 'org.jglue.cdi-unit:cdi-unit:4.0.2'
    testRuntime 'org.jboss.weld.se:weld-se-core:3.0.0.Final'
    testRuntime 'org.jboss.weld.module:weld-web:3.0.0.Final'
}

実行すると AbstractMethodError が出てしまう。

java.lang.AbstractMethodError: javax.ws.rs.core.Response$ResponseBuilder.status(ILjava/lang/String;)Ljavax/ws/rs/core/Response$ResponseBuilder;
    at javax.ws.rs.core.Response$ResponseBuilder.status(Response.java:921)
    at javax.ws.rs.core.Response.status(Response.java:592)
    at javax.ws.rs.core.Response.status(Response.java:603)
    at javax.ws.rs.core.Response.ok(Response.java:638)

JAX-RS 2.1のAPI群がロードされているにもかかわらず、CDI-Unitが依存しているRESTEasyにはJAX-RS 2.1で追加された抽象メソッド ResponseBuilder#status(int, String) が実装されていないことが原因。

RESTEasyをJAX-RS 2.1に対応したバージョン、すなわち3.5.0以降に上げてやる。

// ✓ OK
dependencies {
    providedCompile 'javax:javaee-web-api:8.0'
    testCompile 'org.jglue.cdi-unit:cdi-unit:4.0.2', {
        exclude module: 'resteasy-jaxrs'
    }
    testRuntime 'org.jboss.resteasy:resteasy-jaxrs:3.6.1.Final'
    testRuntime 'org.jboss.weld.se:weld-se-core:3.0.0.Final'
    testRuntime 'org.jboss.weld.module:weld-web:3.0.0.Final'
}

今度は問題なく実行出来た。

この回避策によって他に悪影響ないかとかは未確認。暫くの間この策を試していこうと思う。