Spring: Parameter conditions "loanTitle" not met for actual request parameters - java

Java Spring MVC. I can't open url without a parameter. I found suggestions in Internet(Spring MVC Thymeleaf Error: Parameter conditions not met for actual request parameters, http://www.baeldung.com/spring-requestmapping), but they didn't help me.
#Controller
#RequestMapping("/loans/")
public class LoanController {
#Autowired
LoanDAO loanDAO;
#GetMapping(value= "objectloan", params = {"loanTitle"})
public String index(Model theModel, HttpSession session, #RequestParam(value = "loanTitle", required = false, defaultValue = "") Optional<String> loanTitle)
{
....
}
URL works
http://localhost:8080/college/loans/objectloan?loanTitle=test
URL with error
http://localhost:8080/college/loans/objectloan
Error:
Type Status Report
Message Parameter conditions "loanTitle" not met for actual request parameters:
Description The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).

Since loanTitle might not present in your query url,try to remove params = {"loanTitle"} in your controller method
#GetMapping(value= "objectloan")
public String index(Model theModel, HttpSession session, #RequestParam(value = "loanTitle", required = false, defaultValue = "") Optional<String> loanTitle)
{
....
}

Related

For 400 Bad Request not getting proper error message

Our controller looks like this -
#RestController
#RequestMapping(value="api")
#Validated
public class SampleController {
#RequestMapping(value = {"/test"}, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public void test(
#RequestParam(value = "testCode",required=true) String merchantCode
) throws Exception{
System.out.print("This is Test");
}
}
Here if we do not specify the required parameter "testCode" in our request we get "400 Bad Request", but the message section of the error response remains blank.
Response we are getting -
{"timestamp":1592441286607,"status":400,"error":"Bad Request","message":"","path":"/test"}
But expected is -
{"timestamp":1592441286607,"status":400,"error":"Bad Request","message":"Required String parameter 'testCode' is not present","path":"/test"}
We are using below Spring dependencies -
<spring-boot.version>2.3.0.RELEASE</spring-boot.version>
<spring-framework.version>5.2.6.RELEASE</spring-framework.version>
What I have seen is for this we are getting MissingServletRequestParameterException, but in the exception the message is coming as blank("").
I just updated the bootstrap.yml with server.error.include-message=always. It appears from Spring 2.3.0 the default behavior of Spring has changed. We can refer the following link from more details https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes#changes-to-the-default-error-pages-content
Configuration in application.yml
server:
error:
include-message: always
include-binding-errors: always
include-stacktrace: on_trace_param
include-exception: true

#RequestParam in GET is always null when it's called using HTTPs

I have this method right now:
#RequestMapping(path = "/api2/rep/report_payment_grouped/{startDate}/{endDate}", method = RequestMethod.GET)
public #ResponseBody
ResponseEntity getPaymentsGroupedReport(HttpServletRequest request,
#PathVariable String startDate,
#PathVariable String endDate,
#RequestParam(required = false, value = "requestId") Integer requestId) {
This returns an object Report with two list, fieldsDefs, data, and the requestId received in the original request:
return ResponseEntity
.ok(new Report(fieldDefs, data, requestId));
This is the returned object client side(it's correct):
In the network data:
Now, the exact same request when the service is deployed in my AWS server, requestId is always null:
This is the response:
I have tried manually setting the requestId serverSide and the value is returned correctly in that case. So it's confirmed that requestId parameter is being received as null/empty.
I suspect your service on AWS isn't able to access the database. Have you looked at the error logs?

How to extract a variable value in Spring AOP advise

The authentication method has been integrated with every REST calls in the API. I have been trying to implement an authentication method via Spring AOP so that I can remove all the duplicate code from end-points and have one single advise to look for all public methods in Controllers.
Please check the below my code,
#Aspect
public class EndpointAccessAspect {
/**
* All the request mappings in controllers need to authenticate and validate end-point access
*/
#Before("execution(public * com.xxxx.webapi.controllers.MenuController.getCategory(HttpServletRequest)) && args(request)")
public void checkTokenAccess(HttpServletRequest request){
String re =(String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
System.out.println(" %%%%%%%%%%%%%%%%%%% checkTokenAccess %%%%%%%%%%%%%%%" + re);
}
public void checkEndPointPermission(){
System.out.println(" $$$$$$$$$$$$$$$$$$ checkEndPointPermission &&&&&&&&&&&&&");
}
}
However, I saw Intelij gives error near getCategory(HttpServletRequest)) && args(request) saying can not resolve symbol HttpServletRequest. I need the request to distingues each REST end-points. There are more variables than HttpServletRequest variable in the method but only that variable is needed.
The code is compiling when I test the functionality I noticed it doesn't reach to the advise. Can anybody help me to fix this?
I found this from Spring documentation
Spring doc
any join point (method execution only in Spring AOP) which takes a
single parameter, and where the argument passed at runtime is
Serializable
Does this mean I can not use methods that have multiple parameters?
Controller end-point
#RequestMapping(value = "{menuId}/categories/{categoryId}", method = RequestMethod.GET)
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Successful retrieval of a category requested", response = ProductGroupModel.class),
#ApiResponse(code = 500, message = "Internal server error") })
public ProductGroupModel getCategory(
#ApiParam(name = "menuId", value = "Numeric value for menuId", required = true) #PathVariable(value = "menuId") final String menuId,
#ApiParam(name = "categoryId", value = "Numeric value for categoryId", required = true) #PathVariable(value = "categoryId") final String categoryId,
final HttpServletRequest request) {
The following syntax, resolved the above issue. Basically, I had to modify the code to deal with multiple parameters in the advise.
#Before("execution(public * com.xxxx.webapi.controllers.MenuController.getCategory( HttpServletRequest,..)) && args(request, ..)")
public void checkTokenAccess(HttpServletRequest request){
String re =(String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
System.out.println(" %%%%%%%%%%%%%%%%%%% checkTokenAccess %%%%%%%%%%%%%%%" + re);
}

Bug: Required request body is missing

I'm trying spring framework.
I have RestController and function:
#RequestMapping(value="/changePass", method=RequestMethod.POST)
public Message changePassword(#RequestBody String id, #RequestBody String oldPass,
#RequestBody String newPass){
int index = Integer.parseInt(id);
System.out.println(id+" "+oldPass+" "+newPass);
return userService.changePassword(index, oldPass, newPass);
}
and code angularJS
$scope.changePass = function(){//changePass
$scope.data = {
id: $scope.userId,
oldPass:$scope.currentPassword,
newPass:$scope.newPassword
}
$http.post("http://localhost:8080/user/changePass/", $scope.data).
success(function(data, status, headers, config){
if(date.state){
$scope.msg="Change password seccussful!";
} else {
$scope.msg=date.msg;
}
})
.error(function(data, status, headers, config){
$scope.msg="TOO FAIL";
});
}
and when i run it.
Error Message :
Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public com.csc.mfs.messages.Message com.csc.mfs.controller.UserController.changePassword(java.lang.String,java.lang.String,java.lang.String)
Help me fix it, pls...
Issue is in this code.
#RequestBody String id, #RequestBody String oldPass,
#RequestBody String newPass
You cannot have multiple #RequestBody in same method,as it can bind to a
single object only (the body can be consumed only once).
APPROACH 1:
Remedy to that issue create one object that will capture all the relevant data, and than create the objects you have in the arguments.
One way for you is to have them all embedded in a single JSON as below
{id:"123", oldPass:"abc", newPass:"xyz"}
And have your controller as single parameter as below
public Message changePassword(#RequestBody String jsonStr){
JSONObject jObject = new JSONObject(jsonStr);
.......
}
APPROACH 2:
Create a custom implementation of your own for ArgumentResolver
You can't have request body for the GET method. If you want to pass username and password as part of request body then change RequestMethod type to POST/PUT.
If you want to use GET only then you will have to pass username and password as either path variables or request/query parameters - which is not best practice.
I would recommend changing RequestMethod and pass username & password as request body.

Mapping restful ajax requests to spring

I have this piece of code:
#RequestMapping(value = "/test.json", method = RequestMethod.GET)
#ResponseStatus(HttpStatus.OK)
public #ResponseBody Object[] generateFile(#RequestParam String tipo) {
Object[] variaveis = Variavel.getListVariavelByTipo(tipo);
return variaveis;
}
As far as I know it should take a request to test.json?tipo=H and return the JSON representation of Variavel[], however when I make such request I get:
HTTP Status 406 -
type Status report
message
descriptionThe resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers ()
By using the following function I can get the expected json:
#RequestMapping(value = "/teste.json")
public void testeJson(Model model, #RequestParam String tipo) {
model.addAttribute("data", Variavel.getListVariavelByTipo("H"));
}
What I'm doing wrong?
#RequestBody/#ResponseBody annotations don't use normal view resolvers, they use their own HttpMessageConverters. In order to use these annotations, you should configure these converters in AnnotationMethodHandlerAdapter, as described in the reference (you probably need MappingJacksonHttpMessageConverter).

Categories

Resources