2011-11-19 11 views
5

Utilizzo RESTEasy 2.2.1.GA come implementazione JAX-RS per creare un client per la connessione a un fornitore di servizi di terze parti. (REST API Education.com se è importante)Come posso ignorare le decisioni prese durante la negoziazione del contenuto JAX-RS?

per assicurarsi che io non ho perso un importante dettaglio di implementazione qui ci sono esempi di codice:

Interface Servizio

@Path("/") 
public interface SchoolSearch { 

@GET 
@Produces({MediaType.APPLICATION_XML}) 
Collection<SchoolType> getSchoolsByZipCode(@QueryParam("postalcode") int postalCode); 
} 

Calling Classe

public class SimpleSchoolSearch { 

public static final String SITE_URL = "http://api.education.com/service/service.php?f=schoolSearch&key=****&sn=sf&v=4"; 

SchoolSearch service = ProxyFactory.create(SchoolSearch.class, SITE_URL); 

public Collection<SchoolType> getSchools() throws Exception { 
    Collection<SchoolType> schools = new ArrayList<SchoolType>(); 
    Collection<SchoolType> response = service.getSchoolsByZipCode(35803); 
    schools.addAll(response); 
    return schools; 

} 
} 

Dopo aver impostato i test per effettuare questa chiamata, Eseguo e vedo la seguente eccezione generata.

org.jboss.resteasy.plugins.providers.jaxb.JAXBUnmarshalException: Unable to find JAXBContext for media type: text/html;charset="UTF-8" 

Dalla lettura della documentazione/JAX-RS RESTEasy, se ho capito bene, quando la risposta viene restituita al cliente, prima della unmarshalling dei dati, viene fatta una determinazione (Negotiation Content ??) su quale meccanismo usare per unmarshalling. (Penso che stiamo parlando di MessageBodyReader qui ma non sono sicuro.) Dal punto di vista del corpo della risposta, vedo che ciò che viene restituito è XML formattato correttamente, ma la negoziazione del contenuto (tramite intestazione HTTP content- type è in effetti text/html; charset = "UTF-8") non consente al testo di essere analizzato da JAXB.

Penso che l'implementazione si comporti correttamente, ed è il servizio che è in errore, tuttavia, non controllo il servizio, ma vorrei comunque consumarlo.

Quindi detto questo:

Ho ragione nella mia comprensione di perché viene generata l'eccezione?

Come posso aggirarlo?

C'è una semplice annotazione su una riga che può forzare JAXB a non riconoscere i dati, o sarà necessario implementare un MessageBodyReader personalizzato? (Se questa è anche la classe corretta da implementare).

Grazie!

Follow Up:

volevo solo inviare i pochi cambiamenti che ho fatto alla risposta di Eiden. Ho creato un ClientExecutionInterceptor usando il suo codice e le informazioni disponibili al Resteasy ClientExecutionInterceptor documentation. La mia classe finale assomiglia

@Provider 
@ClientInterceptor 
public class SimpleInterceptor implements ClientExecutionInterceptor { 

@Override 
    public ClientResponse execute(ClientExecutionContext ctx) throws Exception { 
     final ClientResponse response = ctx.proceed(); 
     response.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML); 
     return response; 
    } 
} 

La grande differenza è l'aggiunta delle annotazioni @Provider e @ClientExecutionInterceptor. Questo dovrebbe assicurare che l'intercettore sia registrato correttamente.

Inoltre, solo per completezza, ho registrato l'Interceptor in modo leggermente diverso per i miei test. Ho usato:

 providerFactory.registerProvider(SimpleInterceptor.class); 

risposta

2

Sono sicuro che ci sono diverse soluzioni a questo problema, ma posso solo pensarne uno.

provare così impostare il tipo di contenuto utilizzando un ClientExecutionInterceptor:

public class Interceptor implements ClientExecutionInterceptor { 

    @Override 
    public ClientResponse<?> execute(ClientExecutionContext ctx) throws Exception { 
     final ClientResponse<?> response = ctx.proceed(); 

     response 
      .getHeaders() 
      .putSingle(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML); 

     return response; 
    } 

} 

public void getSchools() throws Exception { 
    ResteasyProviderFactory.getInstance() 
     .getClientExecutionInterceptorRegistry() 
     .register(new Interceptor()); 

    SchoolSearch service = 
      ProxyFactory.create(SchoolSearch.class, SITE_URL); 
} 
+0

Questo è un compito piuttosto semplice, una volta si stabiliscono che in quel modo. – jholder

0

Non so di tali annotazioni, altre potrebbero fare, ma una soluzione è creare un proxy locale. Creare un controller che trasmetta tutti i parametri a education.com utilizzando un java.Net.URL .get() restituisce la risposta che hai ricevuto, ma modifica l'intestazione. Quindi connetti il ​​tuo client al controller proxy locale.

Problemi correlati