@@ -1787,6 +1787,8 @@ protected boolean applyBeanValidatorAnnotations(Schema property, Annotation[] an
17871787 return modified ;
17881788 }
17891789 }
1790+ // expand composed constraint meta-annotations (e.g., @Min/@Max on custom annotations)
1791+ annotations = expandValidationMetaAnnotations (annotations );
17901792 Map <String , Annotation > annos = new HashMap <>();
17911793 if (annotations != null ) {
17921794 for (Annotation anno : annotations ) {
@@ -1979,6 +1981,8 @@ protected boolean checkGroupValidation(Class[] groups, Set<Class> invocationGrou
19791981 }
19801982
19811983 protected boolean applyBeanValidatorAnnotationsNoGroups (Schema property , Annotation [] annotations , Schema parent , boolean applyNotNullAnnotations ) {
1984+ // expand composed constraint meta-annotations (e.g., @Min/@Max on custom annotations)
1985+ annotations = expandValidationMetaAnnotations (annotations );
19821986 Map <String , Annotation > annos = new HashMap <>();
19831987 boolean modified = false ;
19841988 if (annotations != null ) {
@@ -2082,6 +2086,42 @@ protected boolean applyBeanValidatorAnnotationsNoGroups(Schema property, Annotat
20822086 return modified ;
20832087 }
20842088
2089+ /**
2090+ * Expands provided annotations to include bean-validation constraint annotations present as meta-annotations
2091+ * on custom annotations (i.e., composed constraints like a custom @ValidStoreId annotated with @Min/@Max).
2092+ * Only javax.validation.constraints annotations are added to avoid unrelated meta-annotations.
2093+ */
2094+ private Annotation [] expandValidationMetaAnnotations (Annotation [] annotations ) {
2095+ if (annotations == null || annotations .length == 0 ) {
2096+ return annotations ;
2097+ }
2098+ Map <String , Annotation > merged = new LinkedHashMap <>();
2099+ for (Annotation a : annotations ) {
2100+ if (a != null ) {
2101+ merged .put (a .annotationType ().getName (), a );
2102+ }
2103+ }
2104+ try {
2105+ for (Annotation a : annotations ) {
2106+ if (a == null ) continue ;
2107+ Annotation [] metas = a .annotationType ().getAnnotations ();
2108+ if (metas == null ) continue ;
2109+ for (Annotation meta : metas ) {
2110+ if (meta == null ) continue ;
2111+ String name = meta .annotationType ().getName ();
2112+ // include only standard bean validation constraint annotations
2113+ if (name != null && name .startsWith ("javax.validation.constraints" )) {
2114+ merged .putIfAbsent (name , meta );
2115+ }
2116+ }
2117+ }
2118+ } catch (Throwable t ) {
2119+ // be conservative: if anything goes wrong, fall back to original annotations
2120+ return annotations ;
2121+ }
2122+ return merged .values ().toArray (new Annotation [0 ]);
2123+ }
2124+
20852125 private boolean resolveSubtypes (Schema model , BeanDescription bean , ModelConverterContext context , JsonView jsonViewAnnotation ) {
20862126 final List <NamedType > types = _intr ().findSubtypes (bean .getClassInfo ());
20872127 if (types == null ) {
0 commit comments