Entity of Response is null - rest

currently I am coding on a mock for a rest service we're using. For one case I want to return a 404 with a specific message in the body:
#POST
#Produces(MediaType.APPLICATION_XML)
#Consumes(MediaType.APPLICATION_XML)
#Path("/bookings")
public javax.ws.rs.core.Response performBooking(final BookingRequest booking) {
if (shouldfail(booking)) {
return Response.status(Response.Status.NOT_FOUND).entity("specific message in entity").build();
}
// some more other cases below...
}
If I test the mock with a unit test everything works fine:
final String failedMessage = response.getEntity().toString();
But if I deploy the rest service and call it, I will get the correct 404 code, but the entity is null.
For valid answers I put a BookingResponse object in the entity (simple DTO with some IDs in it) and it works for that. Just the string seems to disappear.
Any idea why my string disappears?

Related

Spring boot restful service Post request always returns null as response message in test code using Junit

This is a demo controller.
#PostMapping("/rest/new")
public ResponseEntity<MessageDto> newUser(#RequestBody UserDto userDto) {
return ResponseEntity.ok(new MessageDto().setMessage(userService.createUser(userDto)));
}
This is service layer.
#Override
public String createUser(UserDto userDto) {
// Do Something
return "Successful!!";
}
This is the test code to test the controller
#Test
public void testPostRestController() throws Exception {
UserDto userDto = new UserDto();
userDto.setName("AA");
userDto.setEmail("a#a.a");
userDto.setId((long) 1);
when(userService.createUser(userDto)).thenReturn("Successful!!");
mockMvc.perform(post("/rest/new")
.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
.content(new ObjectMapper().writeValueAsString(userDto)))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
.andExpect(jsonPath("$.message", is(userService.createUser(userDto))))
.andDo(MockMvcResultHandlers.print());
}
The problem is when I run the test code, it is supposed to check the response status and response message. The response status matched but the problem is the response message always returns as null.
error:
java.lang.AssertionError: JSON path "$.message"
Expected: is "Successful!!"
but: was null
Am I missing something here?
Try using
when(userService.createUser(any(UserDto.class))).thenReturn("Successful!!");
Instead of
when(userService.createUser(userDto)).thenReturn("Successful!!");
This should ideally fix the NPE

Wep Api - 405 Method Not Allowed

I have a Web Api project with a controller that has methods for GET, DELETE, POST, and PUT.
When I try to do a POST or PUT to this controller I always get a 405 Method Not Allowed error. The data being sent over looks valid, it's just an object with six simple properties. I put a breakpoint in my method and as expected in this case, it doesn't get hit. I registered a DelegatingHandler (mentioned at Web Api - Catch 405 Method Not Allowed) to inspect the incoming request and outgoing response and I can tell that my request is being processed by the Api (meaning the problem is not with the client). I also used Fiddler to inspect the request/response and the response headers say under Security, Allow: DELETE, GET.
This clearly tells me that PUT and POST are not allowed, for whatever reason, even though I have methods decorated with the [HttpPost] and [HttpPut] attributes and have the routing configured correctly, as far as I can tell. I am using default routing but also have methods which use attribute routing.
This sounds like there may be some kind of security issue, however, I'm able to do POST and PUT in my other controllers and I don't see any differences which I believe would be the cause of the problem.
Here's a snippet of my code:
public class PricesController : ApiController
{
// DELETE: api/Prices/5
[HttpDelete]
[ResponseType(typeof(Price))]
[Route("api/Prices/{id:int}")]
public async Task<IHttpActionResult> DeletePrice(int id)
{
// code omitted
}
// GET: api/Prices/5
[HttpGet]
[ResponseType(typeof(Price))]
[Route("api/Prices/{id:int}")]
public async Task<IHttpActionResult> GetPrice(int id)
{
// code omitted
}
// GET: api/Prices
[HttpGet]
[Route("api/Prices")]
public IQueryable<Price> GetPrices()
{
// code omitted
}
// POST: api/Prices
[HttpPost]
[ResponseType(typeof(Price))]
[Route("api/Prices", Name = "Prices")]
public async Task<IHttpActionResult> PostPrice(Price price)
{
// code omitted
}
// PUT: api/Prices/5
[HttpPut]
[ResponseType(typeof(void))]
[Route("api/Prices/{id:int}")]
public async Task<IHttpActionResult> PutPrice(int id, Price price)
{
// code omitted
}
}
Any help would be appreciated. I've spent all day trying to figure this out.
It sounds like it's not binding correctly.
Can you try decorating Price with [FromBody] before it in your actions?
PostPrice([FromBody] Price price)

Spring MVC REST using #RequestBody List<?> returns HTTP 400 syntactically incorrect

