Skip to content

Problem with Generic typing extending AbstractHttpMessageConverter<List<XXX> #35942

@cedricbarbin

Description

@cedricbarbin

I try to extend AbstractHttpMessageConverter and my return type is a List. I'd like to have different converters depending on the object type of my list (Generic typing).

Super class:

public abstract class PrometheusCommonHttpMessageConverter<T> extends AbstractHttpMessageConverter<List<T>> {
...
}

Implementation:

public class PrometheusMonitoringHttpMessageConverter extends PrometheusCommonHttpMessageConverter<MonitoringLineDTO> {
...
    @Override
    protected boolean supports(Class<?> clazz) {
        return ???   // Here if I test with List.class it always return true, no matter which generic typing is used
    }
...
}

I couldn't make it works because reflection and generic typing are not compatible.

Can you think of a way to make it possible?

I did it by modifying AbstractMessageConverterMethodProcessor... but my way is a workaround, compatible for my specific project and I'm pretty sure you can find a better way to do it.

My workaround:

public class PrometheusMonitoringHttpMessageConverter extends PrometheusCommonHttpMessageConverter<MonitoringLineDTO> {
...
    @Override
    protected boolean supports(Class<?> clazz) {
        return MonitoringLineDTO.class.isAssignableFrom(clazz);
    }
...
}

And (the idea was to send the class of the objects in the list) :

protected <T> void writeWithMessageConverters(@Nullable T value, MethodParameter returnType, ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
...
                //Patch
                //If List type, use a converter only a data is present and override class type with an element of the list
                else if (List.class.isAssignableFrom(valueType)) {
                   if(value instanceof List<?> && !((List) value).isEmpty() && converter.canWrite(((List) value).get(0).getClass(), selectedMediaType)) {
                        converterTypeToUse = ConverterType.BASE;
                    }
                //Patch end
                } else if(converter.canWrite(valueType, selectedMediaType)) {
                    converterTypeToUse = ConverterType.BASE;
                }
...
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: webIssues in web modules (web, webmvc, webflux, websocket)status: waiting-for-triageAn issue we've not yet triaged or decided on

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions