Search code examples
javaspringspring-bootenumsthymeleaf

Trying to use an enum as an input working with thymeleaf


A problem occurs when I try to make POST request by an html page using thymeleaf. A controller should receive an input as an enum, but it throws an error:

java.lang.NoSuchMethodException: com.trade_analysis.model.StockSymbol.<init>()
    at java.base/java.lang.Class.getConstructor0(Class.java:3427) ~[na:na]"

I don't know what's not ok. I have seen some examples and have tried many things but I can't make it work as it should.

HTML:

<select class="form-item" th:field="${symbol}" required>
    <option value="" selected disabled hidden id="default-symbol">Symbol</option>
    <option class="dropdown-menu-button" th:each="symbolOption: ${symbols}" th:value="${symbolOption}" th:text="${symbolOption}"></option>
</select>

Java controler:

    @GetMapping(value = "/stocks")
    @PreAuthorize(value = "isAuthenticated()")
    public String getStockPrices(Model model) throws UserNotFoundException {
        User user = userService.getUserByUsername(getUsername());
        String apiKey = user.getApiKey() == null ? "" : user.getApiKey();

        model.addAttribute("apiKey", apiKey);
        model.addAttribute("symbol", "");
        model.addAttribute("symbols", asList(StockSymbol.values()));

        return "stock-prices-preview";
    }

    @PostMapping(value = "/stocks")
    @PreAuthorize(value = "isAuthenticated()")
    public String stockPrices(@ModelAttribute String apiKey, @ModelAttribute StockSymbol symbol, Model model) {
        model.addAttribute("apiKey", apiKey);
        model.addAttribute("symbol", symbol);
        model.addAttribute("symbols", asList(StockSymbol.values()));

        return "stock-prices-preview";
    }

'StockSymbol' enum:

public enum StockSymbol {
    GOOGL("GOOGL"),
    MSFT("MSFT"),
    AMZN("AMZN"),
    IBM("IBM"),
    CSCO("CSCO"),
    AAPL("AAPL");

    String sys;

    StockSymbol(String sys) {
        this.sys = sys;
    }
}

First few lines of error (full error is on: https://pastebin.com/kg8RR7G6)

java.lang.NoSuchMethodException: com.trade_analysis.model.StockSymbol.<init>()
    at java.base/java.lang.Class.getConstructor0(Class.java:3427) ~[na:na]
    at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2631) ~[na:na]
    at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:216) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]

Solution

  • In your POST handler you have this line:

    public String stockPrices(@ModelAttribute String apiKey, @ModelAttribute StockSymbol symbol, Model model) {
    

    Remove the @ModelAttribute annotation. Your problem is that Spring tries to instantiate the enum when it runs the controller method.

    Use @RequestParam to obtain the incoming POST parameter by name. You might need to specify the parameter name in the annotation if your compiler doesn't use the -parameters switch.