how to accept a future date in a param request? - java

I would like that in my controller the update service would only accept dates after the current one, I tried to use the future annotation but it doesn't work ... could you give me a suggestion?
in particular, I would like if the user entered the date 1990-04-01T12: 08: 56Z the service would return 400 because the entered date is not later than the current one, I thought the #Future annotation worked in this sense instead I was wrong and still allows the execution of the service
#PatchMapping(path = "/{id}", produces = "application/json")
public ResponseEntity<Employee> update(#PathVariable(value = "id") Integer id,
#RequestParam(value = "afterdate") #Future #DateTimeFormat(pattern =" yyyy-MM-dd'T'HH:mm:ss'Z'") Date afterdate) { ....

Related

SpringBoot Controller mapping to incorrect method

I have below 2 GET mappings in my controller:
1. #GetMapping("/department/{deptId}/employee/{employeeId}")
public String func1(#PathVariable(value = "deptId", required = true) String deptId,
#PathVariable(value = "employeeId", required = true) String employeeId) { ... }
2. #GetMapping("/department/{deptId}/employee/{employeeId}/workLogs")
public String func2(#PathVariable(value = "deptId", required = true) String deptId,
#PathVariable(value = "employeeId", required = true) String employeeId) { ... }
When I Fire the API as:
GET http://localhost:8080/department/102/employee//workLogs --> Keeping employeeId as blank, this call gets mapped to the first GetMapping (func1) and employeeId is calculated as employeeId = "workLogs".
Hence, There is no exception thrown for missing path variable which was marked as required and call completed with 200 OK.
How to resolve this, so that it maps correctly to func2, and throws an exception for missing required path variable.
When you make a request
http://localhost:8080/department/102/employee/workLogs
This will be interpreted as workLogs being provided as the employeeId.
There's a couple ways to solve the problem.
In func1, throw an exception if employeeId.equals("workLogs")
set employeeId as an Int or Long, so that an exception will be thrown by default when workLogs is attempted to be parsed as an employeeId
But actually, calling http://localhost:8080/department/102/employee//workLogs with the double slash (//) should result in a 404 error. Try using version 5.3.15 of Spring if this isn't the case.

Swagger for java - the required field prevents execution

I am using swagger with the following Maven dependency:
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-jaxrs2</artifactId>
<version>2.0.9</version>
</dependency>
I wrote an API call as follows:
#Operation(
method = "GET",
summary = "Get alerts by Date Range",
extensions = #Extension(name = "x-rest-api", properties = #ExtensionProperty(name = "public", value = "true")),
parameters = {
#Parameter(name = "startDate",
in = ParameterIn.QUERY,
description = "Get alerts from this date. `startDate` should be in GMT and 24 hour Clock",
example = "2020-07-15T15:57:00Z",
schema = #Schema(implementation = ZonedDateTime.class),
required = true),
#Parameter(name = "endDate",
in = ParameterIn.QUERY,
description = "Get alerts to this date. `endDate` should be in GMT and 24 hour Clock",
example = "2020-07-20T15:57:00Z",
required = true)
},
responses = {
#ApiResponse(
responseCode = "200",
description = "A list of alerts",
content = #Content(schema = #Schema(implementation = AlertObject .class))),
#ApiResponse(
responseCode = "401",
description = "Invalid Bearer Token",
content = #Content(schema = #Schema(implementation = ApiException.class))
)
}
)
#GET
#Path("/old")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public AlertObject alertsByDateRange(#NotNull #Valid #QueryParam("startDate") ZonedDateTime startDate,
#NotNull #Valid #QueryParam("endDate") ZonedDateTime endDate) { ... }
The above 2 parameters are both supposed to be required parameters. So I set the required = true. However, once I set them to required, I was no longer able to execute this API call through swagger. When I used Postman to call this function it worked perfectly. However, I can no longer use the swagger UI to test. I don't know why that is? I even tried setting the schema field for one of them (I thought that perhaps swagger needed to know how to validate) but that didn't help. So now, when I fill out those fields, swagger highlights them in red and refuses to execute this API call. When I hover my mouse over the red box, it says "Required field is not provided".
I looked online but I cannot find a good set of examples of how to properly set required parameters in swagger for java, nor could I find an API that describes the nuances of the java version.
So my question is - how do I properly setup required parameters such that they are still executable through the swagger UI?
I figured out the issue.
If you notice in the code above, I declare the same parameter in swagger twice. The first time is:
#Parameter(name = "startDate",
in = ParameterIn.QUERY,
description = "Get alerts from this date. `startDate` should be in GMT and 24 hour Clock",
example = "2020-07-15T15:57:00Z",
schema = #Schema(implementation = ZonedDateTime.class),
required = true),
And the second time is:
#NotNull #Valid #QueryParam("startDate") ZonedDateTime startDate,
When I looked at the yaml, I saw this:
parameters:
- name: startDate
in: query
description: Get historical alerts from this date. `startDate` should be in
GMT and 24 hour Clock
required: true
schema:
type: string
format: date-time
example: 2020-07-15T15:57:00Z
...
- name: startDate
in: query
required: true
schema:
type: string
format: date-time
The parameter appears twice as a result. And you can tell which is which, because the 1st parameter has a description and the second one does not.
(I think the underlying problem is that both are considered required but we are only able to fill out 1 parameter.)
Once I remove the second declaration I was then able to use swagger to test my API calls.