I am using Spring 4 + Jackson 2 and have written a fully functional POST method using #RequestBody on a custom class. This method has no trouble unmarshalling the object.
#ResponseBody
#RequestMapping(value="store", method = RequestMethod.POST)
public ServiceResponse store(#RequestBody CustomClass list) {
...
}
// Request: { code: "A", amount: 200 }
When I attempted to add another method to handle a collection of the same class instead, my POST requests were returning with the following error.
HTTP Status 400: The request sent by the client was syntactically incorrect.
I note that this error typically occurs when the JSON submitted does not match the entity class. However, all I am doing is submitting an array of the same object instead of the object itself, which has already proven to work.
#ResponseBody
#RequestMapping(value="store-bulk", method = RequestMethod.POST)
public ServiceResponse storeBulk(#RequestBody List<CustomClass> list) {
...
}
// Request: [{ code: "A", amount: 200 }, { code: "B", amount: 400 }]
Am I missing something here?
In Java, type information for generics is erased at runtime, so Spring sees your List<CustomClass> object as List<Object> object, thus it cannot understand how to parse it.
One of ways to solve it, you could capture the type information by creating a wrapper class for your list, like this:
public class CustomClassList extends ArrayList<CustomClass> {
}
Sergey is right that the issue is due to type erasure. Your easiest way out is to bind to an array, so
#ResponseBody
#RequestMapping(value="store-bulk", method = RequestMethod.POST)
public ServiceResponse storeBulk(#RequestBody CustomClass[] object) {
...
}
The answer is that Spring 4 doesn't actually get rid of type erasure, contrary to what some other solutions suggest. While experimenting on debugging via manual unmarshalling, I decided to just handle that step myself instead of an implicit cast that I have no control over. I do hope someone comes along and proves me wrong, demonstrating a more intuitive solution though.
#ResponseBody
#RequestMapping(value="store-bulk", method = RequestMethod.POST)
public ServiceResponse storeBulk(#RequestBody String json) {
try {
List<CustomClass> list = new ObjectMapper().readValue(json, new TypeReference<List<CustomClass>>() { });
...
} catch (Exception e) {
...
}
}
Bonus: Right after I got this working, I bumped into this exception:
IllegalStateException: Already had POJO for id
If anyone gets this, it's because the objects in the list happen to reference some object that another item in the list already references. I could work around this since that object was identical for my entire collection, so I just removed the reference from the JSON side from all but the first object. I then added the missing references back after the JSON was unmarshalled into the List object.
Two-liner for the Java 8 users (the User object reference was the issue in my case):
User user = list.get(0).getUser();
list.stream().filter(c -> c.getUser() == null).forEach(t -> t.setUser(user));

jersey 2.0 jaxrs RI - return json string on exception

I am creating a REST service using jersey 2.0. I am extending WebApplicationException
Method raising a particular exception
if(json.equals("") || json.equals(" ")) {
throw new ArgumentException("bad post data");
}
public class ArgumentException extends RestException {
.....
public ArgumentException(String message) {
super(Status.BAD_REQUEST,message);
}
}
public class RestException extends WebApplicationException {
...........
public RestException(Status status, String message) {
super(Response.status(status)
.entity(message)
.type("text/plain")
.build());
/*
super(Response.status(status)
.entity(new ErrorBean(status.getStatusCode(),message))
.type(MediaType.APPLICATION_JSON)
.build()); */
}
ErrorBean is a POJO
The method that returns error as plain string inside RestException works (right http code 400 and message). However when I try to pass the ErrorBean POJO and use MediaType.APPLICATION_JSON in response I get an error saying "Headers have already been sent" with http error code 500 (so some internal problem with plumbing) and empty response.
I have also looked at this question Returning JSON or XML for Exceptions in Jersey
How can I return the exception with code and message as a JSON like
{"code" : 400, "message" : .... }
Update
I have received answer on SO as well as jersey users mailing list. steps are
A non AJXB POJO does not need any annotations
Register JacksonFeature in your application
ResourceConfig rc = new ResourceConfig().packages("test").register(JacksonFeature.class);
You need to register JacksonFeature in your Application/ResourceConfig, i.e.:
// Create JAX-RS application.
final Application application = new ResourceConfig()
.packages("org.glassfish.jersey.examples.jackson")
.register(JacksonFeature.class)
// No need to register this provider if no special configuration is required.
.register(MyObjectMapperProvider.class);
Take a look at the documentation for Jackson support in Jersey and also at the example.

Error Generating XML Document from object

I am wishing to serialize a complex object for returning from a web service request. Here are my assumptions. I need to have the serialized (deflated) object in an XML document (as opposed to a string) before returning to the calling client. I "believe" I am deserializing just fine it is just a matter of getting it loaded into the XMLDocument. However I could be wrong and the deserialization may be wrong therefore the XmlDocument blows up. Here is the code:
My Complex Object:
namespace ABCTest
{
[XmlRoot("TapRoot")]
public class UserDetails
{
[XmlElement]
public String AccountName { get; set; }
}
}
My serialization code:
FYi: UsrDtls == List<UserDetails>
XmlSerializer Obj2XML = new XmlSerializer(UsrDtls.GetType());
Stream strWriter = Stream.Null;
XmlWriter XWriter = new XmlTextWriter(strWriter, Encoding.Unicode);
XmlDocument XDoc = new XmlDocument();
Obj2XML.Serialize(XWriter, lst_Exercises);
string abc = Obj2XML.ToString(); //debugging line to attempt to browse the obj2xml object
XDoc.LoadXml(abc);
return XDoc;
I have no idea where you learned about web services in .NET. Just return the object. The web service infrastructure will take care of it.
You don't say whether you're using WCF services or the legacy ASMX services. The ASMX services should not be used for new development.
If you still have trouble when you "just return it", then please post the details of any exceptions you receive.