2015-06-02 15 views
8

Sto scrivendo un client REST utilizzando Jersey con JacksonFeature abilitato per un servizio web che mi obbliga a specificare il loro tipo di contenuto con nome personalizzato, anche se è solo normale JSON. In altre parole, quando faccio questo:Jersey REST Client - Tratta MediaType personalizzato come MediaType.APPLICATION_JSON

Request request = buildMySampleRequestPojo(); 

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

Il servizio lamenta che sto usando un tipo di contenuto valido. Posso ottenere intorno a questo specificando il tipo di supporto con nome personalizzato al posto della costante MediaType.APPLICATION_JSON:

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

Tuttavia, quando lo faccio, ottengo:

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

Esiste un modo Posso fare in modo che Jersey tratti questo nome di tipo di supporto personalizzato come se fosse un normale JSON senza scrivere un MessageBodyWriter personalizzato?

+0

hai provato a utilizzare il formato di tipo di supporto convenzionale, ad es. 'Application/vnd.stupidNameThatReallyIsJustJSON + json'? –

+0

Sì, nel mio secondo esempio di codice è più che il formato del nome del tipo di supporto effettivo sembra che ho appena cercato di offuscarlo un po ' – kwikness

risposta

7

Penso che sia possibile utilizzare sia this (JAX-RS entity providers) e this (use Jackson with Jersey), al fine di ottenere ciò che si desidera. In poche parole, registra un MessageBodyWriter annotato con @Produces("application/vnd.stupidNameThatReallyIsJustJSON+json") e nell'implementazione deleghi solo il marshalling/unmarshalling a Jackson.

EDIT: provare con qualcosa sulla falsariga di

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; 
    } 

} 

Ovviamente questo è solo un punto di partenza, non un esempio di lavoro, ma dovrebbe darvi abbastanza informazioni per iniziare. Ricorda inoltre che dovrai iscriverti a Jersey per poterlo usare.

+0

non ho dimenticato di te franc, aspettando solo un po' di tempo libero per venire avanti così posso prova questa soluzione – kwikness

+0

Franc potresti fornire ulteriori dettagli? Che MessageBodyWriter potrei usare in questo caso? Dovrei creare la mia classe? Esiste una classe "JSONMessageBodyWriter" esistente che potrei sottoclasse e annotare semplicemente con l'annotazione @Produces che hai menzionato? – kwikness

+1

@kwikness 'JacksonJsonProvider' –