I have a front end that gives me a query and a type.
The types are JSON and XML. How can I create and send the download file to the ajax post?
#RestController
public class RestCtrl {
#Autowired
JdbcTemplate jdbcTemplate;
#GetMapping("/getData")
List<Map<String, Object>> getData(#RequestParam String type, #RequestParam String query) {
System.out.println(type + " " + query);
List<Map<String, Object>> data = jdbcTemplate.queryForList(query);
if(type.equals("JSON")) {
}
else if (type.equals("XML")){
}
}
}
Basically the XML would have the column names in <> for example <TITLE>This is a title</TITLE> I this is is SOAP, right?
Something like this: https://flowgear-wpengine.netdna-ssl.com/wp-content/uploads/2016/12/XML-vs-JSON1.png
Edit:nothing like that
From the Spring Web documentation:
https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-requestmapping-produces
You can narrow the request mapping based on the Accept request header
and the list of content types that a controller method produces.
https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-requestmapping-consumes
You can narrow the request mapping based on the Content-Type of the
request.
Request
Client application can control POST request data mime format (XML, JSON) using Content-Type HTTP header. For example:
Content-Type: application/json will define that request data is provided in the JSON format
Content-Type: text/xml will define that request data is provided in the XML format
The server-side application can control what mime format it can process using consumes attribute of the #PostMapping annotation:
#PostMapping(path = "/pets", consumes = "application/json")
public void addPet(#RequestBody Pet pet) {
// ...
}
If 'Content-Type' header value doesn't match the consumer attribute value, Spring will produce an exception that it can process input data.
Response
Client application can control response data mime format (XML, JSON) using Accept HTTP header. For example:
Accept: application/json will define that the client can accept data is provided in the JSON format
Accept: text/xml will define that the client can accept data in the XML format
The server-side application can control what mime format it can process using produces attribute of the #RequestMapping, #GetMapping and other annotations:
#GetMapping(path = "/pets/{petId}", produces = "application/json;charset=UTF-8")
#ResponseBody
public Pet getPet(#PathVariable String petId) {
// ...
}
If 'Accept' header value doesn't match the produces attribute value, Spring will produce an exception that it can process input data.
Spring defined useful constants for the widely used mime-types:
MediaType.APPLICATION_XML_VALUE
MediaType.APPLICATION_JSON_VALUE
For the full list of values, check documentation: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/MediaType.html
consumes and produces are multi-valued attributes. Multiple values can be specified as a list:
#GetMapping(path = "/pets/{petId}", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
You don't have to worry about the returned media type, spring will handle that for you, you need to add 'produces' to your rest endpoint
#RequestMapping(value="getData", method = RequestMethod.GET , produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
List<Map<String, Object>> getData(#RequestParam String type, #RequestParam String query) {
you may need to add jackson dataformat for an implicit POJO to XML mapping
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
Related
I have a controller that accepts multipart/form-data.
Below is controller declaration:
#PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> upload(#RequestPart(value = "data") Data data, #RequestPart(value = "file") MultipartFile file)
Data can be either application/json or text/plain and we need to support both the content types for data.
However the code gives error when data content type is text/plain
Exception occurred - org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'text/plain' not supported at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:225)
Is it possible to support text/plain for data #RequestPart?
The code is as follow.Where I am checking the content type extracted from the header then I want to write the code and return the response from the same method.
#POST
#Produces(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_XML)
public Response addMessage(Message message , #Context UriInfo uriInfo,
#HeaderParam ("content-type") String contentType) throws
URISyntaxException
{
//Conditional check based on the content type.
if(contentType.equals("application/json")) {
return json;
}else {
return xml;
}
}
How a rest API will return both Json and XML response depending on the input header?
First , your usage of multiple #Produces on same method is incorrect. A String[] can be specified for all types that you wish to produce with #Produces , Annotation Type Produces
And for your main question, I agree with vlumi's comment that ,
You should just return the Response built with the object to return,
and let JAX-RS handle the serialization into XML or JSON, depending on
which the client expects/prefers
i.e. let the framework do it for you depending on Accept header as specified by client as Raj has already mentioned in comments,
You have to pass the request header Accept: application/json or
application/xml
Jersey Multiple Produces
I'm working on a Spring MVC application and have a client that I have no control over. This client is POSTing JSON data but transmitting a application/x-www-form-urlencoded header. Spring naturally trusts this header and tries to receive the data but can't because its JSON. Has anyone had experience overriding the header that Spring receives or just specifying exactly what type of data is coming, regardless of the headers?
You can do two things;
Change the client to send the Content-Type:
application/json header
Write a Servlet Filter or Spring Interceptor which is on top of the Spring Controller and checks for the header Content-Type. If it is not application/json then it changes it to application/json.
Why don't you write a separate controller to handle application/x-www-form-urlencoded requests. If the request is a valid JSON, then you can parse it and forward it to to appropriate service.
This way you can also handle a case in future where you get request of same type which is not a valid JSON.
#RequestMapping(value = "/handleURLEncoded", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public #ResponseBody Object handleURLEncoded(HttpEntity<String> httpEntity) {
String json = httpEntity.getBody();
//now you have your request as a String
//you can manipulate it in any way
if(isJSONValid(json)) {
JSONObject jsonObj = new JSONObject(json);
//forward request or call service directly from here
//...
}
//other cases where it's not a valid JSON
}
Note: isJSONValid() method copied from this answer
I am using Spring MVC on a J2EE Web application.
I have created a method that bounds the request body to a model like the above
#RequestMapping(value = "/", method = RequestMethod.POST, produces = "application/json")
public AModel createEntity(#Valid #ModelAttribute MyInsertForm myInsertForm) {
// coding..
}
Everything are working great and when i include a property of type MultipartFile in the MyEntityForm, then i have to make the request with content type "multipart/form-data".
Also, everything are working great with this scenario too.
The problem i am facing is that i would like to have the MultipartFile property as optional.
When a client request include a file my method works great but when a client request does not include a file spring throws a
HTTP Status 500 - Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is org.apache.commons.fileupload.FileUploadException: Stream ended unexpectedly
Is there any way to solve this issue without creating two methods on my controller (one with a MultipartFile and another without)?
I had the same issue and just adding the required=false worked for me; because, I don't send a file all the time. Please find the sample code below,
#RequestMapping(value = "/", method = RequestMethod.POST, produces = "application/json")
public AModel createEntity(#Valid #ModelAttribute MyInsertForm myInsertForm, #RequestParam(value ="file", required=false) MultipartFile file) {
// coding..
}
Give a try by adding
(required=false)
to multipart property in method signature.
When you wish to send one or more files using HTTP, you have to use multipart request. This means that the body of the request will be like the above,
-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name="text"
text default
-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name="file1"; filename="a.txt"
Content-Type: text/plain
Content of a.txt.
-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name="file2"; filename="a.html"
Content-Type: text/html
When you wish to send only data (and not files) you can send them as json, key-value pairs etc.
Spring framework uses the #ModelAttribute annotation when you wish to map a multipart request to an object.
When you have a normal key-value request, you use the #RequestBody annotation.
Thus, you can't have the MultipartFile optional, because you have to use different annotations. Using two different methods, one per request type, solves the issue. Example,
#RequestMapping(value = "/withFile", method = RequestMethod.POST, produces = "application/json")
public ReturnModel updateFile(#ModelAttribute RequestModel rm) {
// do something.
}
#RequestMapping(value = "/noFile", method = RequestMethod.PUT, produces = "application/json")
public ReturnModel updateJson(#RequestBody RequestModel rm) {
// do something else.
}
Can you point me to article or explain me how to declare RESTful web service which consumes JSON request and based on parameter inside JSON produces output in different formats, meaning customer can get output in JSON but in pdf also. I'm using Java and RestEasy on JBoss 5.1.
You could map the request on a method returning a RestEasy Response object, using a ResponseBuilder to build your response, setting dynamically the mime type of the response depending on a parameter in your JSON.
#POST
#Path("/foo")
#Consumes("application/json")
public Response fooService(MyObject obj) {
MyResponseEntity entity = MyObjectService.retrieveSomethingFrom(obj);
return Response.status(200).entity(entity).type(obj.isXml() ? "text/xml" : "application/json").build();
}
This way if your MyObject domain object that represent incoming JSON has a parameter xml set to true, then the Response object is parameterized to produce text/xml otherwise it produces application/json. RestEasy should do the rest.
You can use this way
#Path("/")
public class Test {
#Path("/test")
#POST
#Consumes("application/json")
#Produces("text/plain")
public Response addOrderJSON(OrderDetails details) {...}
}