Repository: micronaut-projects/micronaut-core
File: http/src/main/java/io/micronaut/http/body/DefaultMessageBodyHandlerRegistry.java (Java)

Code before:
                    // Filter by media types first before filtering by the type hierarchy
                    newMediaTypeQualifier(Argument.of(MessageBodyWriter.class, type), mediaTypes, Produces.class),
                    MatchArgumentQualifier.ofLowerTypes(MessageBodyWriter.class, type)
                )
            ).stream()
            .filter(writer -> mediaTypes.stream().anyMatch(mediaType -> writer.isWriteable(type, mediaType)))
            .findFirst().orElse(null);
    }

    private static final class MediaTypeQualifier<T> extends FilteringQualifier<T> {
        private final Argument<?> type;
        private final List<MediaType> mediaTypes;
        private final Class<? extends Annotation> annotationType;

        private MediaTypeQualifier(Argument<?> type,
                                   List<MediaType> mediaTypes,
                                   Class<? extends Annotation> annotationType) {
            this.type = type;
            this.mediaTypes = mediaTypes;
            this.annotationType = annotationType;
        }

        @Override
        public boolean doesQualify(Class<T> beanType, BeanType<T> candidate) {
            if (type.getType() == MessageBodyWriter.class && candidate instanceof BeanDefinition<?> definition) {
                List<Argument<?>> consumedType = definition.getTypeArguments(type.getType());
                Argument<?>[] typeParameters = type.getTypeParameters();
                if (ArrayUtils.isEmpty(typeParameters)) {
                    return false;
                }

                Argument<?> requiredType = typeParameters[0];
                if (consumedType.isEmpty() || isInvalidType(consumedType, requiredType)) {
                    return false;
                }
            }
            String[] applicableTypes = candidate.getAnnotationMetadata().stringValues(annotationType);
            if (applicableTypes.length == 0) {
                return true;
            }
            for (String mt : applicableTypes) {
                if (mediaTypes.contains(new MediaType(mt))) {
                    return true;
                }
            }
            return false;
        }

        private static boolean isInvalidType(List<Argument<?>> consumedType, Argument<?> requiredType) {
            Argument<?> argument = consumedType.get(0);
            return !(argument.isTypeVariable() || argument.isAssignableFrom(requiredType.getType()));

Review comment (suggestion):
```suggestion
                List<Argument<?>> consumedType = definition.getTypeArguments(MessageBodyWriter.class);
```

Code after:
                    // Filter by media types first before filtering by the type hierarchy
                    newMediaTypeQualifier(Argument.of(MessageBodyWriter.class, type), mediaTypes, Produces.class),
                    MatchArgumentQualifier.contravariant(MessageBodyWriter.class, type)
                )
            ).stream()
            .filter(writer -> mediaTypes.stream().anyMatch(mediaType -> writer.isWriteable(type, mediaType)))
            .findFirst().orElse(null);
    }

    private static final class MediaTypeQualifier<T> extends FilteringQualifier<T> {
        private final Argument<?> type;
        private final List<MediaType> mediaTypes;
        private final Class<? extends Annotation> annotationType;

        private MediaTypeQualifier(Argument<?> type,
                                   List<MediaType> mediaTypes,
                                   Class<? extends Annotation> annotationType) {
            this.type = type;
            this.mediaTypes = mediaTypes;
            this.annotationType = annotationType;
        }

        @Override
        public boolean doesQualify(Class<T> beanType, BeanType<T> candidate) {
            if (type.getType() == MessageBodyWriter.class && candidate instanceof BeanDefinition<?> definition) {
                List<Argument<?>> consumedType = definition.getTypeArguments(MessageBodyWriter.class);
                Argument<?>[] typeParameters = type.getTypeParameters();
                if (ArrayUtils.isEmpty(typeParameters)) {
                    return false;
                }

                Argument<?> requiredType = typeParameters[0];
                if (consumedType.isEmpty() || isInvalidType(consumedType, requiredType)) {
                    return false;
                }
            }
            String[] applicableTypes = candidate.getAnnotationMetadata().stringValues(annotationType);
            if (applicableTypes.length == 0) {
                return true;
            }
            for (String mt : applicableTypes) {
                if (mediaTypes.contains(new MediaType(mt))) {
                    return true;
                }
            }
            return false;
        }

        private static boolean isInvalidType(List<Argument<?>> consumedType, Argument<?> requiredType) {
            Argument<?> argument = consumedType.get(0);
            return !(argument.isTypeVariable() || argument.isAssignableFrom(requiredType.getType()));