Skip to content

Commit

Permalink
Retrieve bean validation parameter names from Spring MVC / JAX-RS ann…
Browse files Browse the repository at this point in the history
…otations (#105)

Fixes #96
  • Loading branch information
jpraet authored Sep 26, 2024
1 parent 76142da commit af5eb31
Show file tree
Hide file tree
Showing 17 changed files with 410 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,20 @@ public interface Frontend {

@GET
@Path("/beanValidation/queryParameter")
Response beanValidationQueryParameter(@QueryParam("param") @NotNull @Positive Integer param,
@QueryParam("other") @Size(max = 5) String other);
Response beanValidationQueryParameter(@QueryParam("param") @NotNull @Positive Integer p,
@QueryParam("other") @Size(max = 5) String o);

@GET
@Path("/beanValidation/headerParameter")
Response beanValidationHeaderParameter(@HeaderParam("param") @NotNull @Positive Integer param);
Response beanValidationHeaderParameter(@HeaderParam("param") @NotNull @Positive Integer p);

@GET
@Path("/beanValidation/pathParameter/inherited/{param}")
Response beanValidationPathParameterInherited(@PathParam("param") @NotNull @Positive Integer param);
Response beanValidationPathParameterInherited(@PathParam("param") @NotNull @Positive Integer p);

@GET
@Path("/beanValidation/pathParameter/overridden/{param}")
Response beanValidationPathParameterOverridden(@PathParam("param") @NotNull @Positive Integer param);
Response beanValidationPathParameterOverridden(@PathParam("param") @NotNull @Positive Integer p);

@POST
@Path("/beanValidation/body")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,31 +190,31 @@ public Response unmappedFromBackend(@QueryParam("client") Client client) {
}

@Override
public Response beanValidationQueryParameter(Integer param, String other) {
return Response.ok("param: " + param + ", other: " + other).build();
public Response beanValidationQueryParameter(Integer p, String o) {
return Response.ok("param: " + p + ", other: " + o).build();
}

@Override
public Response beanValidationHeaderParameter(Integer param) {
return Response.ok("param: " + param).build();
public Response beanValidationHeaderParameter(Integer p) {
return Response.ok("param: " + p).build();
}

@GET
@Path("/beanValidation/pathParameter/class/{param}")
public Response beanValidationPathParameter(@PathParam("param") @NotNull @Positive Integer param) {
return Response.ok("param: " + param).build();
public Response beanValidationPathParameter(@PathParam("param") @NotNull @Positive Integer p) {
return Response.ok("param: " + p).build();
}

@Override
public Response beanValidationPathParameterInherited(Integer param) {
return Response.ok("param: " + param).build();
public Response beanValidationPathParameterInherited(Integer p) {
return Response.ok("param: " + p).build();
}

@Override
@GET
@Path("/beanValidation/pathParameter/overridden")
public Response beanValidationPathParameterOverridden(@QueryParam("param") @NotNull @Positive Integer param) {
return Response.ok("param: " + param).build();
public Response beanValidationPathParameterOverridden(@QueryParam("param") @NotNull @Positive Integer p) {
return Response.ok("param: " + p).build();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,20 @@ public interface Frontend {

@GET
@Path("/beanValidation/queryParameter")
Response beanValidationQueryParameter(@QueryParam("param") @NotNull @Positive Integer param,
@QueryParam("other") @Size(max = 5) String other);
Response beanValidationQueryParameter(@QueryParam("param") @NotNull @Positive Integer p,
@QueryParam("other") @Size(max = 5) String o);

@GET
@Path("/beanValidation/headerParameter")
Response beanValidationHeaderParameter(@HeaderParam("param") @NotNull @Positive Integer param);
Response beanValidationHeaderParameter(@HeaderParam("param") @NotNull @Positive Integer p);

@GET
@Path("/beanValidation/pathParameter/inherited/{param}")
Response beanValidationPathParameterInherited(@PathParam("param") @NotNull @Positive Integer param);
Response beanValidationPathParameterInherited(@PathParam("param") @NotNull @Positive Integer p);

@GET
@Path("/beanValidation/pathParameter/overridden/{param}")
Response beanValidationPathParameterOverridden(@PathParam("param") @NotNull @Positive Integer param);
Response beanValidationPathParameterOverridden(@PathParam("param") @NotNull @Positive Integer p);

@POST
@Path("/beanValidation/body")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,31 +189,31 @@ public Response unmappedFromBackend(@QueryParam("client") Client client) {
}

@Override
public Response beanValidationQueryParameter(Integer param, String other) {
return Response.ok("param: " + param + ", other: " + other).build();
public Response beanValidationQueryParameter(Integer p, String o) {
return Response.ok("param: " + p + ", other: " + o).build();
}

@Override
public Response beanValidationHeaderParameter(Integer param) {
return Response.ok("header: " + param).build();
public Response beanValidationHeaderParameter(Integer p) {
return Response.ok("header: " + p).build();
}

@GET
@Path("/beanValidation/pathParameter/class/{param}")
public Response beanValidationPathParameter(@PathParam("param") @NotNull @Positive Integer param) {
return Response.ok("param: " + param).build();
public Response beanValidationPathParameter(@PathParam("param") @NotNull @Positive Integer p) {
return Response.ok("param: " + p).build();
}

@Override
public Response beanValidationPathParameterInherited(Integer param) {
return Response.ok("param: " + param).build();
public Response beanValidationPathParameterInherited(Integer p) {
return Response.ok("param: " + p).build();
}

@Override
@GET
@Path("/beanValidation/pathParameter/overridden")
public Response beanValidationPathParameterOverridden(@QueryParam("param") @NotNull @Positive Integer param) {
return Response.ok("param: " + param).build();
public Response beanValidationPathParameterOverridden(@QueryParam("param") @NotNull @Positive Integer p) {
return Response.ok("param: " + p).build();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ public interface ControllerInterface {

@GetMapping("/beanValidation/pathParameter/inherited/{param}")
ResponseEntity<String> beanValidationPathParameterInherited(
@PathVariable("param") @Positive @NotNull Integer param);
@PathVariable("param") @Positive @NotNull Integer p);

@GetMapping("/beanValidation/pathParameter/overridden/{param}")
ResponseEntity<String> beanValidationPathParameterOverridden(
@PathVariable("param") @Positive @NotNull Integer param);
@PathVariable("param") @Positive @NotNull Integer p);

}
Original file line number Diff line number Diff line change
Expand Up @@ -150,32 +150,32 @@ public void unmappedFromBackend(@RequestParam("client") Client client) {

@GetMapping("/beanValidation/queryParameter")
public ResponseEntity<String> beanValidationQueryParameter(
@RequestParam("param") @Positive @NotNull Integer param,
@RequestParam("other") @Size(max = 5) String other) {
return ResponseEntity.ok("param: " + param + ", other: " + other);
@RequestParam("param") @Positive @NotNull Integer p,
@RequestParam @Size(max = 5) String other) {
return ResponseEntity.ok("param: " + p + ", other: " + other);
}

@GetMapping("/beanValidation/headerParameter")
public ResponseEntity<String> beanValidationHeaderParameter(
@RequestHeader("param") @Positive @NotNull Integer param) {
return ResponseEntity.ok("param: " + param);
@RequestHeader("param") @Positive @NotNull Integer p) {
return ResponseEntity.ok("param: " + p);
}

@GetMapping("/beanValidation/pathParameter/class/{param}")
public ResponseEntity<String> beanValidationPathParameter(
@PathVariable("param") @Positive @NotNull Integer param) {
return ResponseEntity.ok("param: " + param);
@PathVariable("param") @Positive @NotNull Integer p) {
return ResponseEntity.ok("param: " + p);
}

@Override
public ResponseEntity<String> beanValidationPathParameterInherited(Integer param) {
return ResponseEntity.ok("param: " + param);
public ResponseEntity<String> beanValidationPathParameterInherited(Integer p) {
return ResponseEntity.ok("param: " + p);
}

@Override
@GetMapping("/beanValidation/pathParameter/overridden")
public ResponseEntity<String> beanValidationPathParameterOverridden(@RequestParam Integer param) {
return ResponseEntity.ok("param: " + param);
public ResponseEntity<String> beanValidationPathParameterOverridden(@RequestParam("param") Integer p) {
return ResponseEntity.ok("param: " + p);
}

@PostMapping("/beanValidation/body")
Expand All @@ -194,8 +194,8 @@ public ResponseEntity<String> beanValidationBodyInheritance(@Valid @RequestBody
}

@PostMapping("/beanValidation/queryParameter/nested")
public ResponseEntity<String> beanValidationQueryParameterNested(@Valid Model param) {
return ResponseEntity.ok("param: " + param);
public ResponseEntity<String> beanValidationQueryParameterNested(@Valid Model p) {
return ResponseEntity.ok("param: " + p);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ public interface ControllerInterface {

@GetMapping("/beanValidation/pathParameter/inherited/{param}")
ResponseEntity<String> beanValidationPathParameterInherited(
@PathVariable("param") @Positive @NotNull Integer param);
@PathVariable("param") @Positive @NotNull Integer p);

@GetMapping("/beanValidation/pathParameter/overridden/{param}")
ResponseEntity<String> beanValidationPathParameterOverridden(
@PathVariable("param") @Positive @NotNull Integer param);
@PathVariable("param") @Positive @NotNull Integer p);

}
Original file line number Diff line number Diff line change
Expand Up @@ -170,32 +170,32 @@ public void unmappedFromBackend(@RequestParam("client") Client client) {

@GetMapping("/beanValidation/queryParameter")
public ResponseEntity<String> beanValidationQueryParameter(
@RequestParam("param") @Positive @NotNull Integer param,
@RequestParam("other") @Size(max = 5) String other) {
return ResponseEntity.ok("param: " + param + ", other: " + other);
@RequestParam("param") @Positive @NotNull Integer p,
@RequestParam @Size(max = 5) String other) {
return ResponseEntity.ok("param: " + p + ", other: " + other);
}

@GetMapping("/beanValidation/headerParameter")
public ResponseEntity<String> beanValidationHeaderParameter(
@RequestHeader("param") @Positive @NotNull Integer param) {
return ResponseEntity.ok("param: " + param);
@RequestHeader("param") @Positive @NotNull Integer p) {
return ResponseEntity.ok("param: " + p);
}

@GetMapping("/beanValidation/pathParameter/class/{param}")
public ResponseEntity<String> beanValidationPathParameter(
@PathVariable("param") @Positive @NotNull Integer param) {
return ResponseEntity.ok("param: " + param);
@PathVariable("param") @Positive @NotNull Integer p) {
return ResponseEntity.ok("param: " + p);
}

@Override
public ResponseEntity<String> beanValidationPathParameterInherited(Integer param) {
return ResponseEntity.ok("param: " + param);
public ResponseEntity<String> beanValidationPathParameterInherited(Integer p) {
return ResponseEntity.ok("param: " + p);
}

@Override
@GetMapping("/beanValidation/pathParameter/overridden")
public ResponseEntity<String> beanValidationPathParameterOverridden(@RequestParam Integer param) {
return ResponseEntity.ok("param: " + param);
public ResponseEntity<String> beanValidationPathParameterOverridden(@RequestParam("param") Integer p) {
return ResponseEntity.ok("param: " + p);
}

@PostMapping("/beanValidation/body")
Expand All @@ -214,8 +214,8 @@ public ResponseEntity<String> beanValidationBodyInheritance(@Valid @RequestBody
}

@PostMapping("/beanValidation/queryParameter/nested")
public ResponseEntity<String> beanValidationQueryParameterNested(@Valid Model param) {
return ResponseEntity.ok("param: " + param);
public ResponseEntity<String> beanValidationQueryParameterNested(@Valid Model p) {
return ResponseEntity.ok("param: " + p);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package io.github.belgif.rest.problem.jaxrs;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

import javax.validation.ParameterNameProvider;
import javax.ws.rs.CookieParam;
import javax.ws.rs.FormParam;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.MatrixParam;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.ext.Provider;

/**
* A ParameterNameProvider that retrieves the parameter name from JAX-RS annotations (if present).
*
* @see ParameterNameProvider
*/
@Provider
public class JaxRsParameterNameProvider implements ParameterNameProvider {

private static final ConcurrentHashMap<Executable, List<String>> PARAMETER_NAME_CACHE = new ConcurrentHashMap<>();

@Override
public List<String> getParameterNames(Constructor<?> constructor) {
return PARAMETER_NAME_CACHE.computeIfAbsent(constructor, this::getParameterNames);
}

@Override
public List<String> getParameterNames(Method method) {
return PARAMETER_NAME_CACHE.computeIfAbsent(method, this::getParameterNames);
}

private List<String> getParameterNames(Executable executable) {
return Arrays.stream(executable.getParameters())
.map(this::getParameterName)
.collect(Collectors.toList());
}

private String getParameterName(Parameter parameter) {
Annotation[] annotations = parameter.getAnnotations();
for (Annotation annotation : annotations) {
if (annotation instanceof QueryParam) {
return ((QueryParam) annotation).value();
} else if (annotation instanceof PathParam) {
return ((PathParam) annotation).value();
} else if (annotation instanceof HeaderParam) {
return ((HeaderParam) annotation).value();
} else if (annotation instanceof CookieParam) {
return ((CookieParam) annotation).value();
} else if (annotation instanceof FormParam) {
return ((FormParam) annotation).value();
} else if (annotation instanceof MatrixParam) {
return ((MatrixParam) annotation).value();
}
}
return parameter.getName();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<validation-config xmlns="http://xmlns.jcp.org/xml/ns/validation/configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/validation/configuration http://xmlns.jcp.org/xml/ns/validation/configuration/validation-configuration-2.0.xsd"
version="2.0">

<parameter-name-provider>io.github.belgif.rest.problem.jaxrs.JaxRsParameterNameProvider</parameter-name-provider>

</validation-config>
Loading

0 comments on commit af5eb31

Please sign in to comment.