Swagger not picking methods with empty value - java

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()

Related

SpringBoot – add Cache Control Headers in Rest methods

I have a basic SpringBoot 2.0.5.RELEASE app. Using Spring Initializer, JPA, embedded Tomcat, Thymeleaf template engine, and package as an executable JAR
I have created this Rest method:
#GetMapping(path = "/users/notifications", consumes = "application/json", produces = "application/json")
public ResponseEntity<List<UserNotification>> userNotifications(
#RequestHeader(value = "Authorization") String authHeader) {
User user = authUserOnPath("/users/notifications", authHeader);
List<UserNotification> menuAlertNotifications = menuService
.getLast365DaysNotificationsByUser(user);
return ResponseEntity.ok(menuAlertNotifications)
.cacheControl(CacheControl.maxAge(60, TimeUnit.SECONDS));;
}
and I want to add a Cache Control Headers, but I don't know how...
I got a compilation error:
Multiple markers at this line
- The method cacheControl(CacheControl) is undefined for the type
ResponseEntity<List<UserNotification>>
- CacheControl
- cacheControl
I also add this property in application.properties
security.headers.cache=false
When you use ResponseEntity.ok(T body) the return type is ResponseEntity<T> as it is a shortcut method to add data to the body part of the ResponseEntity.
You need the builder object that is created via ResponseEntity.ok() with no param which returns a Builder object. You then add your data yourself on via the body method.
So your code should be like this
#GetMapping(path = "/users/notifications", consumes = "application/json", produces = "application/json")
public ResponseEntity<List<UserNotification>> userNotifications(
#RequestHeader(value = "Authorization") String authHeader) {
User user = authUserOnPath("/users/notifications", authHeader);
List<UserNotification> menuAlertNotifications = menuService
.getLast365DaysNotificationsByUser(user);
return ResponseEntity.ok().cacheControl(CacheControl.maxAge(60, TimeUnit.SECONDS)).body(menuAlertNotifications);
}

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

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";
}

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

How can I throw a 405 for all the HTTP methods that are not defined on my controller in spring boot?

I need to throw a 405 for all the http methods that are not defined in my controller. I am using spring boot is there a generic way to write it so that i do not have to add a method on my controller to read all the HTTP methods currently i do not get any response but it throws a 200 OK. Below is my controller that only has GET and PUT. I want to throw a 405 for all other methods.
#RestController("CardController")
#RequestMapping("/user/v1")
public class CardController {
#Autowired
ICardService iCardService;
#RequestMapping(value = "/{cardHolderId}/cards", produces = "application/json; charset=utf-8", method = RequestMethod.GET)
#ResponseBody
public AllCardsVO getCards(#PathVariable("cardHolderId") final String id) {
return jsonObj;
}
#RequestMapping(value = "/{cardHolderId}/cards/{cardId}", produces = "application/json; charset=utf-8", method = RequestMethod.GET)
#ResponseBody
public CardVO getCard(#PathVariable("cardHolderId") final String cardHolderId,
#PathVariable("cardId") final String cardId){
return jsonObj;
}
#RequestMapping(value = "/{cardHolderId}/cards/{cardId}", produces = "application/json; charset=utf-8", method = RequestMethod.PUT)
#ResponseBody
public CardVO putCard(#PathVariable("cardHolderId") final String cardHolderId,
#PathVariable("cardId") final String cardId, #RequestBody final RequestVO requestVO) {
return jsonObj;
}
This is what I wrote in the controller but it does not work for PATCH.
#RequestMapping(value = "/**", produces = "application/json; charset=utf-8", method = { RequestMethod.OPTIONS,
RequestMethod.DELETE, RequestMethod.PATCH, RequestMethod.POST })
#ResponseBody
public void options(HttpServletResponse response) {
throw new MethodNotAllowedException();
}
Is there a generic way i can do this in spring boot some sort of configuration override or service having this method in every api controller does not seem correct. IF this is the only way how do i get the PATCH working. I am getting a response for PATCH even though i do not have that defined.
ANy help is appreciated.

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