I have configured MEDIA_TYPE_MAPPINGS
for my Jersey apps. Unfortunately, this causes some trouble with a generic upload service in my app.
@PUT
@Path("files/{filename}")
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Response uploadFile(
@PathParam("filename") @NotNull @Size(max = 240) String filename, DataSource dataSource)
If someone uploads .../files/file.xml
the extension is chopped of.
Is there a way to tell Jersey to skip that filtering for this resource?
Edit: After peeskillet's answer, my assumption was confirmed. I have filed an improvement request: https://java.net/jira/browse/JERSEY-2780
First of all, this is in no way a bug. It is the expected behavior. The purpose of media type mappings is not related to working with files, but instead an alternative form of content negotiation for cases where setting headers may not be available, for instance in a browser.
Though not in the official spec, this feature was part of a draft prior to the specs final release. Most implementations decided to include it one way or another. Jersey happens to let you configure it. So can see here in the spec in 3.7.1 Request Preprocessing
3(b) is basically saying that the extension should be removed from the requested URI and 4 is stating that there should be some extension mapping that would map say
json
(the extension) toapplication/json
and set that as theAccept
header. You can see from different tests, this behaviorIf we comment out that configuration property, you will see that the
Accept
header hasn't been set.That being said...
When you configure the
ServerProperties.MEDIA_TYPE_MAPPINGS
, theorg.glassfish.jersey.server.filter.UriConnegFilter
is the filter used for this feature. You can see in the source code in line 204 and 211, where the filter is stripping the extensionSo there's no way to configure this (at least as far as I can tell from looking at the source), so we would have to extend that class, override the
filter
method and take out, at minimum, that last line that actually does the replacing, then register the filter. Here's what I did to get it to work. I simply copy and pasted the code from the filter, and commented out the line where it replaces the extensionThen configure it