How to share information between Spring controller methods from GET and POST requests?

I'm new to Spring and I want to:
1) when an user visits localhost/admin/users I want the predefined options to apply
2) On localhost/admin/users I have some buttons that perform a POST with four parameters because my boss don't want me to use get (and I think is better to use POST, too)
3) I have a controller method adminUsersPost that manages the POST request, and I want that method to be able to make my browser to reload using the adminUsersGet method, but with the information sent in the POST request.
What I'm getting now in my browser is an alert with a webpage content in some weird encoding, I hope it is correct but I don't know.
#RequestMapping(value = "/admin/users", method = RequestMethod.GET)
public ModelAndView adminUsersGet(
Integer page,
Integer items,
String sorting,
String sortingDirection)
{
// predefined options
Integer pagina = 1;
Integer itemsPorPagina = 10;
String ordenacion = "idUsuario";
String dirOrdenacion = "asc";
// end of predefined options
// Code that I want for it to use POST params from the other method
ModelAndView mv = new ModelAndView("adminUsers");
return mv;
}
#RequestMapping(value = "/admin/users", method = RequestMethod.POST)
public ModelAndView adminUsersPost(
#RequestParam(value = "pagina") Integer pagina,
#RequestParam(value = "itemsPorPagina") Integer itemsPorPagina,
#RequestParam(value = "ordenacion") String ordenacion,
#RequestParam(value = "dirOrdenacion") String dirOrdenacion)
{
// Here I try to pass the POST parameters to the GET method for reloading
// the webpage with the new content
return adminUsersGet(pagina, itemsPorPagina, ordenacion, dirOrdenacion);
}
The pattern POST params-->GET same parameters is a common one. What you need is RedirectAttributes which will store your parameters into the session and redirect to your GET method. Once the GET is hit spring will automatically remove all attributes from the session, thus none of the POST parameters will be displayed in the browser url in the GET method. Have a look here for a complete example and adjust it for your needs.

In Spring MVC, can't bind an input to a date field with a Jackson #JsonFormat

I have an application using Spring MVC that interacts with a REST service. The UI has a typical form input using JSP.
There is an object that I wish to allow the user to modify and persist that includes a date field:
public class TheObject {
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "PST")
private Date myDate;
.
.
.
}
And on the UI this is bound to an input:
<form:input path="myDate"/>
So, in my controller when I post the form and I've entered a proper "yyyy-MM-dd" string in that input box I get null for the field and a binding error. Controller method looks like this
#RequestMapping(value = "thePath", method = RequestMethod.POST)
public String postMyForm( #Valid #ModelAttribute final theObject backingModel, final BindingResult result, final Model model,
final HttpServletRequest request) throws Exception {
//Breakpoint here to check the binding
}
If I look at the BindingResult there I see an error saying the following:
Field error in object 'backingModel' on field 'theDate': rejected value [2016-07-07]; codes [typeMismatch.backingModel.theDate,typeMismatch.theDate,typeMismatch.java.util.Date,typeMismatch];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [backingModel.theDate,theDate];
arguments []; default message [theDate]];
default message [Failed to convert property value of type [java.lang.String] to required type [java.util.Date] for property 'theDate';
nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [#com.fasterxml.jackson.annotation.JsonFormat java.util.Date] for value '2016-07-07'; nested exception is java.lang.IllegalArgumentException]
If I take out the #Valid I get an exception with the same message.
How should I be able to bind this?
If I replace the annotation with #DateTimeFormat(pattern = "yyyy-MM-dd") then binding works fine. But the object needs that Jackson annotation.
So after posting all that I realized I can just add both annotations and it works
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "PST")
#DateTimeFormat(pattern = "yyyy-MM-dd")
private Date myDate;
So I'll post this as the answer in case anyone else comes across this (unless someone thinks what I'm describing above is really bad practice or anything).

how to get valid Date and Time instances using spring and thymeleaf

i am using thymeleaf and spring boot in my project and i need to save date and
time object in mySql database, this is how i have validated my entity class
#NotNull
#Column(name = "sdate")
#DateTimeFormat(iso = ISO.DATE)
private Date sdate; //represents start Date - i am passing 2014-01-01- this works fine.
#NotNull
#Column(name = "stime")
#DateTimeFormat(iso = ISO.TIME)
private Date stime; //represent start time - i am passing 12:10:20.444
when i am trying to get the values from thymleaf form to the controller i cant get a valid class it contain errors. is there something i am doing wrong with the validation part. how can i get a valid input from the form.
public String save(#ModelAttribute("travel") #Valid Travel travel,BindingResult result){
if (result.hasErrors()) {
for (Object element : result.getAllErrors()) {
System.out.println(element.toString());
}
}
error message :
Field error in object 'travel' on field 'stime': rejected value [12:10:20.444]
According to spring document for DateTimeFormat.ISO.TIME, the right format for ISO.TIME is "12:10:20.444+00:00", where the "+00:00" part is the time zone offset (suppose that there is no offset for your time zone).
So you need to reformat your input to include the time zone offset in your time string.

Categories

Resources