JOOQ CodeGen and Jersey 3.0.2 bean validation annotations duplication exception

90 views
Skip to first unread message

Benjamin Greiner

unread,
Sep 25, 2021, 6:26:58 PM9/25/21
to jOOQ User Group
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 moreRoot 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

Lukas Eder

unread,
Sep 27, 2021, 2:52:39 AM9/27/21
to jOOQ User Group
Hi Ben,

Hard to say what's causing this. We don't generate jakarta annotations yet, so maybe that's it?

Do you really need bean validation on our generated POJOs? In the past, I've thought about deprecating this kinda weird feature. I'd love to hear about use-cases

On Sun, Sep 26, 2021 at 12:27 AM Benjamin Greiner <benjamin...@avocetsys.com> wrote:
I have an entire sample project built I can zip up and include if you like to test with. Please let me know.

If you think there's a bug in jOOQ other than the above wrong annotation namespace, why not? You can submit it here: https://github.com/jOOQ/jOOQ/issues/new/choose 
Reply all
Reply to author
Forward
0 new messages