2
votes

I'm creating a MVC application using Spring Boot 2 and Thymeleaf.

I got some trouble with creating a form for a complex object. I got my class MedicalJournalEntry, which holds some primitive attributes and also a nested object of class BloodPressure (association). Here you can see both classes:

Class MedicalJournalEntry:

@Entity
@Table(name="MED_JOURNAL_ENTRY")
public class MedicalJournalEntry extends JournalEntry{


/*
 * The following attributes are inherited from the superclass JournalEntry
 * intJournalEntryId
 * datJournalEntryDate
 * tstmpJournalEntryCreateDate
 * tstmpJournalEntryUpdateDate
 * 
 * getters and setters are defined and implemented in the superclass JournalEntry as well
 * 
 */
@Embedded
private BloodPressure bloodPressure;

@ManyToOne
@JoinColumn(name = "JOURNAL_ID")
@JsonBackReference
private MedicalJournal medJournal; // bidirectional relationship with entity MedicalJournal

@Column(name="JOURNAL_ENTRY_PULSE")
private short shPulse; 
@Column(name="JOURNAL_ENTRY_HEIGHT")
@Min(value = 1, message="Die Größe muss größer als 1cm sein.")
@Max(value = 300, message="Die Größe muss kleiner als 300cm sein.")
private short shHeight; // in centimeters
@Column(name="JOURNAL_ENTRY_WEIGHT")
@Min(value = 1, message="Das Gewicht muss größer als 1kg sein.")
@Max(value = 500, message="Das Gewicht muss kleiner als 500kg sein.")
private short shWeight; // in kilograms
@Column(name="JOURNAL_ENTRY_BMI")
private float fltBmi;
@Column(name="JOURNAL_ENTRY_IS_SICK")
private boolean blnIsSick;

// constructors and methods ...
}

Class BloodPressure:

@Embeddable // is part of MedicalJournalEntry
public class BloodPressure {

public BloodPressure(int intSYS, int intDIA) {
    this.intSYS = intSYS;
    this.intDIA = intDIA;
}
@Column(name ="BLOOD_PRESSURE_SYS")
private int intSYS;
@Column(name = "BLOOD_PRESSURE_DIA")
private int intDIA;
// constructors and mehtods ...
}

I've created a form using a fragment. It works really good for the "normal" fields, but since i added the nested objects fields, Thymeleaf cannot even create the view which holds the form anymore. I always get the following error when i want to show the form:

Error during execution of processor

org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "create-medJournalEntry"

My thymeleaf form looks like this:

    <form action = "#" th:action="@{/medJourEntry/add}" th:object=${medicalJournalEntry} method ="post">

    <div th:replace="edit-medJournalEntry.html :: medEntryForm(medEntry=${#object})"></div>


    <button type="submit" class="btn btn-primary">Tagebucheintrag erstellen</button>

    <button type="reset" class="btn btn-primary">Felder zurücksetzen</button>

    </form>

And the corresponding content of the fragment which causes problems:

        </div>

            <div class ="form-row">

                <div class="form-group col-md-4">

                    <label for="bloodpressureSys">Blutdruck systolisch</label>

                    <input type="text" th:field="*{bloodPressure.intSys}" class="form-control" id="bloodpressureSys" aria-describedby="bloodpressureSystHelp" placeholder="Systolischer Blutdruck">

                    <div th:if="${#fields.hasErrors('${medicalJournalEntry.bloodPressure.intSys}')}">
                        <div class="alert alert-danger" role="alert">
                            <p th:each="err : ${#fields.errors('bloodPressure.intSys')}" th:text="${err}"></p>
                        </div>
                    </div>

                    <small id="bloodpressureSystHelp" class="form-text text-muted">Bitte tragen Sie den systolischen Blutdruck (in mmHg) ein.</small>

                </div>

            <div class="form-group col-md-4">

                    <label for="bloodpressureDia">Blutdruck Diastolisch</label>

                    <input type = "text" th:field="*{bloodPressure.intDia}" class="form-control" id="bloodpressureDia" aria-describedby="bloodpressureDiaHelp" placeholder="Diastolischer Blutdruck">

                    <small id="bloodpressureDiaHelp" class="form-text text-muted">Bitte tragen Sie den diastolischen Blutdruck (in mmHg) ein.</small>

            </div>
        </div>

This is my controller. It only returns the view which holds the form the enter data for a new MedicalJournalEntry:

@RequestMapping(value="/create", method = RequestMethod.GET)
public String showCreateMedicalJournalEntryForm(MedicalJournalEntry medicalJournalEntry) {

    return "create-medJournalEntry";
}
1
To clarify, this only happens if you include the fragment? And you do not have the same issue if you include the HTML in the 'template'? Could you also share your controller please for this? - Kyan
You need to include the entire stack track. It will describe what the error is and where it occurs. - Metroids
Also, your properties are named intSYS and intDIA but in the html they are intSys and intDia. - Metroids
Yes i noticed the wrong attribute names as well, but that didn't fix the problem. I also put my Controller into the post. The thing ist: I assume that Thymeleaf is not able to create 2 objects in one form. They also write it in their documentation: thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#preface, citation: "Once inside the <form> tag, no other th:object attribute can be specified. This is consistent with the fact that HTML forms cannot be nested." I couldn't even find someone who implemented an association with thymeleaf like I'm trying to do. Crazy in my opinion - Wallnussfolie
I cannot post the stack trace anymore because i changed my class structure. But I still would like to know how I can implement an association with thymeleaf (nested object). I mean, this MUST be possible somehow. Otherwise Thymeleaf would be a very weak technology^^. I just cannot find any information to that on the internet. - Wallnussfolie

1 Answers

1
votes

Thank you for everyone trying to help me!

We just figured out our problem.

The no-arg constructor of the MedicalJournalEntry class was missing the construction of an emtpy BloodPressure object. This is mandatory, because otherwise basically you get some kind of NullPointerException because the child object is just not alive.

So the problem is fixed. Thank you everyone again, really appreciate that! :)