In my controller I have a ethod annotated by GetMapping and I want to validate the path variable. I tested the #max and #min. they were ok. but the thing is when I want to check when no path variable is not passed, I get 404 error code. meaning that i want to test the case like:
http://localhost:9090/api/mancala-game/last-state/
where there is nothing after the last /.
I want to get the exception in my ExceptionHandler class.
any ideas?
thank you
You should send path variable , in the url it self otherwise you will throw 404 error .
when your are not sending path variable it will be a different API:
in your case : http://localhost:9090/api/mancala-game/last-state/
and this url is not pointing to any handling method in your controller, So you will get 404 error.
I think http://localhost:9090/api/mancala-game/last-state/ and
http://localhost:9090/api/mancala-game/last-state/{key} is two api.
you can create /last-state and /last-state/{key}
What you want to do is add a wildcard ** at the end of the REST endpoint api/mancala-game/last-state/ at the place where you call the antMatchers() method for this REST endpoint. For example:
.authorizeRequests().antMatchers(HttpMethod.GET, "api/mancala-game/last-state/**").permitAll() //Other antMatchers after this..
Related
Does Spring throw HttpRequestMethodNotSupportedException when a request body is not valid and #Valid (or #Validated) is used? I really expected MethodArgumentNotValidException.
Details: I have a small REST server built on Spring-Boot version 2.2.4. One of the methods looks like this:
#PostMapping("/yapp")
public Yapp kickYapp(#Validated #RequestBody YappDescriptor yappDescriptor) {
logger.debug("kickYapp descriptor {}", yappDescriptor);
doWork(yappDescriptor);
}
The YappDescriptor has annotations like "required" but nothing for valid values, ranges, etc. When I POST a well-formed JSON object with values for all the required fields as defined in the YappDescriptor POJO, the Spring controller method is found and invoked as expected.
I tried a couple error scenarios:
1) If I POST a well-formed JSON object that has only null values for the expected fields, the method is found and entered as expected.
2) If I POST a well-formed JSON object with a key that does not match any of the POJO's fields, the method is NOT found and entered. In watching class org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler I see the exception is HttpRequestMethodNotSupportedException and the server answers 405 "Request method 'POST' not supported".
In this controller class, kickYapp is the only POST-mapped method at the specified path, so I think that answer is pretty confusing. Altho I'm definitely sending a bad request (unexpected data), I am surprised my POST-mapped method is not found and invoked.
This post Validating if request body in HTTP POST request is null in Spring Boot controller suggests I should be seeing HttpMessageNotReadableException which would be helpful, but I never get that exception.
Many other questions on SO seem to be about enabling validation of request bodies, like Spring 4.1.7 validate request body , but I seem to be past that.
Thanks in advance for helping me understand this behavior and maybe improve the server to help my users discover their errors more easily (which saves me time :). Thought I could maybe extend that method to accept a BindingResult parameter and report errors that way, but that's a non-starter if the controller method is never entered.
Update to respond to comments: yes I could have used #Valid. In my tests annotation #javax.validation.Valid and #org.springframework.validation.annotation.Validated have the same effect, both turned on validation of the RequestBody parameter.
why not use #Valid?
like so:
public ResponseEntity<SalaryDto> update(#Valid #RequestBody SalaryDto subject)
and don't forget to use javax.validation validation annotations in your request body object
How can I get request url in spring expression language?
This is my piece of code from spring security configuration:
.antMatchers("/users/location/**").access("principal.locations.contains('locationIdFromUrl')")
My expression works but I don't know how get url variable after /location.
I need this variable to pass it into contains method.
The URL parameters cannot be accessed at Config Class, you can use filters to perform this task logically.
Pseudo code
.addFilterBefore(new DeviceResolverRequestFilter(), LocationAccessFilter.class)
Where LocationAccessFilter contains the logic of location access.
Ok, I solved my proble.
antMatchers("/users/location/{id}/**").access("principal.locations.contains(#id)")
I have seen this answer
but it does not help my case.
I have a class that implements an HttpServlet. Now I want to place a URL inside it so that it has the following pattern: resource/identifier/resource.
For example, I want to make this REST call: http://example.com/owners/1234/dogs
I tried to place a URL like this in the servlet: http://example.com/owners/*/dogs, but the call never reached the servlet and was not handled.
If I understood well you want your servlet to be mapped to something like /owners/*/dogs.
Well, unfortunately Servlets can only use wildcards at the beginning or end of the mapping. So you would have to map it to /owners/* and then using request.getPathInfo() parse the rest of the url to extract the path info.
Your best options are to use the standard JAXRS or Spring MVC, both of which support path variables.
I am using #ParamValue annotation in my controller (Spring MVC).
Say My valid URL's are:
www.temp.com/test/a,
www.temp.com/test/b and
www.temp.com/test/c
So, my RequestMapping is:
#RequestMapping(value = "/test/{value}", method = RequestMethod.GET)
Now, my problem is that if anyone types a wrong URL like this :
www.temp.com/test/youarebroken
then I have to manually handle such a case in my controller to show 404 or not found.
Isn't there something inbuilt that sends a "not found or 404" notification to server that I can use directly ?
The simplest solution is to define a custom exception handler and to throw the custom exception when a validation fails within your controller. That would require that you manage the conditions manually as you stated you do not want to do.
A different solution is to use a global exception handler and define it to deal with the HTTP errors that are handled by Spring built-in.
In this link you can see both approaches: http://www.journaldev.com/2651/spring-mvc-exception-handling-exceptionhandler-controlleradvice-handlerexceptionresolver-json-response-example
However, from your question I understand you would like to return automatically an exception when certain condition in your param value does not meet, and you do not want to validate this manually within your controller. For this, you can add custom validation for an specific class and then set #Valid before the #ParamValue.
You can check this link for DataBinding http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html
And this link for specific validation on param attributes: Spring Web MVC - validate individual request params
So, in plain a solution would be to define a custom validator that throws a custom exception when fails. To set #Valid for the parameters (check link) and to adjust the custom exception to handle HTTP errors (e.g. HttpStatus.NOT_FOUND).
You can use a regex in your #RequestMapping URL. Example:
#RequestMapping(value = "/test/{value:[a-z]}", method = RequestMethod.GET)
I am using Java and Jersey for my REST web services. I want to have a put method that takes just one integer value. From this integer value I can then use business logic to update my database. Usually I am passing a custom DTO from my PUT as they often contain more than one piece of information. It seems a bit wasteful creating a custom DTO for just one value. Is it possible to pass this variable as a #PathParam with a PUT
I have tried
#PUT
#Path("apple/{pearId}")
public void doStuff(#PathParam("pearId") Integer pearId) {...}
but this does not work if I pass in
http://myurl/apple/123
I tried using REST client to PUT this but end up with a HTTP Status 403
Can I pass a variable as a PUT #PathParam?
Thanks
UPDATE: more details on error
The error is from REST Client
HTTP Status 403 -
type Status report
message
descriptionAccess to the specified resource () has been forbidden
I will add logging now to see if I actually get into the method
You can definitely use #PathParam with a PUT. HTTP 403 means Forbidden. This error is probably not coming from Jersey. Where is that error coming from? Does your code throw that error?