Response with non-OK status does not respect content-type in producer annotation - jersey

I encountered an odd while I was using Jersey..
I had the #Producer (MediaType.APPLICATION_JSON) for the whole resource class.
I have one class CustomerResponse, which is just normal)
If I return Response.status(Stauts.OK).entity(customerResponse).build(), on the client side, I will receive the json entity as I expected.
However, if I return Response.status(Stauts.BAD_REQUEST).entity(customerResponse).build(), the content-type become text/html.
If I change the Producer to APPLICATION_XML, the same thing happens. It seems to me that only response with 400 will return with content-type specified in the #Producer annotation. For all responses with other status code, it will simply return text/html.
Can anyone help me on this? Thank you very much.

This is turns out to be really interesting.
I started grizzly servlet instead grizzly server by using following code
WebappContext webappContext = new WebappContext("GRIZZLY Web Server WebappContext");
ServletRegistration servletRegistration = webappContext.addServlet("JerseyServletContainer", ServletContainer.class);
servletRegistration.setInitParameter("jersey.config.server.provider.packages", WebServiceConstants.ROOT_PACKAGE);
servletRegistration.addMapping("/*");
webappContext.deploy(grizzlyWebServer);
startGrizzlyWebServer(grizzlyWebServer);
It seems like the servlet somehow convert the content-type for all non-OK (not 400) http response to type=text/html; charset=ISO-8859-1.
If I started the grizzly-http-server, everything works fine.

We use like the following:
Response.status(Response.Status.BAD_REQUEST).entity(myObject)
.type(MediaType.APPLICATION_JSON_TYPE).build()

Related

How can I enable ws-addressing in spring so that replyTo is understood?

I created a ws endpoint with spring using spring-boot-starter-webservices.
I have used #org.springframework.ws.server.endpoint.annotation.Endpoint.It works fine.
But when I am trying to add the wsa:ReplyTo addressing header to the request with mustUnderstand=true the server prints:
Could not handle mustUnderstand headers: {http://www.w3.org/2005/08/addressing}ReplyTo. Returning fault
and returns a similar Fault as a response.
How can I enable addressing so that ReplyTo is understood and replies with 202, sending the response to the differrent endpoint described in ReplyTo?
I tried adding #javax.xml.ws.soap.Addressing(enabled=true) next to #Endpoint annotation but I still get the above behaviour.

Spring MVC: how to handle incoming request to wrong context path

How do we handle incoming request to a wrong contextpath in spring mvc?
I have deployed a spring mvc application having contextpath as
http://exampledomain.com/mycontext
But when I try accessing url http://exampledomain.com/wrongcontext I get error as HTTP Status 404 - /wrongcontext/
I have implemented error handling which works fine for all wrong url when correct context path is used but it does not work for wrong context path.
I am trying to understand how do we redirect all incoming request to specific page in production environment..
thanks in advance
Your application can only see requests to its context /mycontext There is nothing your application can do about requests to other contexts.
You can however deploy an application at the root context / and implement an error handler there.
Check out this answer: How to customize JBoss AS7 404 page
That answer relates to JBoss, but the same idea will apply on other servers.
It is not possible to handle wrong context path requests in Spring since it only will handle the requests which goes to your context root. You have to take a look at server configuration parameters to redirect those kind of requests. If you are working on Tomcat, check path parameter of context.xml:
https://tomcat.apache.org/tomcat-7.0-doc/config/context.html#Defining_a_context
We can use #ExceptionHandler inside a #Controller or #ControllerAdvice to handle such kind of exceptions and decide on the view page to be rendered.
#ExceptionHandler({ HttpRequestMethodNotSupportedException.class,
HttpMediaTypeNotSupportedException.class, HttpMediaTypeNotAcceptableException.class,
MissingPathVariableException.class, MissingServletRequestParameterException.class,
ServletRequestBindingException.class,MethodArgumentNotValidException.class, MissingServletRequestPartException.class,
NoHandlerFoundException.class})
public ModelAndView handleException(){
return new ModelAndView("errorpage");
}

Spring Data REST CORS - how to handle preflight OPTIONS request?

