How to give two representations of dto based on http parameter? - java

I'm trying to write GET which will return response with basic or full set of parameters.
For example. Request to this url
localhost:8080/resource?&outputSchema=basic
Should return
{
"total": 5
}
But this request
localhost:8080/resource?&outputSchema=extended
Should return more data
{
"total": 5,
"name": "John"
}
How can one send different response in spring based on request parameter?

Actually I have found an answer. For #RequestMapping one should use params parameter to filter by desired parameter value.
For example one endpoint would look like this
#RequestMapping(method = RequestMethod.GET, params = "outputSchema=basic", produces = {"application/json"})
public #ResponseBody MyResponse1 findSomeResource(
#RequestParam(value = "outputSchema", required = true) String outputSchema) {
return new MyResponse1();
}
and for the second one
#RequestMapping(method = RequestMethod.GET, params = "outputSchema=extended", produces = {"application/json"})
public String test() {
return "Different response";
}

Related

Return XML or JSON from a REST controller based on request parameters

This is my controller:
#PostMapping(value = "/endpoint", produces = { APPLICATION_JSON_VALUE, APPLICATION_XML_VALUE})
#ResponseBody
public Result generateResult(#Valid #RequestBody Request request) throws JsonProcessingException {
Result result = new Result();
// some code here
return result;
}
and this is my Request class:
#Data
#NoArgsConstructor
public class Request {
#NotNull
private String name;
private String type = "application/json";
}
the controller produces the correct output based on the Accept header in the request sent by the client. However, I want to send no Accept header and only send the following request:
{
"name": "my name",
"type": "application/xml"
}
Then based on the type the correct format should be output. I tried to add HttpServletResponse response to the parameter list of the controller method and then set the content type like this:
response.setHeader(CONTENT_TYPE, request.geType());
but it always returns json. any idea what else I should do?
I think a standard Spring's ResponseEntity builder give you all needed variety:
return ResponseEntity
.ok(//any object for json structure)
.headers(//any header)
.build();
Instead .ok() you can you any other method (that's http status code)
or
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set("MyHeader", "MyValue");
return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.OK);
based on the comments I post this answer which worked for me. I changed my controller method like this:
#PostMapping(value = "/endpoint", produces = { APPLICATION_JSON_VALUE,
APPLICATION_XML_VALUE})
#ResponseBody
public ResponseEntity<Result> generateResult(#Valid #RequestBody Request request)
throws JsonProcessingException {
Result result = new Result();
// some code here
return ResponseEntity.accepted()
.headers(headers)
.body(result);
}

Get values from received html body

I want to get the body values from received html request body using Spring boot:
#PostMapping(value = "/v1/notification")
public ResponseEntity<String> handleNotifications(
#RequestParam(value = "uniqueid", required = false)) String uniqueidValue,
#RequestParam(value = "type", required = false)) String statusValue) {
// Get values from html body
return new ResponseEntity<>(HttpStatus.OK);
}
For example when I receive into the notification body:
some_key=some_value&sec_key=sec_value
I would like to parse the values. How I can implement this?
You can take the key value pair request with using Map and #RequestBody as below:
#PostMapping(value = "/v1/notification")
public ResponseEntity handleNotifications(#RequestBody Map<String,String> keyValuePairs) {
// here you can use keyValuePairs
// you can process some specific key like
String value = keyValuePairs.get("someSpecificKey");
return ResponseEntity.ok(value);
}
Here I attach example postman request :

Swagger not picking methods with empty value

I am using swagger to document my rest apis.
An example:
#RequestMapping(value = "/abc/api/fruit", produces = "application/json")
#Controller
#Api(value = "Fruit", description = "api for fruits", produces = "application/json")
public class FruitResource {
#RequestMapping(method = RequestMethod.GET, value = "")
#ResponseBody
#ApiOperation(httpMethod = "GET", value = "Resource to get fruits", produces = "application/json", notes = "get fruits", response=Fruit.class)
public ResponseEntity<Fruit> getFruits() throws Exception {
return new ResponseEntity<Fruit>(someServiceCallToGetFruits(), HttpStatus.OK);
}
}
As seen above, the value in RequestMapping above the method is empty ("").
Because of this, this class and the method is not getting picked up by swagger.
But when I change the RequestMapping line above method to as below:
#RequestMapping(method = RequestMethod.GET, value = "/")
It starts working.
Is this a bug ? How can I make swagger to work with "" path values. I do not want to put "/" above all such methods.
There's no need to explicitly specify empty value if you don't want to add extend the API path for the particular method. Instead, the following annotation could be used:
#RequestMapping(method = RequestMethod.GET)
Or even
#GetMapping()

How to get JSON as Response in Spring MVC?

I am trying to return response as JSON. After searching I found solution to add headers = "Accept=application/json" in RequestMapping. But still it is not working .
It is throwing error HTTP Status 406 "The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers."
Here is my controller code :
#RestController
public class EmployeeController {
private EmployeeService employeeService;
#Autowired(required = true)
#Qualifier(value = "employeeService")
public void setEmployeeService(EmployeeService employeeService){
this.employeeService = employeeService;
}
#RequestMapping(value = "/test",method = RequestMethod.GET)
public String test(){
return "{\"name\":\"xyz\"}";
}
#RequestMapping(value = "/employees",method = RequestMethod.GET,headers = "Accept=application/json")
public List<Employee> listEmployees(){
List<Employee> employees = this.employeeService.getEmployees();
return employees;
}
}
Where am I doing wrong?
The simple way to generate JSON, XML response is #ResponseBody annotation.
#RequestMapping(value =" /jsonPostSingle", method = RequestMethod.GET)
#ResponseBody
public PostModel generateJSONPostsingle(#ModelAttribute("postModel") PostModel postModel) {
if(postModel.getPostId() == 1) {
postModel.setTitle("post title for id 1");
} else {
postModel.setTitle("default post title");
}
return postModel;
}
This way you will be able to map your request to model class using #ModelAttribute.
Follow the complete tutorial Spring MVC : JSON response using #ResponseBody
I understand that you're trying to send a response from GET request of /employees.
if you are using Spring 3.1, try to use
#RequestMapping(value = "/employees",method = RequestMethod.GET, produces = "application/json")
instead of adding headers = "Accept=application/json"
More info:
if you want to specify type of data that will send with a request, you can use consumes attribute
example:
#RequestMapping(value="/foo", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
this will consumes and response with JSON type only
check this link about spring update http://spring.io/blog/2011/06/13/spring-3-1-m2-spring-mvc-enhancements/
Hope it helps

In Spring, Is there a way to return different Content-Type values for the header?

I would like to set the produces = text/plain to produces = application/json when I encounter an error.
#RequestMapping(value = "/v0.1/content/body", method = RequestMethod.GET, produces = "text/plain")
#ResponseBody
public Object getBody(#RequestParam(value = "pageid") final List<String> pageid, #RequestParam(value = "test") final String test) {
if (!UUIDUtil.isValid(pageid)) {
Map map = new HashMap();
map.put("reason", "bad pageId");
map.put("pageId", pageId);
map.put("test", test);
return new ResponseEntity<Object>(map, HttpStatus.BAD_REQUEST);
}
return "hello";
}
The problem with this code is that it doesn't print the error as json when I send an invalid pageId. It gives me a HTTP 406 error Not acceptable, because it expects to produce text/plain but I didn't return a String.
The cleanest way to handle errors is to use #ExceptionHandler:
#ExceptionHandler(EntityNotFoundException.class) //Made up that exception
#ResponseBody
#ResponseStatus(value = HttpStatus.NOT_FOUND)
public ErrorObject handleException(Exception e) {
return new ErrorObject(e.getMessage());
}
Then assuming you've configured your resolvers properly and put the right JSON serialization library in the classpath, the instance of ErrorObject will be returned to the client as a JSON response.
Of course you can set up multiple #ExceptionHandler methods as needed.

Categories