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?
Ja! Ich habe nicht erkannt, dass der Client eine eigenständige Entität ist. Danke – Vasiliy
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