Reputation: 363
I have a code generator, that generates interfaces for JAX-RS endpoints and my backend app implements these interfaces, to provide the business logic.
The problem now is, that I cannot use name-bound container filters to enhance the business logic or to add security: Any @NameBinding
marker annotation on the implementing class or its methods is ignored and the corresponding filter is not called.
Here is a minimal example: (code is in Kotlin, but the issue is the same when implemented in pure Java)
// generated
data class FooDto(val filtered: Boolean)
// generated
@Path("/")
interface OpenApiGeneratedInterface {
@GET
@Path("/foo/bar")
@Produces("application/json")
fun foo(): FooDto
}
// my implementation
class ImplementingApiController : OpenApiGeneratedInterface {
@TestMarker
override fun foo() = FooDto(filtered = false)
}
// may come from external dependency
@NameBinding
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
annotation class TestMarker
// may come from external dependency
@Provider
@TestMarker
class TestFilter: ContainerResponseFilter {
override fun filter(
requestContext: ContainerRequestContext,
responseContext: ContainerResponseContext,
) {
responseContext.entity = FooDto(filtered = true)
}
}
When a request to /foo/bar
is made, I get {"filtered":false}
, so the filter is not running.
When I move the @TestMarker
annotation from ImplementingApiController::foo
to OpenApiGeneratedInterface::foo
, I instead get {"filtered":true}
, so the filter did run this time. Note, that modifying the interface is not possible in reality, since the real interfaces are generated. I only did this in the example to show that the filter is working in general.
The problem seems to be, that the system only looks for marker annotations on the interfaces and never on the implementing classes.
Here is the complete picture; I am in control of:
ImplementingApiController
classI have no or nearly no control over:
OpenApiGeneratedInterface
interface (is generated from an OpenAPI spec)FooDto
(also generated)@TestMarker
annotation and its corresponding filter (come from yet another project)This leaves me with little wiggle room to get this working.
Is this even possible in this constellation, and if yes, how would this work?
What I have tried so far:
@Path
or @Provider
annotation to ImplementingApiController
to force the system to use this class for annotation discovery (did not work)javax.ws.rs.container.DynamicFeature
and wire up the filters by searching the interface implementations via reflection (could work, but it will get really ugly, when interface and implementation are not managed by the same class loader)ContainerResponseFilter
that is always active and call the actual filters dynamically (also requires the same reflection madness like with a DynamicFeature
)Further ideas:
Upvotes: 3
Views: 417