Search code examples
jerseyjersey-client

Can not register jersey MultiPartFeature


I'm trying to create a test case for my Jersey REST application.

I added already in pom.xml:

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-multipart</artifactId>
    <version>2.25</version>
</dependency>

I'm creating my client with:

Client client = ClientBuilder.newBuilder()
        .register(MoxyJsonFeature.class)
        .register(MultiPartFeature.class)
        .build();

But this is failing with an InstantiationException on line .register(MultiPartFeature.class). Here is the full stack trace:

java.lang.RuntimeException: java.lang.InstantiationException: org.glassfish.jersey.media.multipart.internal.MultiPartReaderClientSide

    at __randomizedtesting.SeedInfo.seed([8269888A1B7E6430]:0)
    at org.apache.cxf.jaxrs.impl.ConfigurationImpl.createProvider(ConfigurationImpl.java:199)
    at org.apache.cxf.jaxrs.impl.ConfigurableImpl.register(ConfigurableImpl.java:102)
    at org.apache.cxf.jaxrs.impl.ConfigurableImpl.register(ConfigurableImpl.java:97)
    at org.apache.cxf.jaxrs.impl.ConfigurableImpl$FeatureContextImpl.register(ConfigurableImpl.java:139)
    at org.apache.cxf.jaxrs.impl.ConfigurableImpl$FeatureContextImpl.register(ConfigurableImpl.java:120)
    at org.glassfish.jersey.media.multipart.MultiPartFeature.configure(MultiPartFeature.java:67)
    at org.apache.cxf.jaxrs.impl.ConfigurableImpl.register(ConfigurableImpl.java:86)
    at org.apache.cxf.jaxrs.impl.ConfigurableImpl.doRegister(ConfigurableImpl.java:117)
    at org.apache.cxf.jaxrs.impl.ConfigurableImpl.register(ConfigurableImpl.java:102)
    at org.apache.cxf.jaxrs.impl.ConfigurableImpl.register(ConfigurableImpl.java:97)
    at org.apache.cxf.jaxrs.client.spec.ClientBuilderImpl.register(ClientBuilderImpl.java:56)
    at org.apache.cxf.jaxrs.client.spec.ClientBuilderImpl.register(ClientBuilderImpl.java:35)
    at fr.pilato.elasticsearch.crawler.fs.test.integration.AbstractRestITCase.startRestClient(AbstractRestITCase.java:54)
    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.carrotsearch.randomizedtesting.RandomizedRunner.invoke(RandomizedRunner.java:1764)
    at com.carrotsearch.randomizedtesting.RandomizedRunner$6.evaluate(RandomizedRunner.java:811)
    at com.carrotsearch.randomizedtesting.RandomizedRunner$7.evaluate(RandomizedRunner.java:827)
    at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:48)
    at com.carrotsearch.randomizedtesting.rules.StatementAdapter.evaluate(StatementAdapter.java:36)
    at com.carrotsearch.randomizedtesting.ThreadLeakControl$StatementRunner.run(ThreadLeakControl.java:367)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.InstantiationException: org.glassfish.jersey.media.multipart.internal.MultiPartReaderClientSide
    at java.lang.Class.newInstance(Class.java:427)
    at org.apache.cxf.jaxrs.impl.ConfigurationImpl.createProvider(ConfigurationImpl.java:197)
    ... 23 more
Caused by: java.lang.NoSuchMethodException: org.glassfish.jersey.media.multipart.internal.MultiPartReaderClientSide.<init>()
    at java.lang.Class.getConstructor0(Class.java:3082)
    at java.lang.Class.newInstance(Class.java:412)
    ... 24 more

I don't understand what I'm missing here. I followed Jersey documentation but I might have missed something. When I remove the line .register(MultiPartFeature.class), I'm able to run REST tests normally using my client.

Any idea?


Solution

  • The problem was caused by another dependency in my project: org.apache.tika:tika-langdetect:1.14. tika-langdetect adds apache CXF to the classpath which seems to trouble a bit Jersey.

    When excluding CXF from my project, I can see that Jersey is only using "Jersey" classes:

      at org.glassfish.jersey.media.multipart.MultiPartFeature.configure(MultiPartFeature.java:67)
      at org.glassfish.jersey.model.internal.CommonConfig.configureFeatures(CommonConfig.java:730)
      at org.glassfish.jersey.model.internal.CommonConfig.configureMetaProviders(CommonConfig.java:648)
      at org.glassfish.jersey.client.ClientConfig$State.configureMetaProviders(ClientConfig.java:372)
      at org.glassfish.jersey.client.ClientConfig$State.initRuntime(ClientConfig.java:405)
      at org.glassfish.jersey.client.ClientConfig$State.access$000(ClientConfig.java:90)
      at org.glassfish.jersey.client.ClientConfig$State$3.get(ClientConfig.java:122)
      at org.glassfish.jersey.client.ClientConfig$State$3.get(ClientConfig.java:119)
      at org.glassfish.jersey.internal.util.collection.Values$LazyValueImpl.get(Values.java:340)
      - locked <0x1178> (a java.lang.Object)
      at org.glassfish.jersey.client.ClientConfig.getRuntime(ClientConfig.java:733)
      at org.glassfish.jersey.client.ClientRequest.getConfiguration(ClientRequest.java:286)
      at org.glassfish.jersey.client.JerseyInvocation.validateHttpMethodAndEntity(JerseyInvocation.java:135)
      at org.glassfish.jersey.client.JerseyInvocation.<init>(JerseyInvocation.java:105)
      at org.glassfish.jersey.client.JerseyInvocation.<init>(JerseyInvocation.java:101)
      at org.glassfish.jersey.client.JerseyInvocation.<init>(JerseyInvocation.java:92)
      at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:437)
      at org.glassfish.jersey.client.JerseyInvocation$Builder.post(JerseyInvocation.java:343)
      at fr.pilato.elasticsearch.crawler.fs.test.integration.FsCrawlerRestIT.testUploadFile(FsCrawlerRestIT.java:56)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-1)
      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)
    

    I now need to understand why actually this CXF dependency is confusing Jersey but that's another story :)

    EDIT: basically you can't have both CXF and Jersey on the same classpath as they are providing different implementation for the same JaxRS feature.

    For my project, I don't need Tika upload/download features, so I can simply exclude Apache CXF from tika dependencies with:

        <dependency>
            <groupId>org.apache.tika</groupId>
            <artifactId>tika-parsers</artifactId>
            <version>1.14</version>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.cxf</groupId>
                    <artifactId>cxf-rt-rs-client</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.tika</groupId>
            <artifactId>tika-langdetect</artifactId>
            <version>1.14</version>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.cxf</groupId>
                    <artifactId>cxf-rt-rs-client</artifactId>
                </exclusion>
            </exclusions>
        </dependency>