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.
Solution: Defines the Bean, however, it is incompatible with Pageable
@Bean
public QueryMapEncoder feignQueryMapEncoderPageable() {
return new FieldQueryMapEncoder();
}