Skip to content

Exception thrown only in Eclipse runtime environment when using openapi annotations with javax.Validation.Validannotation #2346

@Kazuki-Machida

Description

@Kazuki-Machida

Describe the bug

  • I encountered an exception when attempting to instantiate a record under specific conditions, exclusively within the Eclipse runtime environment.. The error message is as follows:
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.annotation.AnnotationFormatError: Duplicate annotation for class: interface javax.validation.Valid: @javax.validation.Valid()
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1087) ~[spring-webmvc-5.3.29.jar:5.3.29]
	at ...
full error message

org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.annotation.AnnotationFormatError: Duplicate annotation for class: interface javax.validation.Valid: @javax.validation.Valid()
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1087) ~[spring-webmvc-5.3.29.jar:5.3.29]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:965) ~[spring-webmvc-5.3.29.jar:5.3.29]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.29.jar:5.3.29]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.29.jar:5.3.29]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:517) ~[jakarta.servlet-api-4.0.4.jar:4.0.4]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.29.jar:5.3.29]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:584) ~[jakarta.servlet-api-4.0.4.jar:4.0.4]
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:799) ~[jetty-servlet-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1656) ~[jetty-servlet-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:292) ~[websocket-server-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) ~[jetty-servlet-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626) ~[jetty-servlet-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.29.jar:5.3.29]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.29.jar:5.3.29]
	at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) ~[jetty-servlet-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626) ~[jetty-servlet-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.29.jar:5.3.29]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.29.jar:5.3.29]
	at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) ~[jetty-servlet-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626) ~[jetty-servlet-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.29.jar:5.3.29]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.29.jar:5.3.29]
	at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) ~[jetty-servlet-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626) ~[jetty-servlet-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:552) ~[jetty-servlet-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) ~[jetty-server-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:600) ~[jetty-security-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) ~[jetty-server-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235) ~[jetty-server-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1624) ~[jetty-server-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233) ~[jetty-server-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1440) ~[jetty-server-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188) ~[jetty-server-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:505) ~[jetty-servlet-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1594) ~[jetty-server-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186) ~[jetty-server-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1355) ~[jetty-server-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) ~[jetty-server-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) ~[jetty-server-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.server.Server.handle(Server.java:516) ~[jetty-server-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:487) ~[jetty-server-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:732) ~[jetty-server-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:479) ~[jetty-server-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:277) ~[jetty-server-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311) ~[jetty-io-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105) ~[jetty-io-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104) ~[jetty-io-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883) ~[jetty-util-9.4.51.v20230217.jar:9.4.51.v20230217]
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034) ~[jetty-util-9.4.51.v20230217.jar:9.4.51.v20230217]
	at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
