javagsonjersey-2.0jersey-test-framework

MessageBodyProvider not found in Test for Custom provider - Manually works


I know that the error "MessageBodyProvider" not found for application type question has been asked a lot of time, but my case is a bit different.

The REST works fine when I manually invoke the REST API through Fiddler or in the browser. So there seems to something odd with the test. I can't get my head around this.

org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/json, type=class xxxx.observer.Observer, genericType=class xxxxx.observer.Observer.
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:248)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:163)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1135)   at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:248)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:163)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1135)
    at org.glassfish.jersey.client.ClientRequest.doWriteEntity(ClientRequest.java:516)
    at org.glassfish.jersey.client.ClientRequest.writeEntity(ClientRequest.java:498)
    at org.glassfish.jersey.client.internal.HttpUrlConnector._apply(HttpUrlConnector.java:384)
    at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:282)
    at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:278)
    at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$0(JerseyInvocation.java:753)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:229)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:414)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:752)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:445)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.post(JerseyInvocation.java:351)

I have a Custom Json Provider (Gson) and my test class:

public class AppTest extends JerseyTest {
    @Override
    protected Application configure() {
        String directory = "src/test/resources/de/xxxx";

        ResourceConfig resourceConfig = new ResourceConfig(GenericExceptionMapper.class, ScenarioProtocolResource.class,
                CloudlistResource.class, GsonJerseyProvider.class, CORSFilter.class, EncodingFilter.class,
                GZipEncoder.class, DeflateEncoder.class);
        Map<String, String> properties = new HashMap<>();

        properties.put("directory", directory);
        resourceConfig.setProperties(properties);

        return resourceConfig;
    }

In my test class I simply try do a POST request:

Response resp = target("json/proto/observer/add/xxxxx").request(MediaType.APPLICATION_JSON).post(Entity.entity(observer, MediaType.APPLICATION_JSON));

Solution

  • You're only registering the provider on the server side in the configure() method. You still need to register it on the client side. You can see in the stacktrace that the problem is occurring on the client side (see client in the package names).

    You can either just register the provider on the WebTarget or you can override configureClient() to register it with the Client.

    Response resp = target("json/proto/observer/add/xxxxx")
            .register(GsonJsonProvider.class)
            ...
    

    or

    @Override
    public void configureClient(ClientConfig config) {
        config.register(GsonJsonProvider.class);
    }
    

    Benefit of the latter is that you don't need to keep registering it with the WebTarget on each test.