3

My problem is very similar with this one: Spring MVC Multiple Controllers with same @RequestMapping

I'm building simple Human Resources web application with Spring Boot. I have a list of jobs and individual url for each job:

localhost:8080/jobs/1

This page contains job posting details and a form which unauthenticated users -applicants, in this case- can use to apply this job. Authenticated users -HR Manager-, can see only posting details, not the form. I have trouble with validating form inputs.

What I tried first:

@Controller
public class ApplicationController {

    private final AppService appService;

    @Autowired
    public ApplicationController(AppService appService) {
        this.appService = appService;
    }

    @RequestMapping(value = "/jobs/{id}", method = RequestMethod.POST)
    public String handleApplyForm(@PathVariable Long id, @Valid @ModelAttribute("form") ApplyForm form, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return "job_detail"; //HTML page which contains job details and the application form
        }
        appService.apply(form, id);
        return "redirect:/jobs";
    }

    @RequestMapping(value = "/applications/{id}", method = RequestMethod.GET)
    public ModelAndView getApplicationPage(@PathVariable Long id) {
        if (null == appService.getAppById(id)) {
            throw new NoSuchElementException(String.format("Application=%s not found", id));
        } else {
            return new ModelAndView("application_detail", "app", appService.getAppById(id));
        }
    }
}

As you guess this didn't work because I couldn't get the models. So I put handleApplyForm() to JobController and changed a little bit:

@Controller
public class JobController {

    private final JobService jobService;
    private final AppService appService;

    @Autowired
    public JobController(JobService jobService, AppService appService) {
        this.jobService = jobService;
        this.appService = appService;
    }

    @RequestMapping(value = "/jobs/{id}", method = RequestMethod.POST)
    public ModelAndView handleApplyForm(@PathVariable Long id, @Valid @ModelAttribute("form") ApplyForm form, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return getJobPage(id);
        }

        appService.apply(form, id);
        return new ModelAndView("redirect:/jobs");
    }

    @RequestMapping(value = "/jobs/{id}", method = RequestMethod.GET)
    public ModelAndView getJobPage(@PathVariable Long id) {
        Map<String, Object> model = new HashMap<String, Object>();

        if (null == jobService.getJobById(id)) {
            throw new NoSuchElementException(String.format("Job=%s not found", id));
        } else {
            model.put("job", jobService.getJobById(id));
            model.put("form", new ApplyForm());
        }

        return new ModelAndView("job_detail", model);
    }
}

With this way, validations works but I still can't get the same effect here as it refreshes the page so that all valid inputs disappear and error messages don't appear.

By the way, job_detail.html is like this:

<h1>Job Details</h1>
<p th:inline="text"><strong>Title:</strong> [[${job.title}]]</p>
<p th:inline="text"><strong>Description:</strong> [[${job.description}]]</p>
<p th:inline="text"><strong>Number of people to hire:</strong> [[${job.numPeopleToHire}]]</p>
<p th:inline="text"><strong>Last application date:</strong> [[${job.lastDate}]]</p>

<div sec:authorize="isAuthenticated()">
    <form th:action="@{/jobs/} + ${job.id}" method="post">
        <input type="submit" value="Delete this posting" name="delete" />
    </form>
 </div>

<div sec:authorize="isAnonymous()">
    <h1>Application Form</h1>
    <form action="#" th:action="@{/jobs/} + ${job.id}" method="post">
        <div>
            <label>First name</label>
            <input type="text" name="firstName" th:value="${form.firstName}" />
            <td th:if="${#fields.hasErrors('form.firstName')}" th:errors="${form.firstName}"></td>
        </div>

        <!-- and other input fields -->

        <input type="submit" value="Submit" name="apply" /> <input type="reset" value="Reset" />
    </form>
</div>

1 Answer 1

0

Check thymeleaf documentation here

Values for th:field attributes must be selection expressions (*{...}),

Also ApplyForm is exposed then you can catch it in the form.

Then your form should looks like this:

<form action="#" th:action="@{/jobs/} + ${job.id}" th:object="${applyForm}" method="post">
        <div>
            <label>First name</label>
            <input type="text" name="firstName" th:value="*{firstName}" />
            <td th:if="${#fields.hasErrors('firstName')}" th:errors="*{firstName}"></td>
        </div>

        <!-- and other input fields -->

        <input type="submit" value="Submit" name="apply" /> <input type="reset" value="Reset" />
</form>
Sign up to request clarification or add additional context in comments.

1 Comment

It didn't change anything man. I don't think that problem is showing error messages. If problem was this, valid inputs wouldn't disappear. Problem is refreshing of page as I call getJobPage() method in handleApplyForm(). But this is the only way validation works, I don't know how to control it otherwise.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.