Describe the bug
@SpringQueryMap doesn't support String[], but as @RequestParam String[] is working.
Sample Fiegn client interface with two different API methods
@FeignClient
public interface ApiClient {
@GetMapping("/incorrect")
ApiResponse<ResponseDto> findAll(@SpringQueryMap ApiParams params);
@PostMapping("/correct")
ApiResponse<ResponseDto> findMarkingCodes(@RequestParam String[] fields);
}
ApiParams class
@Data
@AllArgsConstructor
public class ApiParams {
private String[] fields;
}
Expected Behaviour Expected url for request with @SpringQueryMap: https://url/incorrect?fields=name,surname Generated url for request with @SpringQueryMap: https://url/incorrect?fields=%5BLjava.lang.String%3B%405ed08faf&b=%5BLjava.lang.String%3B%4075386aa2
But when I'm trying to use String[], it works and generated url is as expected: https://url/correct?fields=name,surname
Comment From: MissingNone
You can implements the QueryMapEncoder interface.
public class FormQueryMapEncoder implements QueryMapEncoder {
private MappingJackson2HttpMessageConverter converter;
public FormQueryMapEncoder(MappingJackson2HttpMessageConverter converter) {
this.converter = converter;
}
@Override
public Map<String, Object> encode(Object object) {
Map<String, Object> ret = converter.getObjectMapper().convertValue(object,HashMap.class);
return ret;
}
}
And then declare a QueryMapEncoder bean in JavaConfig.
@Bean
QueryMapEncoder queryMapEncoder() {
return new FormQueryMapEncoder(mappingJackson2HttpMessageConverter);
}
Comment From: OlgaMaciaszek
@rkovtiuk Does the provided workaround solve your issue?
Comment From: rkovtiuk
Hi @MissingNone, @OlgaMaciaszek,
No, it doesn't.
I tried this example and see same:
fields=%5BLjava.lang.String%3B%40e35dc14
I also tried this variant:
@Bean
public QueryMapEncoder queryMapEncoder(ObjectMapper objectMapper) {
return object -> objectMapper.convertValue(object, new TypeReference<Map<String, Object>>() {});
}
But this also doesn't help.
Comment From: MissingNone
@rkovtiuk But I tried this is worked.
Maybe Encoder is different with me.
config file:
@Configuration
public class CoreFeignConfiguration {
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
@Autowired
private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter;
@Bean
@Primary
@Scope(SCOPE_PROTOTYPE)
Encoder feignFormEncoder() {
return new SpringFormEncoder(new SpringEncoder(messageConverters));
}
@Bean
QueryMapEncoder queryMapEncoder() {
return new FormQueryMapEncoder(mappingJackson2HttpMessageConverter);
}
}
FormQueryMapEncoder.java
public class FormQueryMapEncoder implements QueryMapEncoder {
private MappingJackson2HttpMessageConverter converter;
public FormQueryMapEncoder(MappingJackson2HttpMessageConverter converter) {
this.converter = converter;
}
@Override
public Map<String, Object> encode(Object object) {
Map<String, Object> ret = converter.getObjectMapper().convertValue(object,HashMap.class);
return ret;
}
}
version: spring-cloud-stater-openfeign:2.2.2.RELEASE
Can you provide a demo for your issue?
Comment From: rkovtiuk
My configuration
@Configuration
public class FeignConfiguration {
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
@Bean
public QueryMapEncoder queryMapEncoder(ObjectMapper objectMapper) {
return object -> objectMapper.convertValue(object, new TypeReference<Map<String, Object>>() {});
}
@Bean
@Primary
@Scope(SCOPE_PROTOTYPE)
public Encoder feignFormEncoder() {
return new SpringFormEncoder(new SpringEncoder(messageConverters));
}
@Bean
public Client feignClient() {
return new Client.Default(getSSLSocketFactory(), new NoopHostnameVerifier());
}
private SSLSocketFactory getSSLSocketFactory() {
try {
var sslContext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();
return sslContext.getSocketFactory();
} catch (Exception exception) {
throw new RuntimeException(exception);
}
}
}
version: 2.1.2.RELEASE
Comment From: MissingNone
@rkovtiuk I used your version for project And find out it.
Beacause Feign still used default QueryMapEncoder instead of Our QueryMapEncoder bean before spring-cloud-stater-openfeign:2.0.0.M3.
So adding the Feign.Builder bean based on the previous then it worked on your version.
new configuration:
@Configuration
public class CoreFeignConfiguration {
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
@Bean
@Primary
@Scope(SCOPE_PROTOTYPE)
Encoder feignFormEncoder() {
return new SpringFormEncoder(new SpringEncoder(messageConverters));
}
@Bean
QueryMapEncoder queryMapEncoder(ObjectMapper objectMapper) {
return object-> objectMapper.convertValue(object, new TypeReference<Map<String, Object>>() {});
}
@Bean
@Scope(SCOPE_PROTOTYPE)
public Feign.Builder feignBuilder(QueryMapEncoder queryMapEncoder) {
return Feign.builder().queryMapEncoder(queryMapEncoder);
}
}
Comment From: rkovtiuk
@MissingNone, this configuration works for me thanks 😃
@Configuration
public class FeignConfiguration {
@Bean
public QueryMapEncoder queryMapEncoder(ObjectMapper objectMapper) {
return object -> objectMapper.convertValue(object, new TypeReference<Map<String, Object>>() {});
}
@Bean
@Scope(SCOPE_PROTOTYPE)
public Feign.Builder feignBuilder(QueryMapEncoder queryMapEncoder) {
return Feign.builder().queryMapEncoder(queryMapEncoder);
}
}
But as I understood, this must work without this additional configuration.
Comment From: MissingNone
@rkovtiuk Yes,it's a bug. your issue is same as the issue #256.Issue https://github.com/OpenFeign/feign/issues/1170 mentioned it.
Comment From: OlgaMaciaszek
Closing in favour of OpenFeign/feign#1170.