1

Please note: I am using Spring Boot here, not Spring MVC.

Java 8 and Spring Boot/Jackson here. I have the following enum:

public enum OrderType {

    PARTIAL("partialOrder"),
    FULL("fullOrder");

    private String label;

    OrderType(String label) { this.label = label; }

}

I would like to expose a POST endpoint where the client can place the OrderType#label as a request parameter, and Spring will know to convert the provided label into an OrderType like so:

@PostMapping("/v1/myapp/orders")
public ResponseEntity<?> acceptOrder(@RequestParam(value = "orderType") OrderType orderType) {
    // ...
}

And hence the client could make a call such as POST /v1/myapp/orders?orderType=fullOrder and on the server, the controller would receive an OrderType instance.

How can I accomplish this?

hotmeatballsoup
  • 385
  • 6
  • 58
  • 136
  • 1
    I think this will reduce to [this question](https://stackoverflow.com/questions/49070155/use-jackson-deserialization-for-datetime-in-spring-rest-controller), and the answer is "write a `Converter`". – chrylis -cautiouslyoptimistic- Jun 23 '21 at 15:59
  • Yes thank you, that does appear to be the case, but the problem is that I need to then register the converter with the `FormatterRegistry`, which I do not seem to have access to in Spring Boot. The `FormatterRegistry` is available from a web config that implements `WebMvcConfigurer` which is standard with Spring MVC applications. But this, being a Spring Boot application, implements `WebSecurityConfigurerAdapter`. – hotmeatballsoup Jun 23 '21 at 16:03
  • You seem to misunderstand what Spring Boot is. It's a set of configuration utilities for Spring applications. You are _also_ using the Spring MVC module to provide your Web services (and likely Spring Data for data access, and adding several more is common). – chrylis -cautiouslyoptimistic- Jun 23 '21 at 16:12
  • Oh perfect, thanks, any chance you could provide some sample code that would show me how to access the `FomatterRegistry` (so I can register my custom converter with it)? – hotmeatballsoup Jun 23 '21 at 16:41

1 Answers1

1

This was so easy, a cave man could even do it.

Enum:

public class MyEnum {
    FIZZ("sumpin"),
    BUZZ("sumpinElse");

    @JsonValue
    private String label;

    MyEnum(String label) { this.label = label; }

    public String getLabel() { return this.label; }

    public static Optional<MyEnum> toMyEnum(String label) {
        if (label == null) {
            return Optional.empty();
        }

        for (MyEnum mine : MyEnum.values()) {
            if (label.equals(mine.getLabel()) {
                return Optional.of(mine);
            }
        }

        throw new IllegalArgumentException("no supported");

    }

}

Spring converter:

public class MyEnumConverter implements Converter<String,MyEnum> {

    @Override
    public MyEnum convert(String label) {

        Optional<MyEnum> maybeMine = MyEnum.toMyEnum(label);
        if (maybeMine.isPresent()) {
            return maybeMine.get():
        }

        // else, you figure out what you want your app to do,
        // thats not my job!

    }

}

Register it:

@Configuration
public class YourAppConfig {

    @Autowired
    public void configureConverter(FormatterRegistry registry) {
        registry.addConverter(new MyEnumConverter());
    }

}

Support it from inside in a controller/resource:

@Post("/v1/foobar/doSomething")
public ResponseEntity<?> doSomething(@RequestParam(value = "mine") MyEnum mine) {
    // ... whatever
}

Use the darn thing in an API call:

POST http://yourlousyapp.example.com/v1/foobar/doSomething?mine=sumpin
hotmeatballsoup
  • 385
  • 6
  • 58
  • 136