Caused by: java.lang.annotation.AnnotationFormatError: Duplicate annotation for class: interface javax.validation.Valid: @javax.validation.Valid()
	at java.base/sun.reflect.annotation.TypeAnnotationParser.mapTypeAnnotations(TypeAnnotationParser.java:387) ~[na:na]
	at java.base/sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl.<init>(AnnotatedTypeFactory.java:152) ~[na:na]
	at java.base/sun.reflect.annotation.AnnotatedTypeFactory.buildAnnotatedType(AnnotatedTypeFactory.java:67) ~[na:na]
	at java.base/sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedParameterizedTypeImpl.getAnnotatedActualTypeArguments(AnnotatedTypeFactory.java:433) ~[na:na]
	at org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.findTypeArgumentsConstraints(AnnotationMetaDataProvider.java:766) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.findTypeAnnotationConstraints(AnnotationMetaDataProvider.java:619) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.findExecutableMetaData(AnnotationMetaDataProvider.java:336) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.getMetaData(AnnotationMetaDataProvider.java:292) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.getMethodMetaData(AnnotationMetaDataProvider.java:279) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.retrieveBeanConfiguration(AnnotationMetaDataProvider.java:130) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.getBeanConfiguration(AnnotationMetaDataProvider.java:120) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl.getBeanConfigurationForHierarchy(BeanMetaDataManagerImpl.java:234) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl.createBeanMetaData(BeanMetaDataManagerImpl.java:201) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl.getBeanMetaData(BeanMetaDataManagerImpl.java:165) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.engine.ValidatorImpl.buildNewLocalExecutionContext(ValidatorImpl.java:772) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.engine.ValidatorImpl.access$200(ValidatorImpl.java:84) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.engine.ValidatorImpl$CascadingValueReceiver.doValidate(ValidatorImpl.java:707) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.engine.ValidatorImpl$CascadingValueReceiver.indexedValue(ValidatorImpl.java:681) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.engine.valueextraction.ListValueExtractor.extractValues(ListValueExtractor.java:28) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.engine.valueextraction.ListValueExtractor.extractValues(ListValueExtractor.java:17) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.engine.valueextraction.ValueExtractorHelper.extractValues(ValueExtractorHelper.java:42) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.engine.ValidatorImpl.validateCascadedContainerElementsForCurrentGroup(ValidatorImpl.java:651) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.engine.ValidatorImpl.validateCascadedConstraints(ValidatorImpl.java:598) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.engine.ValidatorImpl.validateParametersInContext(ValidatorImpl.java:880) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.engine.ValidatorImpl.validateParameters(ValidatorImpl.java:283) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.hibernate.validator.internal.engine.ValidatorImpl.validateParameters(ValidatorImpl.java:235) ~[hibernate-validator-6.2.5.Final.jar:6.2.5.Final]
	at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:110) ~[spring-context-5.3.29.jar:5.3.29]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.29.jar:5.3.29]
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.29.jar:5.3.29]
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.29.jar:5.3.29]
	at com.sample.simplesample.presentation.api.InspectionController$$EnhancerBySpringCGLIB$$317d4b1e.inspection(<generated>) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.29.jar:5.3.29]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.29.jar:5.3.29]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.29.jar:5.3.29]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.29.jar:5.3.29]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.29.jar:5.3.29]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.29.jar:5.3.29]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1072) ~[spring-webmvc-5.3.29.jar:5.3.29]
	... 49 common frames omitted


  • The error occurs under the following circumstances:
    • Running the code in Eclipse
    • Having a record annotated with javax.Validation.Valid, which contains a List of other records
    • Within this List of records, each record has a field that is also a List, containing another record annotated with javax.Validation.Valid
    • Applying io.swagger.v3.oas annotations to the List contained in the field (e.g., @Schema(), @parameter(), ...)
    • Accessing this endpoint with API testing tools
  • When the code is run through Gradle or executed in IntelliJ IDEA, no such exception occurs; instead, status 200 is received, as expected. The issue appears to be specific to the Eclipse environment.

To Reproduce
Steps to reproduce the behavior:

  • What version of spring-boot you are using? → 2.7.14
  • What modules and versions of springdoc-openapi are you using? → 1.7.0
  • Provide with a sample code (HelloController) or Test that reproduces the problem:
    • Here is a sample code:
package com.sample.simplesample.presentation.api;

import java.util.List;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.sample.simplesample.presentation.api.InspectionController.InspectionRequest.InnerClass;

import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;

@RestController
@RequestMapping("/v1")
@Validated
@Hidden
public class InspectionController {
	
	public class OkResponse {
		public String r = "OK";
	}
	
	public record InspectionRequest(
	       
		@Schema(requiredMode = RequiredMode.REQUIRED, description = "somehow Eclipse throws an exception once this line is valid")
		List<@Valid InnerClass> inners
		
	) {
		public record InnerClass(@NotNull Integer id) {}
	}

	@PostMapping("/inspections")
	public OkResponse inspection(
			
			@RequestBody
			List<@Valid InspectionRequest> req
			
	) {
		return new OkResponse();
	}
	
}
  • Here are the information of Eclipse I'm using:
    • Version: 2023-06 (4.28.0)
    • Installed JRE: OpenJDK Temurin jdk-17.0.8+7

Expected behavior

  • If I run this code in gradle or other IDE like IntelliJ IDEA, I don't encounter such an exception, just receive OkResponse with status 200. I want Eclipse to behave the same way.

Additional context

I see you recommend to use IntelliJ IDEA but I hope you consider it.

Thank you.

Metadata

Metadata

Assignees

No one assigned

    Labels

    wontfixThis will not be worked on

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions