jackson-dataformat-xml breaks defualt config - java

I have a RestController which receives a XML POST Request.
#PostMapping(value = "/check", consumes = { MediaType.TEXT_XML_VALUE,
MediaType.MULTIPART_FORM_DATA_VALUE }, produces = MediaType.TEXT_XML_VALUE)
public ResponseEntity<CheckResponse> checkRequest(
#RequestBody(required = true) CheckRequest checkRequest) {
//Code...
}
The body looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<ns2:CheckRequest>
<UserIp>1.1.1.1</UserIp>
<AgencyManagement>
<Customer>123456</Customer>
<Office>abcde</Office>
</AgencyManagement>
</ns2:CheckRequest>
I'm using the default converter configuration and the CheckRequest Object is filled with data.
Now I like to save the request to the Database using the com.fasterxml.jackson.databind.ObjectMapper. Using the default config its writing JSON instead of XML. So I added the following dependency to get the XmlMapper.class :
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
So if I start my application again and send the same request all the properties are empty when it arrives to the Controller.
Why is this the case and how can I solve it?

Related

Spring Boot file upload doesn't work (bad request)

I'm trying to do a simple file upload via a Rest API created with Spring Boot and Kotlin. This is my code:
#RestController
#RequestMapping("/api")
class Controller {
#PostMapping("/upload")
fun handleFileUpload(#RequestParam("file") file: MultipartFile): ResponseEntity<String> {
try {
file.transferTo(File("C:\\upload\\" + file.originalFilename))
}
catch (e: Exception) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build()
}
return ResponseEntity.ok("File uploaded successfully.")
}
}
When I use Postman to test it, I get the status "400 Bad Request".
I'm using a Post-Request with the URL http://localhost:8080/api/upload. In the Header Section I left everything how it is (I read somewhere that the Content-Type Header sometimes causes trouble and therefore turned it off temporarily but this didn't help). In the Body section I chose "form-data", added a key called "file" and selected my test-file as a value.
What am I doing wrong?
Try to check your configuration, in particular if you have in the application.yml or application.properties the following:
spring.servlet.multipart.enabled=true
spring.servlet.multipart.location=${java.io.tmpdir}
And also in your pom.xml or build.gradle the dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.1</version>
</dependency>
You can get some inspiration from this tutorial: https://www.baeldung.com/spring-file-upload

Cannot send http post request to springboot

When I send an HTTP post request to spring boot rest API from my angular application, request is failing with below error
Browser Error
HTTP Status 415 – Unsupported Media Type
Type Status Report
Description: The origin server is refusing to service the request because the payload is in a format
not supported by this method on the target resource
Spring boot console error
java.lang.IllegalArgumentException: No converter found for return value of type: class java.util.LinkedHashMap
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:187) ~[spring-webmvc-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:203) ~[spring-webmvc-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
.......
What I have tried so far
As this solution mentioned, i have added the necessary headers to the request from angular end
this.http.post(ipUrl, args, { headers: new HttpHeaders({'Content-Type': 'application/json', 'Accept': 'application/json', 'Access-Control-Allow-Headers': 'Content-Type'})});
As this answer, I have added getters/setters to the Model objects
I want to know where i went wrong and how to resolve this issue?
UPDATE
Springboot Rest Controller method
#PostMapping("/login")
public #ResponseBody ResponseWrapper<WebUser> login(#RequestBody LoginData loginData){
try {
return loginService.loginProcess(loginData);
}
catch (Exception ex){
ProgrammerAlert.printStackTrace(ex);
return new ResponseWrapper<>(ResponseWrapper.ERROR, ex.getMessage());
}
}
Could you write your controller in this way. and see if it responds.
#ResponseBody
#RequestMapping(value = "/login",
method = RequestMethod.POST)
public ResponseWrapper<WebUser> login(...){
.
.
.
}
Is there a reason that you do not want to use RequestMapping ?
Is there any reasons not to add produces and consumes properties?
#PostMapping("/login", produces = MediaType.APPLICATION_JSON_UTF8, consumes = MediaType.APPLICATION_JSON_UTF8)
public #ResponseBody ResponseWrapper<WebUser> login(#RequestBody LoginData loginData){
try {
return loginService.loginProcess(loginData);
}
catch (Exception ex){
ProgrammerAlert.printStackTrace(ex);
return new ResponseWrapper<>(ResponseWrapper.ERROR, ex.getMessage());
}
}
or,
Did you add any JSON message converter, like jackson? Check your application has below dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
your return object should be converted to JSON properly. Add Jackson to you pom (separately from starter web) and retry.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.2</version>
</dependency>
As per your recent edit, you're now getting 406 Not Acceptable, to fix this error, keep the media type of your Spring boot application's response same as the Accept header of your client. Try the following.
Change the value of produces to MediaType.APPLICATION_JSON as you have accept header in client as "application/json". Also please note:
APPLICATION_JSON_UTF8 is deprecated in favor of APPLICATION_JSON
Reference: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/http/MediaType.html
For those who are facing a similar issue, you can also check if there is any typo in Accept header as I often face this problem.
I also came across the same issue, I guess the answer of this question is very clear
HTTP Status 415 – Unsupported Media Type
while sending the request make the content type json instead of text

