1

I've been researching for days and none of them worked for me. Most of what I got from the Internet was jsp, but I'm using Thymeleaf. What I'm trying to write is a generic type of CRUD which takes in any class and its variables to become the view page's field labels and inputs.

However, every time I try to submit the form which is filled out, it saves on the database but only the ID is not null, all else is of null value.

Here's my method which has the annotation of @ModelAttribute:

@ModelAttribute
public void instantiateEntity(Model model,
      @RequestParam("entityName") String entityName)
      throws Exception {

String className = SimpleEntity.NAMEPREF + entityName;
SimpleEntity entity =
        (SimpleEntity) Class.forName(className).getDeclaredConstructor().newInstance();

 Field[] fields = Class.forName(className).getDeclaredFields();
 List<FieldUI> fieldUISpecs = new ArrayList<>();

   for (Field f : fields) {
     System.out.println(f.getName());
     FieldUI fieldUI = new FieldUI(f);
     UI ui = f.getAnnotation(UI.class);
     if (ui != null){
       fieldUI.setColHeading(ui.colHeading());
       fieldUI.setFldPrompt(ui.fldPrompt());
       fieldUI.setCss(ui.css());
       fieldUI.setInputHidden(ui.inputHidden());
       fieldUI.setColHidden(ui.colHidden());
       fieldUI.setType(ui.type());

       if(!ui.option().equals("")){
        fieldUI.setOption(entityDBA.listEntities(ui.option()));
        System.out.println(fieldUI.getOption());
       }

       System.out.println("\n --- CSS: "+fieldUI.getCss());

    } else {
      fieldUI.setColHeading(f.getName());
      fieldUI.setFldPrompt(f.getName());
      fieldUI.setColHidden(false);
      fieldUI.setInputHidden(false);

    }
    fieldUISpecs.add(fieldUI);
  }

  List<SimpleEntity> entities = entityDBA.listEntities(entityName);

  model.addAttribute("fieldUISpecs", fieldUISpecs);
  model.addAttribute("entity", entity);
  model.addAttribute("entities", entities);
  model.addAttribute("currentEntity", entityName);
  model.addAttribute("displayAddButton", true);
  model.addAttribute("displayList", true);

 }

Here's my controller for the saving:

@PostMapping("/add") 
public String addEntity(@Valid @ModelAttribute("entity") SimpleEntity entity, BindingResult result, Model model, @RequestParam("entityName") String entityName){

    List<SimpleEntity> entities = db.listEntities(entityName);
    model.addAttribute("displayList", true);
    System.out.println("Entity values: "+entityName);

    if (result.hasErrors()) {
      model.addAttribute("displayForm", true);
      model.addAttribute("isNew", true);

      return "th_home";
    }

    db.saveEntity(entity);

    return "redirect:/list-edit-entities?entityName="+entityName;}

    //Here's my transactional or service layer:

    public long saveEntity(SimpleEntity entity) {
        long id = 0;
        Session ses = sf.getCurrentSession();
        if (entity.getId() == 0) ses.persist(entity);
        else ses.merge(entity);
        return entity.getId();
    }

here's my view:

<form th:if="${isNew}" method="POST" th:action="@{'/add?entityName='+${currentEntity}}" th:object="${entity}">
<th:block th:each="field: ${fieldUISpecs}">
    <div class="input-group" th:unless="${field.inputHidden}">
      <label th:unless="${field.name} == 'id'" th:text="${field.name}"></label>

        <input type="hidden" th:if="${field.name} == 'id'" class="c-form" th:field="*{__${field.name}__}" readonly>
        <input th:type="${field.type}" th:unless="${field.name} == 'id'" class="c-form" th:field="*{__${field.name}__}">
      </th:block>
    </div>
  </th:block>
  <div class="input-group input-button">
    <input class="save-button" type="submit" value="Save">
  </div>
</form>
Neil
  • 65
  • 7

1 Answers1

0

You're using @ModelAttribute that's the reason you're receiving null values on your controller after submit.

On your controller where you're requesting for the view page, you need to send your SimpleEntity object.

For Eg. -

Step 1 -

@RequestMapping("/openRequestedPage")
   public String addReferralPack(Model model) { 
   model.addAttribute("simpleEntityObject", new SimpleEntity());
   return "openRequestedPage";
} 

Step 2 -

<form th:if="${isNew}" method="POST" th:action="@{'/add?entityName='+${currentEntity}}"  th:object="${simpleEntityObject}"">

     //Some Code

</form>

Step 3

@PostMapping("/add") 
public String addEntity(@Valid @ModelAttribute("simpleEntityObject") SimpleEntity entity, BindingResult result, Model model, @RequestParam("entityName") String entityName){

     //some code
     return "yourPageName";

}

For information on @ModelAttribute ,here's a link -

What is @ModelAttribute in Spring MVC?

And here's a reference on how does it works -

https://www.baeldung.com/spring-mvc-and-the-modelattribute-annotation][1]

Sumit
  • 917
  • 1
  • 7
  • 18
  • Yeah I am using **@ModelAttribute**, but if I try to remove it on the `@Postmapping("/add")`, the whole part of adding won't work when the system runs. I just want to get the input values of the user but i don't know how. :/ – Neil Sep 13 '19 at 14:33
  • Edited my answer, please have a look . I hope it'd help you out. – Sumit Sep 16 '19 at 06:45
  • Hi @Sumit Thank you for your time. I tried what you said regarding the sending of my SimpleEntity object, but it asks for me to always implement methods. I'm not sure if I'm supposed to write this `new SimpleEntity()` on my **@ModelAttribute** instantiation method or on the form opener method I wrote – Neil Sep 16 '19 at 07:24
  • I edited my question @Sumit so you can see where all the values resets to null upon submitting the form. – Neil Sep 16 '19 at 07:31
  • The object's reference name has to be same everywhere - on both of the controllers and on the form as well. Please check the 'SimpleEntity' object reference name. – Sumit Sep 16 '19 at 07:49
  • Yes it's all the same, it's just that because of my method instantiateEntity() which has the **@ModelAttribute** as shown above, the values are all reset to null – Neil Sep 16 '19 at 07:55