java - 提交表单时收到接口(interface) java.util.List 未找到主要或默认构造函数?

标签 java spring thymeleaf

我再次来到了百里叶沼泽。

我收到了

There was an unexpected error (type=Internal Server Error, status=500). No primary or default constructor found for interface java.util.List

当我点击 addRow 按钮“+”时。

主页模板:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <link rel="stylesheet" type="text/css" media="all"

          href="../static/css/home-style.css"
          th:href="@{/css/home-style.css}"/>

    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--------------------------------------------------------------------------->
<h1 id="page-title"/>
<h3 id="recipe-id"/>
<h3 id="recipe-name"/>
<!--------------------------------------------------------------------------->
<form id="get-recalculated-recipe" action="#" method="post">
    <table>
        <tr>
            <th th:text="#{table.label.quantity}">Quantity</th>
            <th>Unit</th>
            <th>Ingredient Name</th>
            <th>Multiplier</th>
        </tr>
<!---------------------------------------------------------------------------->
        <div>
            <h2 th:text="#{text.new.recipe}">Add new Recipe</h2>

            <!--   @{/home}   replace via home th xml-->
            <!--    Replace ${recipe} via home th xml-->
            <form action="#" th:action="@{/home}" th:object="${recipe}" method="post">


                <legend th:text="${recipename}">Legend text</legend>


                <div>
                    <!--                message text-->
                    <label th:text="#{text.ingredients}">Ingredients</label>
                    <table>
                        <!--------------------------------------------------------------------------------------------->
                        <thead>
                        <tr>
                            <th th:text="#{text.ingredient.quantity}">Qty</th>
                            <th th:text="#{text.ingredient.unit}">Unit</th>
                            <th th:text="#{text.ingredient.name}">Name</th>
                            <th>
                                <button type="submit" name="addRow" th:text="#{text.submit.addrow}">Add row</button>
                            </th>
                        </tr>
                        </thead>
                        <!--------------------------------------------------------------------------------------------->
                        <tbody>
                        <!--- Property or field 'ingredients' cannot be found on object of type 'com.potatospy.reciply.web.model.response.Recipe' - maybe not public or not valid? --->
                        <tr th:each="ingredient : *{ingredientList}">
                            <!--                  <td th:text="${rowStat.count}">1</td>-->
                            <td>
                                <input type="text" th:field="*{ingredientName}"
                                       th:errorclass="fieldError"/>
                            </td>
                            <!--------------------------------------------------------------------------------------------->
                            <td>
                                <input type="text" th:field="*{quantity}"
                                       th:errorclass="fieldError"/>
                            </td>
                            <!--------------------------------------------------------------------------------------------->
                            <td>
                                <select th:field="*{unit}">
                                    <option th:each="units : ${allUnits}" th:value="${units.id}" th:text="${var.name}">
                                        Thymus Thymi
                                    </option>
                                </select>
                            </td>
                            <!--------------------------------------------------------------------------------------------->
                            <td>
                                <button type="submit" name="removeRow" th:value="${rowStat.index}"
                                        th:text="#{text.submit.removerow}">Remove row
                                </button>
                            </td>
                            <!--------------------------------------------------------------------------------------------->
                        </tr>
                        </tbody>
                    </table>
                </div>
                <!--------------------------------------------------------------------------------------------->
                <div class="submit">
                    <button type="submit" name="save" th:text="#{text.submit.newrecipe}">Add New Recipe</button>
                </div>
            </form>
        </div>
    </table>
</form>


</body>
</html>

Controller :

package com.potatospy.reciply.web.controller;

import com.potatospy.reciply.business.service.RecipeService;
import com.potatospy.reciply.business.util.AttributeNames;
import com.potatospy.reciply.business.util.ViewNames;
import com.potatospy.reciply.web.model.response.Unit;
import com.potatospy.reciply.web.model.response.Ingredient;
import com.potatospy.reciply.web.model.response.Recipe;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.potatospy.reciply.business.util.Mappings;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


@Controller
@Slf4j
@RequestMapping("/")
public class ReciplyController {


    @Autowired
    RecipeService svc;


    // == Model attributes == todo
    @ModelAttribute
    public List<Recipe> recipeData(){ return svc.getAllRecipes(); } // Todo For populating a menu of recipes

    // Menu Text for recipe row Unit selection
    @ModelAttribute("allUnits")
    public List<Unit> unitList() {
        return Arrays.asList(Unit.ALL);
    }


    // == FIRST STOP ==

    /* This view doesn't require any attributes or params passed to it. It's for first visits only. */
    @GetMapping(Mappings.HOME)
    public String getHomeView(Model model) {    // Took out params and attribs since they dont exist in the model
                                                // until the controller creates them

        log.info("Inside getMainView");


        Recipe recipe = svc.initNewRecipe(); // Create and initialize a new recipe

//////////////////////////////////////////////////////////////////////////////////////////////////
        model.addAttribute(AttributeNames.RECIPE, recipe);
        model.addAttribute(AttributeNames.RECIPE_ID, recipe.getRecipeId()); // should I put 0 here or what LOL
        model.addAttribute(AttributeNames.RECIPE_NAME, recipe.getRecipeName()); // "" ?
        model.addAttribute(AttributeNames.RECIPE_DATA, recipeData());
        model.addAttribute("ingredients", recipe.getIngredientList());

        log.info("recipe ingredient list size: {}", recipe.getIngredientList().size());
        //model.addAttribute(AttributeNames.INGREDIENT_LIST, recipe.getIngredientList());

        return ViewNames.HOME;
    }


    // == ADD ROW ==

