Reputation: 11
I am using Jersey and Jackson to access a REST web service, which is correctly returning well formed JSON data but has the response header:
Content-Type: text/html; charset=UTF-8
Even though I have specified Accept: application/json in the request header and as a result is causing Jersey to throw:
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=text/html;charset=UTF-8
I am consuming other web services fine with my code, but I am wondering if there is a way to create my own MessageBodyReader to deal with the mis-match, however I have yet to figure out how to implement it correctly. I plan to ask the owner of the web service to fix the mis-match but I don't hold out much hope.
Upvotes: 0
Views: 211
Reputation: 11
Okay so I managed to figure it out by essentially following Stephen C's advice but thought I'd post a few more details in case anyone else is in the same boat. First I actually started from the Jersey guide a few sections back, specifically this one:
https://jersey.java.net/documentation/latest/user-guide.html#d0e6825
Obviously I am using Jersey for the javax.ws.rs.client and I am using Genson to do the JSON deserialisation. As a result I have implemented the following class to implement a MessageBodyReader:
public class BTCEURTradeMessageBodyReader
implements MessageBodyReader<BTCEURTrades> {
final org.slf4j.Logger logger =
LoggerFactory.getLogger(BTCEURTradeMessageBodyReader.class);
@Override
public boolean isReadable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
logger.info("isReadable being checked for: {} and media type: {}", type, mediaType);
return type == BTCEURTrades.class;
}
@Override
public BTCEURTrades readFrom(Class<BTCEURTrades> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
throws IOException, WebApplicationException {
logger.info("readFrom being called for: {}", type);
BTCEURTrades btceurTrades;
try {
btceurTrades = new Genson().deserialize(entityStream, type);
} catch(Exception e) {
logger.error("Error processing JSON reponse.", e);
throw new ProcessingException("Error processing JSON reponse.");
}
return btceurTrades;
}
}
This then gets registered with the client after it is created as follows:
client = ClientBuilder.newClient();
client.register(BTCEURTradeMessageBodyReader.class);
Upvotes: 1
Reputation: 718826
I am wondering if there is a way to create my own MessageBodyReader to deal with the mis-match.
This page in the Jersey documentation explains how to create a custom MessageBodyReader:
In your case, you may be able to find the source code for the reader that is ordinarily used for your JSON, and "tweak" it. In theory.
However, after a bit more reading, I found this:
which is telling me that Jersey already has extensive support for JSON. There is a good chance that you could fix your problem this by simply tweaking the configs so that Jersey knows what to do with the unusual content-type. But that will depend on which of the many possible ways that you are parsing JSON response bodies ... at the moment.
Someone commented thus:
I think however easier just to retrieve the data, ignore the header and just parse it into your json object.
That is a bad idea. The header is telling you that the JSON could contain multi-byte characters. If you simply ignored that and decoded the bytes to characters in the default character set, you would get "mojibake" if there were multibyte characters present.
If you are parsing the JSON yourself, then it should be a simple matter to configure the parser's input stream to use UTF-8, or whatever else the content-type header says the character encoding is.
Finally, there is the issue of "who is wrong".
I actually think it is your fault. If you send just an "Accept: application/json" header, you are telling the server that you don't care what the character set is. The server is then free to pick any charset for the response that it knows will correctly represent the response text. (In this case the text content of the JSON.)
If you specifically want (say) ASCII or Latin-1 then you should add an "Accept-charset:" header.
If >>THAT<< doesn't work, then maybe it is the server's fault. But bear in mind that if the response does / could contain characters that cannot be encoded on your preferred charset, then the server could / should send you a 406 error.
Upvotes: 0