2017-06-27 2 views
1

Ich benutze Jersey und entschied mich, mit GSON statt Moxy für JSON-Handhabung zu gehen (mochte nicht die Tatsache, dass Moxy Setzer benötigt).MessageBodyProviderNotFoundException wird in JerseyTest geworfen, wenn GSON verwendet wird

Alles funktioniert gut, bis auf ein sehr nerviges Problem in meinen Unterklassen JerseyTest: benutzerdefinierte GsonProvider wird nicht erkannt, es sei denn explizit für jeden Anruf registriert. Es wird jedoch erkannt, wenn ich die Anwendung auf Tomcat ausstelle.

Mein ResourceConfig:

@ApplicationPath("") 
public class MyResourceConfig extends ResourceConfig { 

    public MyResourceConfig() { 
     register(GsonProvider.class); 

     register(SomeResource.class); 
    } 
} 

Implementierung von GsonProvider (obwohl ich glaube nicht, es auf die Frage verwandt erlebe ich):

@Produces(MediaType.APPLICATION_JSON) 
@Consumes(MediaType.APPLICATION_JSON) 
public class GsonProvider<T> implements MessageBodyReader<T>, MessageBodyWriter<T> { 

    private final Gson mGson; 

    public GsonProvider() { 
     mGson = new GsonBuilder().create(); 
    } 

    @Override 
    public boolean isReadable(Class<?> type, Type genericType, 
           Annotation[] annotations, MediaType mediaType) { 
     return true; 
    } 

    @Override 
    public T readFrom(Class<T> type, Type genericType, Annotation[] annotations, 
         MediaType mediaType, MultivaluedMap<String, String> httpHeaders, 
         InputStream entityStream) throws IOException, WebApplicationException { 

     InputStreamReader reader = new InputStreamReader(entityStream, "UTF-8"); 
     try { 
      return mGson.fromJson(reader, type); 
     } finally { 
      reader.close(); 
     } 
    } 

    @Override 
    public boolean isWriteable(Class<?> type, Type genericType, 
           Annotation[] annotations, MediaType mediaType) { 
     return true; 
    } 

    @Override 
    public long getSize(T t, Class<?> type, Type genericType, 
         Annotation[] annotations, MediaType mediaType) { 
     return -1; 
    } 

    @Override 
    public void writeTo(T t, Class<?> type, Type genericType, Annotation[] annotations, 
         MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, 
         OutputStream entityStream) throws IOException, WebApplicationException { 

     PrintWriter printWriter = new PrintWriter(entityStream); 
     try { 
      String json = mGson.toJson(t); 
      printWriter.write(json); 
      printWriter.flush(); 
     } finally { 
      printWriter.close(); 
     } 
    } 
} 

Diese Testergebnisse in MessageBodyProviderNotFoundException:

public class SomeResourceTest extends JerseyTest { 
    @Override 
    public Application configure() { 
     return new MyResourceConfig(); 
    } 

    @Test 
    public void someApi_200Returned() throws Exception { 
     // Arrange 
     // Act 
     SomeResponse response = 
       target("/somepath") 
         .request() 
         .post(Entity.json(""), SomeResponse.class); 
     // Assert 
     assertThat(response.getStatus(), is(200)); 
    } 
} 

Um dieses Problem zu beheben I reg iter GsonProvider für Anfrage. Die folgende Änderung macht den Test:

public class SomeResourceTest extends JerseyTest { 
    @Override 
    public Application configure() { 
     return new MyResourceConfig(); 
    } 

    @Test 
    public void someApi_200Returned() throws Exception { 
     // Arrange 
     // Act 
     SomeResponse response = 
       target("/somepath") 
         .register(GsonProvider.class) 
         .request() 
         .post(Entity.json(""), SomeResponse.class); 
     // Assert 
     assertThat(response.getStatus(), is(200)); 
    } 
} 

So, die Registrierung von GsonProvider in MyResourceConfig ist gut für den Einsatz, aber JerseyTest erfordert zusätzliche Registrierung pro Anfrage.

Während ich damit leben kann, ist es ärgerlich, zeitaufwendig und wird schwierig sein, mit anderen Teammitgliedern zu kommunizieren. Irgendeine Lösung für dieses Problem?

Antwort

1

Sie haben den StackTrace nicht angezeigt, aber ich bin mir ziemlich sicher, dass wenn Sie genau hinsehen, es zeigen wird, dass es sich tatsächlich um einen clientseitigen Fehler handelt. Was Sie tun müssen, ist die Gson Anbieter mit dem Kunden auch registrieren lassen, da Sie versuchen, die Antwort JSON zu einer POJO

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

Die configureClient Verfahren ist ein Verfahren, in dem JerseyTest deserialisieren, die Sie überschreiben können.

+0

Ja! Ich habe nicht erkannt, dass der Client eine eigenständige Entität ist. Danke – Vasiliy

+0

Ich musste den Provider bei jedem Anruf registrieren und es hat funktioniert. Ich war mir jedoch ziemlich sicher, dass es eine allgemeine Lösung gibt, und Ihre Antwort ist genau das, was ich brauchte. Setze diese Logik in die 'MyJerseyTest'-Basisklasse und das Leben ist wieder gut :) – Vasiliy

Verwandte Themen