    // Add Row, creates and initializes a new Recipe, adds it to the DB and List
    // and adds the attribute.
    @RequestMapping(value=Mappings.ADD_ROW)
    public String addRow(Model model
            /*final Recipe recipe, */
            /*final BindingResult bindingResult*//*holds the result of the validation and binding and contains errors that may have occurred*/) {


        svc.initNewRecipe();

        model.addAttribute(AttributeNames.RECIPE_DATA, recipeData());

        return ViewNames.HOME;
    }
/*@RequestMapping(value="/seedstartermng", params={"addRow"})
    public String addRow(final SeedStarter seedStarter, final BindingResult bindingResult) {
        seedStarter.getRows().add(new Row());
        return "seedstartermng";



    }*/

    @GetMapping("homelink")
    public String getHomeViewShortcut(Model model){
        log.info("Inside getHomeViewShortcut");
        Recipe recipe1 = new Recipe();
        recipe1.setIngredientList(new ArrayList<>());

        model.addAttribute("RECIPE",recipe1);

        return ViewNames.HOME;
    }


    // == AFTER SUBMIT ==

    @PostMapping(Mappings.SUBMIT)
    public String submit(Model model/*, @ModelAttribute(AttributeNames.RECIPE*/){

        //model.addAttribute(AttributeNames.RECIPE, recipe);
        model.addAttribute(AttributeNames.RECIPE_ID, 0); // should i put 0 here or what LOL
        model.addAttribute(AttributeNames.RECIPE_NAME, ""); // "" ?
        model.addAttribute(AttributeNames.RECIPE_DATA, recipeData());

        return "";
    }


    // == AFTER SUBMIT ==

    @PostMapping(Mappings.HOME)
    public String getRecipe(
            @ModelAttribute(AttributeNames.RECIPE) Recipe recipe,
            @ModelAttribute(AttributeNames.INGREDIENT_LIST) List<Ingredient> ingredientList){


        return "";
    }
}

服务:

package com.potatospy.reciply.business.service;

import com.potatospy.reciply.business.dao.entity.RecipeEntity;
import com.potatospy.reciply.business.dao.repository.RecipeRepository;
import com.potatospy.reciply.business.util.IDManager;
import com.potatospy.reciply.web.model.response.Unit;
import com.potatospy.reciply.web.model.response.Ingredient;
import com.potatospy.reciply.web.model.response.Recipe;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class RecipeServiceImpl implements RecipeService{


    @Value("${id.length}")
    private int idLength;

    @Autowired
    private RecipeRepository recipeRepository;

    @Autowired
    IDManager idManager;

    List<Recipe> inMemRecipeList = new ArrayList<>();  // In-memory list of recipes


    // Get all Recipes from DB, load into list of Recipes, return list
    @Override
    public List<Recipe> getAllRecipes() {

        // "Clear" the list
        inMemRecipeList = new ArrayList<>();


        // Retrieve recipes from DB and add to In-memory list
        for(RecipeEntity recipeDbEntity : recipeRepository.findAll()){

            Recipe recipe = new Recipe();
            BeanUtils.copyProperties(recipeDbEntity, recipe);

            inMemRecipeList.add(recipe);
        }


        log.info("Returning list from getAllRecipes : {}", inMemRecipeList);
        return inMemRecipeList;
    }


    // Save a recipe and log
    @Override
    public RecipeEntity addRecipeToDb(RecipeEntity recipeToSave) {

        log.info("Saved recipe with ID: " + recipeToSave.getRecipeId());

        return recipeRepository.save(recipeToSave);
    }


    // == Create new blank Recipe, save to DB and memory and return ==

    public Recipe initNewRecipe(){

        // Create a new recipe
        Recipe newRecipe = new Recipe();
        newRecipe.setRecipeId(generateId());
        newRecipe.setRecipeName("Hamblargers");

        // Add a blank ingredient FOR TESTING to the Recipe
        Ingredient blankIngredient = new Ingredient(
                0L,
                0.0,
                Unit.CUPS,
                ""
        );

        newRecipe.getIngredientList().add(blankIngredient);


        // Save it to DB and return the result
        RecipeEntity newRecipeEntity = new RecipeEntity();
        BeanUtils.copyProperties(newRecipe, newRecipeEntity);

        Recipe returnableRecipe = new Recipe();
        BeanUtils.copyProperties(addRecipeToDb(newRecipeEntity), returnableRecipe);

        getAllRecipes();    // Update memory TODO This should be all automatic!


        log.info("New recipe created with id {}", returnableRecipe.getRecipeId());

        return returnableRecipe;
    }


    // Delete a recipe and log
    @Override
    public void delete(Recipe recipeToDelete) {

        RecipeEntity recipeEntityToDelete = new RecipeEntity();

        log.info("Deleting recipe with ID: {}  There is no undo at this time.",
                recipeToDelete.getRecipeId());

        recipeRepository.delete(recipeEntityToDelete);
    }


    @Override
    public Long generateId() {
        log.info("Service Generating Generic ID with length {}", idLength);

        return (idManager.generateId(idLength));   // Return string via service
    }
}

最佳答案

我的 Recipe 对象 Ingredient ArrayList 的大小为 0!

我在服务中的初始化似乎不起作用。

关于java - 提交表单时收到接口(interface) java.util.List 未找到主要或默认构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57452965/

相关文章:

java - 为什么在catch block 中使用bitwise or来处理java中的异常?

java - 将大的 csv 文件加载到 redis

java - 创建后如何在 JTextField 中设置新文本?

java - 是否有更好的解决方案将大量字段实体映射到两个表中?

java - Sql Server 连接关闭

要动画化的 Java TrayIcon 图像

java - @Transactional 不适用于方法级别

java - spring thymeleaf 按字母顺序对枚举进行排序

java - Spring Boot 与 thymeleaf 方法不调用

validation - 如何从表单中的集合中选择实体? Spring MVC 和 Thymeleaf