Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Feign client support for optional request param

Does Feign client support optional request param?

For example, I have an endpoint, but I am not finding a way to actually make the param1 optional using feign client.

@GetMapping(path = "endpoint1")
ResponseEntity request(@RequestParam(name = "param1", required = false, defaultValue = "key") String param1){}
like image 234
krmanish007 Avatar asked Oct 20 '25 04:10

krmanish007


2 Answers

Since you are using Spring Cloud Feign I find the easiest way to implement optional parameters is using a DTO, and optionally implementing a builder pattern (Lombok can help to make that less verbose).

The DTO will make the parameter in the request optional (when null), not the method signature. Optional parameters to methods should be -almost- impossible but some alternatives can be found here.

The builder pattern will make the initialization parameters optional (or mandatory) details can be found here. The builder can also be used to set defaults. Lombok details can be found here. Alternatively a builder can built manually. Starting at wikipedia. Some example pure Java code.

Code might look like this:

@GetMapping(path = "/endpoint1") //Not starting with / does not look ok...
ResponseEntity request(@SpringQueryMap MyDTO);

//MyDTO

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class MyDTO {

  private String param1;
  private String param2;
  private String param3;
}

//when using

request(MyDTO.Builder().build()); //use all defaults
request(MyDTO.Builder().param1("foo").build()); //param1 set, all other defaults
request(MyDTO.Builder().param1("foo").param2("bar").build()); //param1 and param2 set
like image 163
gbarco Avatar answered Oct 22 '25 04:10

gbarco


I managed to use Optional request params with Feign by creating a customised FeignFormatterRegistrar. Here is the code:

package feignformatters;

import org.springframework.cloud.openfeign.FeignFormatterRegistrar;
import org.springframework.format.FormatterRegistry;
import org.springframework.stereotype.Component;

import java.util.Optional;

@Component
public class OptionalFeignFormatterRegistrar implements FeignFormatterRegistrar {
    
    @Override
    public void registerFormatters(FormatterRegistry registry) {
        registry.addConverter(
            Optional.class, 
            String.class, 
            optional -> {
                if (optional.isPresent())
                    return optional.get().toString();
                else
                    return "";
            });
    }
}

The following client started working fine with the previous component loaded in the project:

@FeignClient("book-service")
public interface BookServiceClient {

    @GetMapping("/books")
    public List<Book> getBooks(
        @RequestParam("page") Optional<Integer> pageNum,
        @RequestParam("size") Optional<Integer> pageSize,
        @RequestParam("reader") Optional<Long> readerId);
}
like image 35
dbaltor Avatar answered Oct 22 '25 03:10

dbaltor