I try to access an open data web service which gives me traffic infos. Documentation says that requests have to be GET
and need to contain Accept: applica
Isn't
accept(MediaType.APPLICATION_JSON)
andheader("Content-type","application/json")
the same?
No, they are different.
This is how they are related:
Client Server
(header) (class/method annotation)
====================================================
Accept <---> @Produces
Content-Type <---> @Consumes
The server consumes what it receives from the client in body (its format is specified in Content-Type
) and it produces what the client accepts (its format is specified in Accept
).
Example:
Content-Type
= text/xml
(it sends an XML in body)Accept
= application/json
(it expects to get a JSON as a response)@Consumes(MediaType.TEXT_XML)
(it gets an XML from the client)@Produces(MediaType.APPLICATION_JSON)
(it sends a JSON to the client)Obs:
The server can be more flexible, being configured to get/produce multiple possible formats.
E.g.: a client can send an XML while another client can send a JSON to the same method if it has the following annotation: @Consumes({ MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
.
The MediaType
values are just String
constants:
public final static String APPLICATION_JSON = "application/json";
public final static String TEXT_XML = "text/xml";
The Accept
header tells the server what your client wants in the response. The Content-Type
header tells the server what the client sends in the request. So the two are not the same.
If the server only accepts application/json
, you must send a request that specifies the request content:
Content-Type: application/json
That's why your edited code works.
Edit
In your first code you use WebTarget.request(MediaType... acceptedResponseTypes). The parameters of this method
define the accepted response media types.
You are using Innvocation.Builder.accept(MediaType... mediaTypes) on the result of this method call. But accept()
adds no new header, it is unnecessary in your first code.
You never specify the content type of your request. Since the server expects a Content-Type
header, it responds with 415
.
You can use the ContainerResponseFilter
to set the default Accept header if it is not provided in the input request.
@Provider
public class EntityResponseFilter implements ContainerResponseFilter {
private MediaType getExternalMediaType(){
MediaType mediaType = new MediaType("application", "vnd.xxx.resource+json")
return mediaType;
}
@Override
public void filter( ContainerRequestContext reqc , ContainerResponseContext resc ) throws IOException {
MediaType mediaType = getExternalMediaType();
List<MediaType> mediaTypes = reqc.getAcceptableMediaTypes();
if( mediaTypes.contains(mediaType) ) {
resc.setEntity( resc.getEntity(), new Annotation[0], mediaType );
}
// ...
}
}