Class UnknownQueryParameterFilter
java.lang.Object
ubic.gemma.rest.providers.UnknownQueryParameterFilter
- All Implemented Interfaces:
jakarta.ws.rs.container.ContainerRequestFilter
@Provider
@Component
public class UnknownQueryParameterFilter
extends Object
implements jakarta.ws.rs.container.ContainerRequestFilter
Rejects a request that carries a query parameter the matched resource method cannot bind, rather than ignoring it.
JAX-RS drops an undeclared query parameter silently, which turns a typo or a wrong parameter name into a
confidently-wrong answer instead of an error: GET /datasets?ids=1,2,3&limit=200 dropped ids and
answered with the whole corpus, reported under a totalElements covering every dataset. There is no JAX-RS
or Jersey setting for this (Jersey 3.1 exposes none), so it is enforced here.
Why the accepted set cannot go stale
The accepted set is not written down anywhere. It is read, per route, fromInvocable.getParameters() — the very Parameter objects Jersey uses to bind values into the
method's arguments. Adding a @QueryParam to a resource method therefore widens what this filter accepts in
the same edit, and there is no second list to update. Consequences that follow from reading Jersey's own model
rather than re-deriving one by reflection:
@BeanParamis expanded, because Jersey models it as aParameter.BeanParameterholding the nested parameters (none are used in this module today; the recursion is what keeps that true if one is added).- Parameters inherited from a superclass or interface are already resolved into the invocable, so a route that declares its parameters on a base type is not wrongly narrowed.
- Anything Jersey binds from somewhere other than the query string — path, header, cookie, matrix, entity — is simply not in the accepted set and is not looked for in the query string either.
What is deliberately not checked
- A method annotated
AllowsUnknownQueryParameters, or declared in a class so annotated: it reads the query string itself, so no declared set describes what it accepts. - A method handed the raw
UriInfo, for the same reason — it can read any parameter, so no parameter can be shown to be ignored. Derived from the signature rather than from a list, so a new pass-through route is covered the moment it is written. OPTIONS, so a CORS preflight — which the browser sends to the same URL, query string included — can never be answered with a 400.CorsFiltershort-circuits preflights ahead of Jersey today; this does not depend on that staying true.- Every request, when
gemma.rest.rejectUnknownQueryParametersisfalse. The setting is the rollback: it takes a restart, not a redeploy.
- Author:
- gemma
-
Constructor Summary
ConstructorsConstructorDescriptionUnknownQueryParameterFilter(boolean enabled) The inline default matters: the mocked REST test contexts resolve placeholders from a fixed list rather than fromdefault.properties, so a bare${...}here fails container startup for every JerseyTest in the module, not just a test of this filter. -
Method Summary
Modifier and TypeMethodDescriptionvoidfilter(jakarta.ws.rs.container.ContainerRequestContext requestContext)
-
Constructor Details
-
UnknownQueryParameterFilter
@Autowired public UnknownQueryParameterFilter(@Value("${gemma.rest.rejectUnknownQueryParameters:true}") boolean enabled) The inline default matters: the mocked REST test contexts resolve placeholders from a fixed list rather than fromdefault.properties, so a bare${...}here fails container startup for every JerseyTest in the module, not just a test of this filter.
-
-
Method Details
-
filter
public void filter(jakarta.ws.rs.container.ContainerRequestContext requestContext) - Specified by:
filterin interfacejakarta.ws.rs.container.ContainerRequestFilter
-