Get better logging on Jackson parsing error

I am working on a REST application built with Jackson-2.2.3.
Here is the Dependency:
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.2.3</version>
</dependency>
I have a simple endpoint to create a User as below:
#POST
#Path(value = "/addUser")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response createUser(User user) {
...
}
As this endpoint consumes JSON, when api users send JSON Jackson will desearilize to User object.
If user invoke the endpoint with faulty JSON like, missing a property or bad structure. I want to log the fault JSON as a string and ERROR.
How can I achieve that?
I tried using Filters but didn't work.
Consider handling the JsonParseException:
Exception type for parsing problems, used when non-well-formed content (content that does not conform to JSON syntax as per specification) is encountered.
To achieve it, you could use an ExceptionMapper:
#Slf4j
#Provider
public class JsonParseExceptionMapper implements ExceptionMapper<JsonParseException> {
#Override
public Response toResponse(JsonParseException exception) {
log.error("Cannot parse JSON", exception);
return Response.status(Response.Status.BAD_REQUEST)
.entity("Cannot parse JSON")
.type(MediaType.TEXT_PLAIN)
.build();
}
}
For logging purposes, you may also be interested in getting some details from JsonLocation using exception.getLocation().
To register the exception mapper in Jersey, refer to this answer.

Restful web service 415

#RestController
#RequestMapping(value="/uri",produces = "application/json",
consumes="application/json")
public class VisitorService {
VisitorDAO vis=new VisitorDAO();
#RequestMapping(value = "/ex" ,method = RequestMethod.POST)
public String showDetails(#RequestBody VisitorDTO visitor){
vis.addVisitorEntry(visitor);
return "success"+visitor;
}}
Above is my rest service.
whenever I hit a post using the URL with the below JSON,
{
"phoneNumber" : 188892,
"name" : "kikiki" ,
"email" : "loa#gmail.com",
"purpose" : "Business",
"hostName" : "sjs S Murthy"
}
im getting HTTP Status 415 – Unsupported Media Type.
why would that be?
Check that you have set the #EnableWebMvc annotation in a #Configuration class.
Also, try adding the following dependencies to your pom.xml (if not using Maven, just add them to your classpath however you prefer).
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson-version}</version> // 2.4.3
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-version}</version> // 2.4.3
</dependency>
Spring uses Jackson and Jackson-databind to parse the request's JSON body into a Java Object.

Java Spring Restcontroller Post

I need help creating a POST request to my Java Spring Restcontroller.
This is my controller -
#RestController
#RequestMapping("hedgesimulator/")
public class HedgeSimulatorController {
#RequestMapping(value = "hedgesim/", method = RequestMethod.POST)
#ResponseBody
public HedgeSimulatorLog putHedgeSimulation(
#RequestBody HedgeSimulatorLog hedgeSimulatorLog) {
System.out.println(hedgeSimulatorLog.toJsonString());
return hedgeSimulatorLog;
}
}
I am using Chrome's "Advanced Rest Client" Plugin to POST my request to my URL (I am sure my localhost is running properly, etc.)
What do I need to add to my header?
I receive an error for "HTTP 400 - Status report: The request sent by the client was syntactically incorrect"
Please help!
To pass an object to controller you must configure HttpMessageConverter which helds serialization and deserealization of this object. For example, if you want to pass an object to controller as JSON, set a MappingJackson2HttpMessageConverter as parameter in your mvc declaration in spring config file.
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
If http message converter configured properly, maybe request was improperly formed.
#RequestMapping(value = "/hedgesim/", method = RequestMethod.POST)
Try with following, hope you might resolve the issue:
Since you are using #RestController annotation, so no need to use #ResponseBody annotation again, which is redundant.
If you are using spring boot, then make sure you have added the below dependency .
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
If the project is not spring boot, then add dependency for jackson : com.fasterxml.jackson.databind.ObjectMapper
Just to make sure the request body is correct, what you can do is, execute request method first, get the JSON response, pass the same JSON for POST, so this might avoid some typo/human error while creating JSON data.
Hope, it helps.
You can do the following checks.
Validate the request body you are sending through some online tool like
JSonLint.
Check whether MappingJackson2HttpMessageConverter is registered or not. By default, Spring registers this converter if you have the jar in the classpath.
No need to use #ResponseBody if you are using #RestController. So remove it.
For a complete example on creating and consuming REST Service using Spring 4.0, you can visit Techno Spots.

Categories