Is your feature request related to a problem? Please describe. If you use Records in Java 16+ (JEP 395) as @SpringQueryMap, it does not recognize any field.

Describe the solution you'd like

Create src/main/java/org/springframework/cloud/openfeign/support/RecordSpringQueryMapEncoder.java:

// Skipped License and imports part.

/**
 * Provides support for encoding Record annotated as
 * {@link org.springframework.cloud.openfeign.SpringQueryMap}.
 *
 * @author Hyeonmin Park
 * @since Maybe 3.0.6
 */
public class RecordSpringQueryMapEncoder extends BeanQueryMapEncoder {

    @Override
    public Map<String, Object> encode(Object object) {
        if (supports(object)) {
            try {
                RecordComponent[] component = object.getClass().getRecordComponents();
                Map<String, Object> propertyNameToValue = new HashMap<>();
                for (RecordComponent rc : component) {
                    Method method = rc.getAccessor();
                    Object value = method.invoke(object);
                    if (value != null && value != object) {
                        String name = rc.getName();
                        propertyNameToValue.put(name, value);
                    }
                }
                return propertyNameToValue;
            }
            catch (IllegalAccessException | InvocationTargetException e) {
                throw new EncodeException("Failure encoding object into query map", e);
            }
        }
        else {
            return super.encode(object);
        }
    }

    protected boolean supports(Object object) {
        return object.getClass().isRecord();
    }

}

Add a bean to src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java:

@Bean
@ConditionalOnJava(JavaVersion.SIXTEEN)
@ConditionalOnMissingBean
public QueryMapEncoder feignQueryMapEncoderRecord() {
    return new RecordSpringQueryMapEncoder();
}

But in this way, we need to only build with Java 16+, and I think it can break many compatibilities. Is there any way to include some classes using the Records feature with Java 8? or just by splitting the artifact something like 'spring-cloud-openfeign-jdk16'?

Describe alternatives you've considered * I can implement this in my project, but it's better to provide a common solution in the library. * I'm also considering making support for Records directly in https://github.com/OpenFeign/feign but still unfamiliar with.

Additional context Reference: https://softwaregarden.dev/en/posts/new-java/records/reflection/

Comment From: OlgaMaciaszek

Hi @KENNYSOFT , thanks for submitting the issue. It does seem like something that should be added to OpenFeign in general, not just to the Spring integration. Could you create a separate issue in https://github.com/OpenFeign/feign and link it here?

Comment From: KENNYSOFT

Alright. I'm wondering why Feign uses JDK 8, 11, 14 (but not 16+) but I will make some contribution there.

Comment From: OlgaMaciaszek

Possibly they are still working on the integration. Here, we just provide the integration for Spring Boot projects, so it should better be solved there. However, if it does not get addressed in that repo, please get back to me and we will try to add a solution here.

Comment From: KENNYSOFT

I found out that I was in the totally wrong way. I can utilize feign.querymap.FieldQueryMapEncoder and it already works well with Records.

BTW, I also noticed that spring-cloud-openfeign does not provide the queryMapEncoder property in FeignClientConfiguration, so I should manually make a bean via java code.

@OlgaMaciaszek Can I contribute here with the addition of the queryMapEncoder property in FeignClientConfiguration?

Comment From: marcusvoltolim

The problem is with @SpringQueryMap because it uses PageableSpringQueryMapEncoder, which extends BeanQueryMapEncoder, limiting it to just these two encoders.

In feign.QueryMap, you can define mapEncoder as either BEAN or FIELD.

Image

Solution: Defines the Bean, however, it is incompatible with Pageable

   @Bean
    public QueryMapEncoder feignQueryMapEncoderPageable() {
        return new FieldQueryMapEncoder();
    }