2015-06-02 29 views
8

Piszę klienta REST za pomocą Jersey z JacksonFeature włączona dla usługa, która zmusza mnie, aby określić swoją niestandardową nazwie typ zawartości, nawet jeśli jest to tylko regularne JSON. Innymi słowy, gdy to zrobię:Jersey REST Client - Treat niestandardowy MediaType jak MediaType.APPLICATION_JSON

Request request = buildMySampleRequestPojo(); 

Response response = requestBuilder.post(
     Entity.entity(request, MediaType.APPLICATION_JSON) 
); 

Usługa polega na tym, że używam nieprawidłowego typu treści. mogę obejść ten problem, określając ich niestandardowy typ nośnika nazwie zamiast stałej MediaType.APPLICATION_JSON:

Response response = requestBuilder.post(
     Entity.entity(request, "vnd.stupidNameThatReallyIsJustJSON+json") 
); 

Jednak, kiedy to zrobić, uzyskać:

*SEVERE: MessageBodyWriter not found for media type=stupidNameThatReallyIsJustJSON* 

Czy istnieje sposób Mogę traktować tę niestandardową nazwę typu nośnika w programie Jersey tak, jakby był zwykłym JSON-em bez pisania dostosowanego MessageBodyWriter?

+0

czy próbowałeś używać konwencjonalnego formatu typu nośnika, np. 'application/vnd.stupidNameThatResetIsJustJSON + json'? –

+0

Tak, w moim drugim przykładzie kodu wygląda to tak, jak wygląda format nazwy rzeczywistego typu mediów Po prostu starałem się to zaciemnić – kwikness

Odpowiedz

7

Myślę, że można użyć zarówno this (JAX-RS entity providers) i this (use Jackson with Jersey), aby osiągnąć to, co chcesz. W skrócie, zarejestruj się pod numerem MessageBodyWriter, opatrzonym adnotacją @Produces("application/vnd.stupidNameThatReallyIsJustJSON+json"), a we wdrożeniu po prostu przekazuj misjonowanie/unmarshalling Jacksonowi.

EDIT: spróbować czegoś wzdłuż linii

package my.pack.age; 

import com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider; 
import com.sun.jersey.core.util.ReaderWriter; 

import javax.ws.rs.Produces; 
import javax.ws.rs.WebApplicationException; 
import javax.ws.rs.core.MediaType; 
import javax.ws.rs.core.MultivaluedMap; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.io.OutputStreamWriter; 
import java.lang.annotation.Annotation; 
import java.lang.reflect.Type; 

@Produces("application/vnd.stupidNameThatReallyIsJustJSON+json") 
public class MyJsonBodyWriter<T> extends AbstractMessageReaderWriterProvider<T> { 

    // T should be your pojo in this case. If you can make your pojo compatible with org.codehaus.jettison.json.JSONObject, 
    // then you can extend com.sun.jersey.json.impl.provider.entity.JSONObjectProvider and delegate all the methods of 
    // MessageBodyWriter (and MessageBodyReader) to that. Otherwise just implement them. 

    @Override 
    public T readFrom(Class<T> type, Type genericType, Annotation annotations[], MediaType mediaType,MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException { 
     try { 
//   deserialize entityStream according to the given media type and return a new instance of T. 
//    
//   You can do it like this (just an example) : 
//   JSONObject myObject = new JSONObject(); 
//   try { 
//    these names and values should come from the stream. 
//    myObject.put("name", "Agamemnon"); 
//    myObject.put("age", 32); 
//   } catch (JSONException ex) { 
//    LOGGER.log(Level.SEVERE, "Error ...", ex); 
//   } 
      return null; 
     } catch (Exception e) { 
      throw new WebApplicationException(new Exception("Error during deserialization", e),400); 
     } 
    } 

     @Override 
    public void writeTo(T t,Class<?> type, Type genericType, Annotation annotations[], MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException { 
     try { 
      OutputStreamWriter writer = new OutputStreamWriter(entityStream, ReaderWriter.getCharset(mediaType)); 
      // write t on the writer 
      writer.flush(); 
     } catch (Exception e) { 
      throw new WebApplicationException(new Exception("Error during serialization", e), 500); 
     } 
    } 

    @Override 
    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { 
     // should return true if this class can serialize the given type to the given media type 
     return true; 
    } 

    @Override 
    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { 
     // should return true if this class can deserialize the given type to the given media type 
     return true; 
    } 

    @Override 
    public long getSize(T t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { 
     // calculate and return content-lenght, i.e. the lenght of the serialized representation of t 
     return 0; 
    } 

} 

Oczywiście jest to tylko punkt wyjścia, a nie przykładem pracy, ale powinno dać wystarczająco dużo informacji, aby rozpocząć. Pamiętaj też, że musisz zarejestrować klasę na Jersey, aby pozwolić jej korzystać z niej.

+0

nie zapomniałem o tobie Franku, tylko czekając na trochę wolnego czasu, więc mogę spróbuj tego rozwiązania. – kwikness

+0

Franc możesz podać więcej szczegółów? Jakiego MessageBodyWriter mogę użyć w tym przypadku? Czy muszę stworzyć własną klasę? Czy istnieje klasa "JSONMessageBodyWriter", którą mogłabym podklasować i po prostu dodawać adnotacje do wspomnianej adnotacji @Produces? – kwikness

+1

@kwikness 'JacksonJsonProvider' –