How to validate redundant query parameters with RestEasy? - java

I have service(WildFly 10.1) which looks like that :
#GET
#Path("/retrieve")
public Response getModels(#BeanParam ModelQueryParams queryParams) {
return getModels();
}
With ModelQueryParams:
public class ModelQueryParams{
#QueryParam("offset")
private Long offset;
#QueryParam("limit")
private Long limit;
}
So the user can call endpoint like:
/retrieve?offset=100&limit=4
But how can I validate case when user pass into the query wrong parameter?
/retrieve?offset=100&limit=4&WRONG_PARAMETER=55
Is there the way to validate it somehow?

if you don't have any field or method parameters annotated with #QueryParam, then those extra parameters are not your problem and it's best to deal with only parameters you expect for your resource.
If you still need access to all query parameters, then inject UriInfo with #Context and call it's getQueryParameters() to get a MultivaluedMap of request parameters

Related

Query parameters with postman and Spring

Can someone explain to me why given this controller:
#RestController
#RequestMapping("/gamification")
public class GamificationController {
private static final Logger logger = LoggerFactory.getLogger(GamificationController.class);
#Autowired
private GameServiceImpl gameService;
#GetMapping("/retrieve-stats/?user={userId}")
ResponseEntity<GameStats> getUserStats(#RequestParam("userId") String userId){
logger.debug("UserId is {}", userId);
return ResponseEntity.ok(gameService.retrieveStatsForUser(Long.parseLong(userId)));
}
}
and this pm request
I get a 404 NOT FOUND?
and If I add brackets to the query parameter, I get a 400 BAD REQUEST
You need to remove the /?user={userId} from #GetMapping as well as from the 1st Postman screenshot request and Construct it like the below one.
#GetMapping("/retrieve-stats")
ResponseEntity<GameStats> getUserStats(#RequestParam("userId") String userId){
logger.debug("UserId is {}", userId);
return ResponseEntity.ok(gameService.retrieveStatsForUser(Long.parseLong(userId)));
}
PS: And you don't have to cast it Long.parseLong, you can declare the parameter with the type #RequestParam("userId") Long userId, Spring is smart enough to autobox the variable type based on its type declartion.

Is there a way that I can limit the number of request parameters in my method header in SpringBoot?