I'm using Spring Data REST to build a RESTful API. Until now my HTML GUI for this RESTful service was served from the same Tomcat and I had no problems wit Cross Origin requests.
Now I want to serve the static files from a different server. This means the API is on another domain/port. Browsers will send the OPTIONS request to get the Access-Control headers from the server. Unfortunately Spring Data REST does not handle those OPTIONS requests and even returns a HTTP 500.
I tried creating a custom controller that handles all OPTIONS requests
#Controller
#RequestMapping(value = "/**", method = RequestMethod.OPTIONS)
public class OptionsController {
#RequestMapping
public ResponseEntity options() {
return new ResponseEntity<Void>(HttpStatus.OK);
}
}
Which worked for OPTIONS, but then all other requests (like GET) ceased to work.
OPTIONS requests are switched on via the dispatchOptionsRequest dispatcher servlet parameter.
tl;dr: currently Spring Data REST does not answer OPTIONS requests at all.
It might be worth opening a ticket in our JIRA.
Browsers will send the OPTIONS request to get the Access-Control headers from the server.
Is that specified somewhere? If so, it would be cool if the ticket description included a link to that spec.
A few comments regarding your approach for a workaround:
#RequestMapping on the controller method overrides the method attribute and expectedly now matches all HTTP methods, which is why you see all requests intercepted. So you need to define OPTIONS as HTTP method there, too (or maybe instead of in the class mapping).
You're not returning any Allow header which is the whole purpose of OPTIONS in the first place.
I wonder if the approach in general makes sense as it'll be hard to reason about the supported HTTP methods in general.
Just set the parameter dispatchOptionsRequest to true into the dispatcher to process the Options method calls, into the implementation of the WebApplicationInitializer.
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(applicationContext));
dispatcher.setInitParameter("dispatchOptionsRequest", "true");
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/*");

Intercept 400 response generation when Jersey detects bad xml?

I'm writing a test server that needs to emulate a 3rd party RESTful server, I'm using Jersey to write the test server.
All of the requests are POST with application/xml payloads so I started off with:
#Path("GetUserDetails")
#POST
#Consumes(MediaType.APPLICATION_XML)
public GetUserDetailsResp GetUserDetails(GetUserDetailsReq request) {
...
}
Jersey happily returns 400 when the XML is badly formatted (GetUserDetailsReq is a JAXB object), which is not what I need. Rather I need to return 200 and an XML error block.
I can get around the 400 by unmarshaling in the method and using an #Provider/ExceptionMapper class, but that's clunky. Is there anyway to specify to Jersey an alternative to returning the 400 declaratively? Maybe a variant on #Provider/ExceptionMapper?
TIA.
Pavel Bucek answered this in the mailing list: http://jersey.576304.n2.nabble.com/Intercept-400-response-generation-when-Jersey-detects-bad-xml-tt7221572.html

JAX-RS Jersey - Howto force a Response ContentType? Overwrite content negotiation

Jersey identifies requests by looking at the accept header. I have a request which accepts only text/* - How can i force the response to be for example application/json?
#POST
#Path("/create")
#Produces(MediaType.APPLICATION_JSON)
public MyResponseObject create() {
return new MyResponseObject();
}
If a request is directed to create which only accepts text/* jersey will return a 500. Is there a way to workaround this issue? (I can't change the requests accept header).
Jersey also supports this via ResourceConfig property PROPERTY_MEDIA_TYPE_MAPPINGS that you could configure in your web.xml or programatically via Jersey APIs as shown below:
DefaultResourceConfig rc = new DefaultResourceConfig(MyResource.class);
rc.getMediaTypeMappings().put("json", MediaType.APPLICATION_JSON_TYPE);
rc.getMediaTypeMappings().put("xml", MediaType.APPLICATION_XML_TYPE);
SimpleServerFactory.create("http://localhost:9090", rc);
You can force content type negotiation by suffixing either .json or .xml to your URL.
I solved this by using a servlet filter:
http://www.zienit.nl/blog/2010/01/rest/control-jax-rs-content-negotiation-with-filters

Resources