Hello!
Let me start by saying absolutely love JOOQ!
I recently encountered a runtime error that was proving difficult to isolate after upgrading to JKD-17 and upgrading to Jersey 3.0.2, migrating all javax dependencies to jarkarta.
java.lang.annotation.AnnotationFormatError: Duplicate annotation for class: interface jakarta.validation.Valid: @jakarta.validation.Valid() 1: org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer$ResponseWriter.rethrow(GrizzlyHttpContainer.java:297)
2: org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer$ResponseWriter.failure(GrizzlyHttpContainer.java:279)
3: org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:438)
4: org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:263)
5: org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
6: org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
7: org.glassfish.jersey.internal.Errors.process(Errors.java:292)
8: org.glassfish.jersey.internal.Errors.process(Errors.java:274)
9: org.glassfish.jersey.internal.Errors.process(Errors.java:244)
10: org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265)
... 7 more
Root Cause: java.lang.annotation.AnnotationFormatError: Duplicate annotation for class: interface jakarta.validation.Valid: @jakarta.validation.Valid() 1: java.base/sun.reflect.annotation.TypeAnnotationParser.mapTypeAnnotations(TypeAnnotationParser.java:387)
2: java.base/sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl.(AnnotatedTypeFactory.java:152)
3: java.base/sun.reflect.annotation.AnnotatedTypeFactory.buildAnnotatedType(AnnotatedTypeFactory.java:67)
4: java.base/sun.reflect.annotation.TypeAnnotationParser.buildAnnotatedTypes(TypeAnnotationParser.java:156)
5: java.base/java.lang.reflect.Executable.getAnnotatedParameterTypes(Executable.java:749)
6: java.base/java.lang.reflect.Parameter.getAnnotatedType(Parameter.java:238)
7: org.hibernate.validator.internal.properties.javabean.JavaBeanParameter.getAnnotatedType(JavaBeanParameter.java:56)
8: org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.findTypeAnnotationConstraintsForExecutableParameter(AnnotationMetaDataProvider.java:731)
9: org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.getParameterMetaData(AnnotationMetaDataProvider.java:430)
10: org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.findExecutableMetaData(AnnotationMetaDataProvider.java:307)
... 32 more
This is pretty vague. I created a new project from scratch and began testing to see what the piece was that was causing it. With just the base Jersey project established, and a test RESTful-endpoint with a jersey-bean-validation annotation used, it worked without a problem.
Seeing how this was a runtime error, I began to focus my efforts on parts of the project that did dynamic reflection such as Guice. I wasn't able to find anything there. It occurred to me that the code-gen from JOOQ might be having some side effects.
I added in the specifics from my reference project that was using the code-gen, added some tables and packages. Even though these were not called or even included in the class (jersey restful endpoint) that was throwing the error, as soon as I did this, the error appeared when calling any method on any endpoint class that contained the jersey-validation-bean annotation, even a method that had none itself. It only needed to be specified next to the method parameter, and the entire end point would return the error above.
import jakarta.validation.Valid;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.util.Map;
/**
*
* @author Benjamin Greiner
*/
@Path("/api/v1.0")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class About
{
//Calling this method would still cause the same error even without the @Valid in the params
@GET
@Path("about")
public Response version1_0()
{
Map<String, Object> m = Map.of(
"version", "1.0",
"application", "hello world");
return Response.status(Response.Status.OK)
.type(MediaType.APPLICATION_JSON)
.entity(m)
.build();
}
@POST
public Response help(@Valid Message msg)
{
return Response.status(Response.Status.OK)
.type(MediaType.APPLICATION_JSON)
.build();
}
}
I also updated JOOQ to 3.16-SNAP-SHOT which is compatible with JDK-17. It didn't make any difference. Still got the same error.
I have an entire sample project built I can zip up and include if you like to test with. Please let me know.
Cheers,
Ben