If I have a method that has like 10 request parameters and I may not always need all of them
#GetMapping("/whatever")
public ResponseEntity<String> sendSomethingBack(#RequestParam String optionalRequestParam1,
#RequestParam String optionalRequestParam2,
...
#RequestParam String optionalRequestParam10)
So in this header I'd like something that is like
#GetMapping("/whatever")
public ResponseEntity<String> sendSomethingBack(#RequestParam RequestParamBuilder requestParamBuilder)
and then it would just build an object for me with all valid parameters sent through filled out and the rest being null or something
You can have multiple parameters without defining their names by just using a Map:
#GetMapping("/whatever")
public ResponseEntity<String> sendSomethingBack(#RequestParam Map<String, Object> params) {
log.info("Params: {}", params.entrySet();
}
How to make the call:
curl --location --request GET 'http://localhost:8080/whatever?integer=45&string="some text"&boolean=true'
Output:
Params: [integer=45, string="some text", boolean=true]
If you wanted the parameters to be passed into an object, you can use a POJO as you were but remove the #RequestParam notation:
#GetMapping("/whatever")
public ResponseEntity<String> sendSomethingBack(RequestParamBuilder requestParamBuilder)
Then create a class for RequestParamBuilder. You can mark the fields inside the POJO as #NotNull etc to handle validation and build out the object with only the params that were included in the request, but the POJO must be annotated with #Valid if you wish for spring to validate it this way:
#GetMapping("/whatever")
public ResponseEntity<String> sendSomethingBack(#Valid RequestParamBuilder requestParamBuilder)

How to map a request in Spring MVC to a Java Object

I'm new to Spring, and since Spring provides many ways to map an HTTP request to Java objects, I'm hoping someone could advice me how to resolve this:
I have a client that sends a request having
ContentType: application/x-www-form-urlencoded
Some of the request parmeters have names such as
"form_data[orderStatus]", "form_data[orderNumber]", etc'
I have no control over this client!
I have a java class (#Component) called MyOrder which looks as follows:
#component
#Scope("prototpe")
public class MyOrder {
private String orderStatus;
private String orderNumber;
//etc'
public void setOrderStatus(String orderStatus) {
this.orderStatus = orderStatus;
}
//public setter for all other properties, as the above
}
What is the simplest way to create an instance of MyOrder
populated with all values of all "form_data[]", so that I can have a controller method having a signature that includes a MyOrder parameter, such as:
public ModelAndView saveNewOrder( #RequestParam("foo") String foo,
#ModelAttribute("myOrder") MyOrder anOrder) {
//... impl'n here
}
The best solution I could think of was to use a Web Filter which would flaten request params names such as "form_data[attrib1]" to "attrib1", and then Spring would do all the work of populating the MyOrder instance.
One disadvantage of this is that the request may have both "form_data[attrib1]" and "attrib1" parameters. For example:
form_data[orderStatus]=ok
orderStatus=fail
In this case i want MyOrder.orderStatus to have the value "ok".
Any good way of utilizing Spring create MyOrder from the request?
As an alternative, that does not use the class MyOrder, is there a way to have Spring map all the form_data[] parameters and their values to a map, so that i can have the controller method below?
public ModelAndView saveNewOrder( #RequestParam("foo") String foo,
<some annotation> #Map<String,String> formFieldsOfAnOrder) {
//... impl'n here
orderStatus = formFieldsOfAnOrder.get("orderStatus");
//or at least:
orderStatus = formFieldsOfAnOrder.get("form_data[orderStatus]");
}

Injection of HttpServletRequest in Jersey POST handler

Consider this case:-
I am injecting HttpServletRequest in a Rest Service like
#Context
HttpServletRequest request;
And use it in a method like:-
#GET
#Path("/simple")
public Response handleSimple() {
System.out.println(request.getParameter("myname"));
return Response.status(200).entity("hello.....").build();
}
This works fine but when I try to send it through POST method and replace the #GET by #POST annotation, I get the parameter value null.
Please suggest me where I am mistaking.
You do not need to get your parameters etc out of the request. The JAX-RS impl. handles that for you.
You have to use the parameter annotations to map your parameters to method parameters. Casting converting etc. is done automaticly.
Here your method using three differnt ways to map your parameter:
// As Pathparameter
#POST
#Path("/simple/{myname}")
public Response handleSimple(#PathParam("myname") String myName) {
System.out.println(myName);
return Response.status(200).entity("hello.....").build();
}
// As query parameter
#POST
#Path("/simple")
public Response handleSimple(#QueryParam("myname") String myName) {
System.out.println(myName);
return Response.status(200).entity("hello.....").build();
}
// As form parameter
#POST
#Path("/simple")
public Response handleSimple(#FormParam("myname") String myName) {
System.out.println(myName);
return Response.status(200).entity("hello.....").build();
}
Documentation about JAX-RS Annotations from Jersey you can find here:
https://jersey.java.net/documentation/latest/jaxrs-resources.html

Extracting parameters from URL with POST method

I have something like this :
#RestController
#RequestMapping("/prop")
public class PropController {
#RequestMapping(method = RequestMethod.POST)
public Prop getProp(#ModelAttribute PropForm propForm) {
//calling methods and stuff using propForm
}
}
My PropForm class :
#Data
public class PropForm {
private String att1;
private String att2;
private String att3;
}
Now I am calling this URL :
http://localhost:8080/prop?att1=blabla&att2=blob&att3=test
I want to extract the parameters from the URL and put them in my propForm.
I've tried replacing #ModelAttribute by #RequestBody and then by #RequestParam. It's still not working, I always get a NullPointerException when running the application.
Please, note that I need to use POST method. I already have it working using GET method
FIRST Make sure you have getters and setters in your PropForm class...
Then, you need to put into your model the Form entity:
model.put("NAME", propForm);
And declare method like this:
#RequestMapping(method = RequestMethod.POST)
public Prop getProp(
#ModelAttribute PropForm propForm
#Valid #ModelAttribute("NAME") PropForm propForm)
// ^ you're missing the name!
{
// do your stuff....
return (Prop) propForm;
}
I think you controller and mapping is ok.
But the problem is you are expecting a post request in the mapping, and you are calling
http://localhost:8080/prop?att1=blabla&att2=blob&att3=test
Now this will generate a GET request Not Post. You cannot send a post request using only url.
If you cant use a form for sending the request then you need to use any 3rd party to generate a POST request
like you can use jquery $.post()
And also att1 att2 will not help unless you bind the object with the model attribute.

Categories