Spring MVC Sorting / searchbar - spring

Im trying to implement that if you click on a column header it will automatically order the various items on that specific header, I know I have to use paging and sorting repo but I can't find an example to help me out..
Relevant Controller info
public class BookController {
private final BookServiceImpl bookService;
private final AuthorServiceImpl authorService;
private final OntleningService ontleningService;
private final UserServiceImpl userService;
private final ReviewServiceImpl reviewService;
private final FileStorageServiceImpl fileStorageService;
#ModelAttribute("books")
public Page<Book> getBooks(#PageableDefault(size = 25) Pageable page) {
return bookService.findAll(page);
}
#GetMapping("/books")
public String bookView(Model model, Principal principal) {
model.addAttribute("ontlening", new Ontlening());
model.addAttribute("bookservice", bookService);
model.addAttribute("reviewService", reviewService);
String username = principal.getName();
User ingelogdeGebruiker = userService.retrieveByUsername(username);
Ontlening laatsteOntleningVanGebruiker = userService.laatsteOntleningVanGebruiker(username);
model.addAttribute("laatsteOntleningVanGebruiker", laatsteOntleningVanGebruiker);
model.addAttribute("ingelogdeGebruiker", ingelogdeGebruiker);
return "books";
}
Service:
public class BookServiceImpl implements BookService {
private final BookRepository bookRepository;
private final FileStorageServiceImpl fileStorageService;
#Override
public void register(Book book) {
bookRepository.save(book);
}
#Override
public void delete(Book book) {
bookRepository.delete(book);
}
#Override
public List<Book> retrieveAll() {
List<Book> books = (List<Book>) bookRepository.findAll();
return books;
}
public Page<Book> findAll(Pageable pageable) {
return bookRepository.findAll(pageable);
}
public class BookServiceImpl implements BookService {
private final BookRepository bookRepository;
private final FileStorageServiceImpl fileStorageService;
#Override
public void register(Book book) {
bookRepository.save(book);
}
#Override
public void delete(Book book) {
bookRepository.delete(book);
}
#Override
public List<Book> retrieveAll() {
List<Book> books = (List<Book>) bookRepository.findAll();
return books;
}
public Page<Book> findAll(Pageable pageable) {
return bookRepository.findAll(pageable);
}
public class BookServiceImpl implements BookService {
private final BookRepository bookRepository;
private final FileStorageServiceImpl fileStorageService;
#Override
public void register(Book book) {
bookRepository.save(book);
}
#Override
public void delete(Book book) {
bookRepository.delete(book);
}
#Override
public List<Book> retrieveAll() {
List<Book> books = (List<Book>) bookRepository.findAll();
return books;
}
public Page<Book> findAll(Pageable pageable) {
return bookRepository.findAll(pageable);
}
View:
<!DOCTYPE html>
<html lang="nl"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>boeken</title>
<th:block th:include="fragments/cdn::custom-style"></th:block>
<th:block th:include="fragments/cdn::bootstrap-style"> </th:block>
</head>
<body>
<header th:replace="fragments/header::header"></header>
<div class="col-8 m-auto innerbackground text-center">
<h2>Alle beschikbare boeken in de klasbibliotheek: </h2>
<form method="post" enctype="multipart/form-data">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
<a type="button" class="btn btn-primary m-2" th:href="#{'/books/new'}" sec:authorize="hasRole('ROLE_ADMIN')"> New </a>
<button type="submit" class="btn btn-danger m-2" name ="delete" value="true" sec:authorize="hasRole('ROLE_ADMIN')"> Delete </button>
<button type="submit" class="btn btn-success m-2" name ="ontleen" value="true" th:if="${ingelogdeGebruiker.getOntleningen().isEmpty()||laatsteOntleningVanGebruiker.datumTerugbrengen!=null}" sec:authorize="hasRole('ROLE_USER')"> Ontlenen </button>
<button type="submit" class="btn btn-success m-2" name ="terugbrengen" value="true" th:if="${!ingelogdeGebruiker.getOntleningen().isEmpty() && laatsteOntleningVanGebruiker.datumTerugbrengen == null}"> Boek terugbrengen </button>
<table class="table table-striped table-hover table align-middle" sec:authorize="hasRole('ROLE_USER')">
<tr>
<th>Selecteer </th>
<th>Cover</th>
<th> Titel</th>
<th> Jouw score</th>
</tr>
<tr th:each="book:${books}" th:if="${book.beschikbaar == true}">
<td class="text-center"><input type="radio" class="form-check-input" name="selection" th:value="${book.id}"></td>
<td><a th:href="#{'/books/'+ ${book.id}}"><img th:src="#{/img/{filename}(filename=${book.fotoFile})}"></a></td>
<td><a th:href="#{'/books/'+ ${book.id}}" th:text="${book.title}"></a></td>
<td><a th:href="#{'/books/'+ ${book.id}}" th:if="${!reviewService.findScoreByBookAndUser(ingelogdeGebruiker.id,book.id).isEmpty()}"><span th:text="${reviewService.findScoreByBookAndUser(ingelogdeGebruiker.id,book.id).get()+'/5'}"></span></a>
</tr>
</table>
<table class="table table-striped table-hover table align-middle" sec:authorize="hasRole('ROLE_ADMIN')">
<tr>
<th>Selecteer </th>
<th>Cover </th>
<th> Titel</th>
<th> Ontleend door</th>
<th> Gemiddelde score</th>
<th> aantal reviews</th>
</tr>
<tr th:each="book:${books}">
<td><input type="checkbox" class="form-check-input" name="selection" th:value="${book.id}"></td>
<td th:if="${!book.fotoFile.isEmpty()}"><a th:href="#{'/books/'+ ${book.id}}" ><img th:src="#{/img/{filename}(filename=${book.fotoFile})}"></a></td>
<td><a th:href="#{'/books/'+ ${book.id}}" th:text="${book.title}"></a></td>
<td><a th:href="#{'/books/'+ ${book.id}}" th:if="${!book.getOntleningen().isEmpty() &&bookservice.laatsteOntleningVanBoek(book.id).datumTerugbrengen == null}"th:text="${bookservice.laatsteOntleningVanBoek(book.id).user.username}"></a><span><a th:href="#{'/books/'+ ${book.id}}" th:if="${book.beschikbaar==true}"> Niet uitgeleend</a></span></td>
<td><a th:href="#{'/books/'+ ${book.id}}" th:if="${!book.reviews.isEmpty()}"th:text="${#numbers.formatDecimal(book.berekenGemiddeldeScoreReview(),1,1,'COMMA')+' /5'}"></a> <span th:if="${book.reviews.isEmpty()}">Nog geen review</span> </td>
<td><a th:href="#{'/books/'+ ${book.id}}" th:if="${!book.reviews.isEmpty()}" th:text="${book.bepaalAantalReviews()}"></a> <span th:if="${book.reviews.isEmpty()}">0</span></td>
</tr>
</table>
<nav aria-label="Page navigation example">
<ul class="pagination">
<li class="page-item" th:classappend="${books.first} ? 'disabled'"><a class="page-link" th:href="#{books(page=${books.number -1})}">Vorige</a></li>
<li class="page-item" th:each="page:${#numbers.sequence(0,books.totalPages-1)}" th:classappend="${books.number} == ${page} ? 'active'"><a class="page-link" th:href="#{books(page=${page})}" th:text="${page+1}"></a></li>
<li class="page-item" th:classappend="${books.last} ? 'disabled'"><a class="page-link" th:href="#{books(page=${books.number +1})}">Volgende</a></li>
</ul>
</nav>
</form>
<th:block th:include="fragments/cdn::bootstrap-script"></th:block>
</div>
</body>
</html>
Originally i tried to implement a searchbar however this ruins my entire program:
When submitting the request I got a lot of errors (see below)
his application has no explicit mapping for /error, so you are seeing this as a fallback.
Wed Oct 05 18:08:37 CEST 2022
There was an unexpected error (type=Bad Request, status=400).
Parameter conditions "terugbrengen=true" OR "delete=true" OR "ontleen=true" not met for actual request parameters: _csrf={140d2c26-4105-4f01-8579-17728161c5be}, zoekterm={}
org.springframework.web.bind.UnsatisfiedServletRequestParameterException: Parameter conditions "terugbrengen=true" OR "delete=true" OR "ontleen=true" not met for actual request parameters: _csrf={140d2c26-4105-4f01-8579-17728161c5be}, zoekterm={}
at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.handleNoMatch(RequestMappingInfoHandlerMapping.java:277)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(AbstractHandlerMethodMapping.java:442)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:383)
at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.getHandlerInternal(RequestMappingInfoHandlerMapping.java:125)
at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.getHandlerInternal(RequestMappingInfoHandlerMapping.java:67)
at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:498)
at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1264)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1046)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:337)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:122)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:109)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:223)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:217)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:132)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:112)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:82)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:221)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:186)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:834)
If anyone would know how to make the searchbar work that would be obv the best, but at this point i'd settle for a sorting function..
Thanks in advance!

Related

Livewire Is not able to store

I have four laravel live wire components. The first component is Step1 which has the values `
`class Step1 extends Component
{
public $firstName;
public $lastName;
public $middleName;
public $prefix;
public $suffix;
public $dateofbirth;
public $gender;
public $phonenumber;
public $emailaddress;
public $step;
public function mount()
{
$this->step = 1;
}
public function nextStep()
{
$this->step++;
}
public function prevStep()
{
$this->step--;
}
public function render()
{
return view('livewire.step1');
}
}
`
Step 2
'<?php
namespace App\Http\Livewire;
use Livewire\Component;
class Step2 extends Component
{
public $step;
public $contact_last_name;
public $contact_first_name;
public $contact_address_one;
public $contact_address_two;
public $contact_country;
public $contact_province;
public $contact_city;
public $contact_email;
public $emergency_phone_coder;
public $citizen_bio_id;
public function mount()
{
$this->step = 2;
}
public function nextStep()
{
$this->step++;
}
public function prevStep()
{
$this->step--;
}
public function render()
{
return view('livewire.step2');
}
`
and step 3
<?php
namespace App\\Http\\Livewire;
use Livewire\\Component;
class Step3 extends Component
{
public $step;
public $country;
public $state;
public $message;
public $date_of_travel;
public $date_of_return;
public $purpose_of_travel;
public $citizen_bio_id;
public function mount()
{
$this->step = 2;
}
public function nextStep()
{
$this->step++;
}
public function prevStep()
{
$this->step--;
}
public function render()
{
return view('livewire.step3');
}
}`
All these steps are managed in the FormWizard Component
`<?php
namespace App\\Http\\Livewire;
use App\\Models\\CitizenBio;
use Illuminate\\Support\\Facades\\DB;
use Livewire\\Component;
class FormWizard extends Component
{
public $step;
public $firstName;
public $lastName;
public $middleName;
public $prefix;
public $suffix;
public $dateofbirth;
public $gender;
public $phonenumber;
public $emailaddress;
public $contact_last_name;
public $contact_first_name;
public $contact_address_one;
public $contact_address_two;
public $contact_country;
public $contact_province;
public $contact_city;
public $contact_email;
public $emergency_phone_coder;
public $country;
public $state;
public $message;
public $date_of_travel;
public $date_of_return;
public $purpose_of_travel;
public function mount()
{
$this->step = 1;
}
public function nextStep()
{
$this->step++;
}
public function prevStep()
{
$this->step--;
}
public function render()
{
return view('livewire.form-wizard', ['step' => $this->step]);
}
public function store()
{
$data = [
'first_name' => session('firstName'),
'last_name' => session('lastName'),
'middle_name' => session('middleName'),
'prefix' => session('prefix'),
'suffix' => session('suffix'),
'date_of_birth' => session('dateOfBirth'),
'gender' => session('gender'),
'phone_number' => session('phonenumber'),
'email_address' => session('emailaddress'),
// ...
];
DB::table('citizen_bios')->insert($data);
$this->reset();
return redirect()->route('/dashboard');
}
public function debug()
{
return $this->step;
}
}`
When a user clicks the submit form that is linked to the FormWizard Component to run the store function It does not store the data into the DB.
I checked to make sure I've linked the component to the correct input which I believe I did as so
`<form>
<div class="grid gap-6 mb-6 md:grid-cols-3">
<div>
<label for="first_name" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">First name</label>
<input wire:model="firstName" wire:error.class="invalid" type="text" name="first_name" id="first_name" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-black dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="Kwesi" required>
</div>
`
and in the FormWizard.blade this is how it looks
<div wire:loading.remove>
<form method="POST" action="{{ route('store')}}" id="postCitizen" accept-charset="UTF-8" style="display:inline-block">
#csrf
#method("POST")
#if ($step === 1)
#livewire('step1')
<div class="grid gap-6 mb-6 md:grid-cols-1">
<button wire:click="nextStep" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-white-600 dark:hover:bg-white-700 dark:focus:ring-white-800">Next</button>
</div>
#elseif ($step === 2)
#livewire('step2')
<div class="grid gap-6 mb-6 md:grid-cols-2">
<button wire:click="prevStep" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-white-600 dark:hover:bg-white-700 dark:focus:ring-white-800">Previous</button>
<button wire:click="nextStep" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-white-600 dark:hover:bg-white-700 dark:focus:ring-white-800">Next</button>
</div>
#elseif ($step === 3)
#livewire('step3')
<div class="grid gap-6 mb-6 md:grid-cols-2">
<button wire:click="prevStep" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-white-600 dark:hover:bg-white-700 dark:focus:ring-white-800">Previous</button>
<button wire:click="store" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Submit</button>
</div>
#endif
</form>
<div>
{{$this->debug()}}
</div>
</div>`
I tried change how the store function runs, and I've made sure the blade fire uses wire:model="firstName". What i don't know where the issues is coming from that when I click the submit button all my values say null even though I've typed in it.

In browser i couldn't get Boot Strap tables instead i get white label error

In Spring Boot, earlier, I've created Employee Management System Table with 4 Columns -> firtsname, lastname, email and Actions column where it has Update&Delete Buttons. now, I've added extra 3 Columns -> gender, birthday, skill. Everything works fine, there is no compilation Errors and console errors but when i hit the browser i get whitelabel error. can anyone please give me a solution for this problem.
1.Employee Entity.Class
package com.employee.entity;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "employees")
public class Employee
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String firstname;
private String lastname;
private String email;
private String gender;
private Date birthday;
private String skill;
public Employee() {
}
public Employee(long id, String firstname, String lastname, String email, String gender, Date birthday,
String skill) {
super();
this.id = id;
this.firstname = firstname;
this.lastname = lastname;
this.email = email;
this.gender = gender;
this.birthday = birthday;
this.skill = skill;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}
}
2.EmployeeController.class
package com.employee.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import com.employee.entity.Employee;
import com.employee.service.EmployeeService;
#Controller // Controller Layer holds all Spring MVC Controllers
public class EmployeeController
{
private EmployeeService employeeService;
public EmployeeController(EmployeeService employeeService) {
super();
this.employeeService = employeeService;
}
#GetMapping("/employees")
public String listEmployess(Model model)
{
model.addAttribute("employees", employeeService.getAllEmployees());
return "employees";
}
#GetMapping("/employees/new")
public String createEmployeeForm(Model model)
{
//Create empty employee object to hold employee form data
Employee employee = new Employee();
model.addAttribute("employee", employee);
return "create_employee";
}
#PostMapping("/employees")
public String saveEmployee(#ModelAttribute("employee") Employee employee)
{
employeeService.saveEmployee(employee);
return "redirect:/employees";
}
#GetMapping("/employees/edit/{id}")
public String editEmployeeForm(#PathVariable Long id, Model model)
{
model.addAttribute("employee", employeeService.getEmployeeById(id));
return "edit_employee";
}
#PostMapping("/employees/{id}")
public String updateEmployee(#PathVariable Long id, #ModelAttribute("employee") Employee employee, Model model)
{
// get employee from database by id
Employee existingEmployee = employeeService.getEmployeeById(id);
//existingEmployee.setId(id);
existingEmployee.setFirstname(employee.getFirstname());
existingEmployee.setLastname(employee.getLastname());
existingEmployee.setEmail(employee.getEmail());
existingEmployee.setGender(employee.getGender());
existingEmployee.setBirthday(employee.getBirthday());
existingEmployee.setSkill(employee.getSkill());
// save updated employee object
employeeService.updateEmployee(existingEmployee);
return "redirect:/employees";
}
#GetMapping("/employees/{id}")
public String deleteEmployee(#PathVariable Long id)
{
employeeService.deleteEmployeeById(id);
return "redirect:/employees";
}
}
3.EmployeeRepository.interface
package com.employee.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.employee.entity.Employee;
#Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long>
{
}
4.EmployeeService.interface
package com.employee.service;
import java.util.List;
import com.employee.entity.Employee;
public interface EmployeeService
{
public List<Employee> getAllEmployees();
Employee saveEmployee(Employee employee);
Employee getEmployeeById(Long id);
Employee updateEmployee(Employee employee);
void deleteEmployeeById(Long id);
}
5.EmployeeServiceImpl.class
package com.employee.service.impl;
import java.util.List;
import org.springframework.stereotype.Service;
import com.employee.entity.Employee;
import com.employee.repository.EmployeeRepository;
import com.employee.service.EmployeeService;
#Service
public class EmployeeServiceImpl implements EmployeeService
{
private EmployeeRepository employeeRepository;
public EmployeeServiceImpl(EmployeeRepository employeeRepository) {
super();
this.employeeRepository = employeeRepository;
}
#Override
public List<Employee> getAllEmployees()
{
return employeeRepository.findAll();
}
#Override
public Employee saveEmployee(Employee employee)
{
return employeeRepository.save(employee);
}
#Override
public Employee getEmployeeById(Long id) {
return employeeRepository.findById(id).get();
}
#Override
public Employee updateEmployee(Employee employee) {
return employeeRepository.save(employee);
}
#Override
public void deleteEmployeeById(Long id)
{
employeeRepository.deleteById(id);
}
}
6.application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/ems?useSSL=false&serverTime=UTC&useLegacyDatetimeCode=false
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=1441
server.port=8097
#spring.jpa.database-platform = org.hibernate.dialect.MySQL5Dialect
#spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.thymeleaf.check-template=true
spring.thymeleaf.check-template-location=true
spring.thymeleaf.enabled=true
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
debug=true
logging.level.org.hibernate.SQL=DEBUG
#logging.level.<package_name>=<LOGGING_LEVEL>
#logging.level.org.springframework.context=DEBUG
spring.profiles.active=#spring.profiles.active#
spring.jpa.open-in-view=false
logging.level.org.springframework.boot.autoconfigure=ERROR
7.employees.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-md bg-dark navbar-dark">
<!-- Brand -->
<a class="navbar-brand" href="#">Employee Management System</a>
<!-- Toggler/collapsibe Button -->
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsibleNavbar">
<span class="navbar-toggler-icon"></span>
</button>
<!-- Navbar links -->
<div class="collapse navbar-collapse" id="collapsibleNavbar">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" th:href="#{/employees}">Employee Management</a>
</li>
</ul>
</div>
</nav>
<div class ="container">
<div class = "row">
<h1> List Employees </h1>
</div>
<div class = "row" >
<div class = "col-lg-3">
<a th:href = "#{/employees/new}" class = "btn btn-primary btn-sm mb-3"> Add Employee</a>
</div>
</div>
<table class = "table table-striped table-bordered" >
<thead class = "table-dark">
<tr>
<th> Employee First Name </th>
<th> Employee Last Name </th>
<th> Employee Email </th>
<th> Employee Gender </th>
<th> Employee Birthday </th>
<th> Employee Skill </th>
<th> Actions </th>
</tr>
</thead>
<tbody>
<tr th:each = "employee : ${employees}">
<td th:text = "${employee.firstname}"></td>
<td th:text = "${employee.lastname}"></td>
<td th:text = "${employee.email}"></td>
<td th:text = "${employee.gender}"></td>
<td th:text = "${employee.birthday}"></td>
<td th:text = "${employee.skill}"></td>
<td>
<a th:href = "#{/employees/edit/{id}(id=${employee.id})}"
class = "btn btn-primary">Update</a>
<a th:href = "#{/employees/{id}(id=${employee.id})}"
class = "btn btn-danger">Delete</a>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
8.create_employee.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Employee Management System</title>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-md bg-dark navbar-dark">
<!-- Brand -->
<a class="navbar-brand" href="#">Employee Management System</a>
<!-- Toggler/collapsibe Button -->
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsibleNavbar">
<span class="navbar-toggler-icon"></span>
</button>
<!-- Navbar links -->
<div class="collapse navbar-collapse" id="collapsibleNavbar">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" th:href="#{/employees}">Employee Management</a>
</li>
</ul>
</div>
</nav>
<br>
<br>
<div class = "container">
<div class = "row">
<div class = "col-lg-6 col-md-6 col-sm-6 container justify-content-center-center card">
<h1 class = "text-center"> Create New Employee </h1>
<div class = "card-body" >
<form th:action="#{/employees}" th:object = "${employee}" method="POST">
<div class = "form-group">
<label> Employee First Name </label>
<input
type = "text"
name = "firstname"
th:field = "*{firstname}"
class = "form-control"
placeholder = "Enter Employee First Name"
/>
</div>
<div class = "form-group">
<label> Employee Last Name </label>
<input
type = "text"
name = "lastname"
th:field = "*{lastname}"
class = "form-control"
placeholder = "Enter Employee Last Name"
/>
</div>
<div class = "form-group">
<label> Employee Email </label>
<input
type = "text"
name = "email"
th:field = "*{email}"
class = "form-control"
placeholder = "Enter Employee Email"
/>
</div>
<div class = "form-group">
<label> Employee Gender </label>
<input type="radio" th:field="*{gender}" value="Male" />Male
<input type="radio" th:field="*{gender}" value="Female" />Female
<input
type = "radio"
name = "gender"
th:field = "*{gender}"
class = "form-control"
/>
</div>
<div class = "form-group">
<label> Employee Birthday </label>
<input type="date" th:field="*{birthday}" />
<input
type = "date"
name = "birthday"
th:field = "*{birthday}"
class = "form-control"
/>
</div>
<div class = "form-group">
<label> Employee Skill </label>
<input
type = "text"
name = "skill"
th:field = "*{skill}"
class = "form-control"
placeholder = "Enter Employee Skill"
/>
</div>
<div class = "box-footer">
<button type="submit" class = "btn btn-primary">
Submit
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
9.edit_employee.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Employee Management System</title>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-md bg-dark navbar-dark">
<!-- Brand -->
<a class="navbar-brand" href="#">Employee Management System</a>
<!-- Toggler/collapsibe Button -->
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsibleNavbar">
<span class="navbar-toggler-icon"></span>
</button>
<!-- Navbar links -->
<div class="collapse navbar-collapse" id="collapsibleNavbar">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" th:href="#{/employees}">Employee Management</a>
</li>
</ul>
</div>
</nav>
<br>
<br>
<div class = "container">
<div class = "row">
<div class = "col-lg-6 col-md-6 col-sm-6 container justify-content-center-center card">
<h1 class = "text-center"> Create New Employee </h1>
<div class = "card-body" >
<form th:action="#{/employees/{id} (id=${employee.id})}" th:object = "${employee}" method="POST">
<div class = "form-group">
<label> Employee First Name </label>
<input
type = "text"
name = "firstname"
th:field = "*{firstname}"
class = "form-control"
placeholder = "Enter Employee First Name"
/>
</div>
<div class = "form-group">
<label> Employee Last Name </label>
<input
type = "text"
name = "lastname"
th:field = "*{lastname}"
class = "form-control"
placeholder = "Enter Employee Last Name"
/>
</div>
<div class = "form-group">
<label> Employee Email </label>
<input
type = "text"
name = "email"
th:field = "*{email}"
class = "form-control"
placeholder = "Enter Employee Email"
/>
</div>
<div class = "form-group">
<label> Employee Gender </label>
<input type="radio" th:field="*{gender}" value="Male" />Male
<input type="radio" th:field="*{gender}" value="Female" />Female
<input
type = "radio"
name = "gender"
th:field = "*{gender}"
class = "form-control"
/>
</div>
<div class = "form-group">
<label> Employee Birthday </label>
<input type="date" th:field="*{birthday}" />
<input
type = "date"
name = "birthday"
th:field = "*{birthday}"
class = "form-control"
/>
</div>
<div class = "form-group">
<label> Employee Skill </label>
<input
type = "text"
name = "skill"
th:field = "*{skill}"
class = "form-control"
placeholder = "Enter Employee Skill"
/>
</div>
<div class = "box-footer">
<button type="submit" class = "btn btn-primary">
Submit
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
You just need to add mapping for /, which will redirect to the landing page (in your case employees page).
So, just add the following GET mapping in your EmployeeController
#GetMapping('/')
public String index() {
return "redirect:/employees";
}

How to use LocalDateTime

what is the right way to solve LocalDateTime error?
I am new to spring therefore I have tried to look for the way to solve this online but I cannot get around it.
This is my entity
package com.reserve.entities;
import java.time.LocalDateTime;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO;
#Entity
public class Flight extends AbstractEntity {
private String flightNumber;
private String operatingAirlines;
private String departureCity;
private String arrivalCity;
#DateTimeFormat(iso=ISO.DATE)
private Date dateOfDeparture;
#Column(name="estimatedDepartureTime",columnDefinition="TIMESTAMP")
private LocalDateTime estimatedDepartureTime;
public String getFlightNumber() {
return flightNumber;
}
public void setFlightNumber(String flightNumber) {
this.flightNumber = flightNumber;
}
public String getOperatingAirlines() {
return operatingAirlines;
}
public void setOperatingAirlines(String operatingAirlines) {
this.operatingAirlines = operatingAirlines;
}
public String getDepartureCity() {
return departureCity;
}
public void setDepartureCity(String departureCity) {
this.departureCity = departureCity;
}
public String getArrivalCity() {
return arrivalCity;
}
public void setArrivalCity(String arrivalCity) {
this.arrivalCity = arrivalCity;
}
public Date getDateOfDeparture() {
return dateOfDeparture;
}
public void setDateOfDeparture(Date dateOfDeparture) {
this.dateOfDeparture = dateOfDeparture;
}
public LocalDateTime getEstimatedDepartureTime() {
return estimatedDepartureTime;
}
public void setEstimatedDepartureTime(LocalDateTime estimatedDepartureTime) {
this.estimatedDepartureTime = estimatedDepartureTime;
}
#Override
public String toString() {
return "Flight [flightNumber=" + flightNumber + ", operatingAirlines=" + operatingAirlines + ", departureCity="
+ departureCity + ", arrivalCity=" + arrivalCity + ", dateOfDeparture=" + dateOfDeparture
+ ", estimatedDepartureTime=" + estimatedDepartureTime + "]";
}
}
This is my controller.
I am not sure which information is required.
Please let me know if there are more information that could help.
package com.reserve.controllers;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import com.reserve.entities.Flight;
import com.reserve.repository.FlightRepository;
#Controller
public class FlightController {
#Autowired
private FlightRepository flightRepository;
#RequestMapping("findFlights")
public String findFlights(
#RequestParam("from")String from,
#RequestParam("to")String to,
#RequestParam("departureDate")
#DateTimeFormat(pattern = "MM-dd-yyyy")
Date departureDate,
Model model)
{
List<Flight> flights = flightRepository.findFlights(from,to,departureDate);
model.addAttribute("flights", flights);
return "displayFlights";
}
#RequestMapping("/ourFlights")
public String ourFlights() {
return "ourFlights";
}
#RequestMapping(value="/add", method=RequestMethod.POST)
public String addFlights(#ModelAttribute("flight")Flight flight,Model model) {
Flight save = flightRepository.save(flight);
String msg = save.getFlightNumber() + " from " + save.getDepartureCity() + " to "
+ save.getArrivalCity() + " has been added.";
model.addAttribute("msg", msg);
return "ourFlights";
}
}
This is my JSP file
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%#taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%#page isELIgnored="false"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Money Wise</title>
<link rel="stylesheet" href="/reserve/css/bootstrap.min.css"/>
<link rel="stylesheet" href="/reserve/css/custom.css"/>
</head>
<body>
<div class="container">
<div id="body">
<nav class="navbar navbar-expand-lg navbar-light bg-lights">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="home">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Ideology</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Faq</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">News</a>
</li>
</ul>
<form class="form-inline my-2 my-lg-0 pull-right">
<input class="form-control mr-sm-2" type="search" placeholder="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</nav>
<!-- Site Body -->
<div id="content" class="container">
<div class="row">
<div id="leftMain" class="col-sm-3">
<img src="/reserve/images/jim.png"width=100%/>
</div>
<div id="mainBody" class="col-sm-9 ">
<h2>Add Flights</h2>
<form action="add" method="post">
<div class="form-group">
<label for="flightNumber">Flight number</label>
<input type="text" class="form-control" name="flightNumber" placeholder="Flight number"/>
</div>
<div class="form-group">
<label for="operatingAirlines">Operating airlines</label>
<input type="text" class="form-control" name="operatingAirlines" placeholder="Operating airlines"/>
</div>
<div class="form-group">
<label for="departureCity">Departure city</label>
<input type="text" class="form-control" name="departureCity" placeholder="Departure city"/>
</div>
<div class="form-group">
<label for="arrivalCity">Arrival city</label>
<input type="text" class="form-control" name="arrivalCity" placeholder="Arrival city"/>
</div>
<div class="form-group">
<label for="dateOfDeparture">Date of departure</label>
<input type="Date" class="form-control" name="dateOfDeparture" placeholder="Date of departure"/>
</div>
<div class="form-group">
<label for="estimatedDepartureTime">Estimated departure time</label>
<input type="datetime-local" class="form-control" name="estimatedDepartureTime" placeholder="Estimated departure time"/>
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- JS, Popper.js, and jQuery -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.0/dist/umd/popper.min.js"></script>
<script src="/reserve/js/bootstrap.min.js"></script>
</body>
</html>
This is the error I get
Field error in object 'flight' on field 'estimatedDepartureTime': rejected value [2020-06-20T17:35]; codes
[typeMismatch.flight.estimatedDepartureTime,typeMismatch.estimatedDepartureTime,typeMismatch.java.time.LocalDateTime,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable:
codes [flight.estimatedDepartureTime,estimatedDepartureTime]; arguments []; default message [estimatedDepartureTime]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.time.LocalDateTime' for property 'estimatedDepartureTime';
nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type
[java.lang.String] to type [#javax.persistence.Column java.time.LocalDateTime] for value '2020-06-20T17:35'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2020-06-20T17:35]]]
``````
You can try to use Spring The Formatter SPI to convert Date expressed as String to LocalDateTime and vice versa.
public class DateTimeFormatters {
public static class LocalDateTimeFormatter implements Formatter<LocalDateTime> {
#Override
public LocalDateTime parse(String pattern, Locale locale) throws ParseException {
return LocalDateTime.parse(pattern, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}
#Override
public String print(LocalDateTime object, Locale locale) {
return object.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}
}
}
And register your Formatter e.g
public class ApplicationConfig implements WebMvcConfigurer {
...
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new DateTimeFormatters.LocalDateTimeFormatter());
}
...
}

Laravel foreign key reference

I'm trying to reference the description of a foreign key via a relation, like follows:
My model.
namespace App;
use Illuminate\Database\Eloquent\Model;
class Evento extends Model
{
//
protected $fillable = [
'idEvento',
'strNombreEvento',
'strDireccion',
'strCiudad',
'strCorreo',
'strTelefono',
'strEncargadoEvento',
'strNotas',
'idEscuela',
];
protected $primaryKey = 'idEvento';
public function escuela()
{
return $this->belongsTo('App\Escuela','idEscuela');
}
public function diaevento()
{
return $this->hasMany('App\diaEvento');
}
}
The relation
namespace App;
use Illuminate\Database\Eloquent\Model;
class Escuela extends Model
{
//
protected $fillable = [
'idEscuela',
'strNombreEscuela',
'bolPrincipal',
'strLogo',
'sitDiasUsuarioInactivo',
'sitDiasToleranciaCobro',
];
protected $primaryKey = 'idEscuela';
public function grupos()
{
return $this->hasMany('app\grupo');
}
public function eventos()
{
return $this->hasMany('app\eventos');
}
}
My view
#extends('layouts.app')
#section('content')
#guest
#else
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="#">Eventos</a>
</nav>
<div class="container-fluid">
<div class="row">
<nav class="col-sm-1 d-md-block bg-light sidebar">
<div class="sidebar-sticky">
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
<span>Acciones</span>
<a class="d-flex align-items-center text-muted" href="#">
<span data-feather="plus-circle"></span>
</a>
</h6>
<ul class="nav flex-column">
<li class="nav-item">
<span data-feather="home"></span>
<span class="sr-only"></span>
</li>
<li class="nav-item">
<a class="nav-link" href="/gymmgr/public/eventos/create">
<span data-feather="file"></span>
Nuevo
</a>
</ul>
</div>
</nav>
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
<h1 class="h5">Catálogo</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<div class="btn-group mr-2">
<button class="btn btn-sm btn-outline-secondary">Exportar</button>
</div>
</div>
</div>
<table class="table">
<thead class="thead-light">
<tr>
<th>Evento</th>
<th>Escuela</th>
<th>Dirección</th>
<th>Ciudad</th>
<th>Correo</th>
<th>Teléfono</th>
<th>Contacto</th>
</tr>
</thead>
<tbody>
#foreach($eventos as $evento)
<tr>
<td> {{ $evento->strNombreEvento }} </td>
<td>{{ $evento->escuela->strNombreEscuela }}</td>
<td>{{ $evento->strDireccion }} </td>
<td>{{ $evento->strCiudad }} </td>
<td>{{ $evento->strCorreo }} </td>
<td>{{ $evento->strTelefono }} </td>
<td>{{ $evento->strEncargadoEvento }} </td>
</tr>
#endforeach
</tbody>
</table>
</main>
</div>
</div>
#endguest
#endsection
My controller
public function index()
{
//
$eventos = evento::all();
return view('eventos.index', ['eventos'=>$eventos]);
}
The result.
The thing is that the same mechanics is working with another model, which I post:
namespace App;
use Illuminate\Database\Eloquent\Model;
class grupo extends Model
{
//
protected $fillable = [
'idGrupo',
'idEscuela',
'strNombreGrupo',
];
protected $primaryKey = 'idGrupo';
public function escuela()
{
return $this->belongsTo('App\Escuela','idEscuela');
}
public function horarioGrupo()
{
return $this->hasMany('App\horario_Periodicos');
}
}
The relation is the same as with evento above.
My view
#extends('layouts.app')
#section('content')
#guest
#else
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="#">Grupos</a>
</nav>
<div class="container-fluid">
<div class="row">
<nav class="col-sm-1 d-md-block bg-light sidebar">
<div class="sidebar-sticky">
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
<span>Acciones</span>
<a class="d-flex align-items-center text-muted" href="#">
<span data-feather="plus-circle"></span>
</a>
</h6>
<ul class="nav flex-column">
<li class="nav-item">
<span data-feather="home"></span>
<span class="sr-only"></span>
</li>
<li class="nav-item">
<a class="nav-link" href="/gymmgr/public/grupos/create">
<span data-feather="file"></span>
Nuevo
</a>
</ul>
</div>
</nav>
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
<h1 class="h5">Catálogo</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<div class="btn-group mr-2">
<button class="btn btn-sm btn-outline-secondary">Exportar</button>
</div>
</div>
</div>
<table class="table">
<thead class="thead-light">
<tr>
<th>Nombre del grupo</th>
<th>Escuela</th>
</tr>
</thead>
<tbody>
#foreach($grupos as $grupo)
<tr>
<td> {{ $grupo->strNombreGrupo }} ></td>
<td>{{ $grupo->escuela->strNombreEscuela }}</td>
</tr>
#endforeach
</tbody>
</table>
</main>
</div>
</div>
#endguest
#endsection
The controller
public function index()
{
//
$grupos = grupo::all();
return view('grupos.index', ['grupos'=>$grupos]);
}
I would appreciate your help.
Thanks.
I post my migrations, they where added today
The original Evento
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateEventosTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('eventos', function (Blueprint $table) {
$table->increments('idEvento');
$table->string('strNombreEvento', 200);
$table->string('strDireccion', 200);
$table->string('strCiudad', 200);
$table->string('strCorreo', 200);
$table->string('strTelefono', 20);
$table->string('strEncargadoEvento', 60);
$table->string('strNotas', 300);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('eventos');
}
}
These one was dump, thinking in a direct referent from the foreign table
From Evento to Escuela, no intermediate.
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class DeleteDiasEventoTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
//
Schema::dropIfExists('dias_eventos');
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
//
Schema::create('dias_eventos', function (Blueprint $table) {
$table->increments('idDiasEventos');
$table->integer('idEvento')->unsigned();
$table->foreign('idEvento')->references('idEvento')->on('eventos');
$table->integer('idDiaEventos')->unsigned();
$table->foreign('idDiaEventos')->references('id')->on('dia_eventos');
$table->unique(['idEvento','idDiaEventos']);
$table->timestamps();
});
}
}
Then I modified Evento, including the foreign key by itself.
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class ModifyEventoTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
//
Schema::table('eventos', function($table) {
$table->integer('idEscuela')->unsigned();
$table->foreign('idEscuela')->references('idEscuela')->on('escuelas');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('eventos', function (Blueprint $table) {
$table->dropForeign('eventos_idescuela_foreign');
$table->dropColumn('idEscuela');
});
}
}
Is your query returning array or object? If you dump it out, you might find that it's an array and all you need is an array access ([]) instead of an object access (->).

Why #Valid Class it fails if I create a repository?

I have this controller:
#RequestMapping(value="admin/departamento", method = RequestMethod.POST)
public ModelAndView departamentoGuardar(
#Valid Departamento departamento ,
BindingResult br
){
ModelAndView mav = new ModelAndView();
mav.setViewName("costos/departamento");
return mav;
}
...and it is working.
But, if I build a empty repository class:
#Repository("departamentoRepository")
public interface DepartamentoRepository extends JpaRepository<Departamento, Integer>{
}
My controller throws this when a put a String and only accepts int:
org.springframework.beans.TypeMismatchException: Failed to convert
value of type 'java.lang.String' to required type
'com.carrduci.gestionycontrol.model.Departamento'; nested exception is
org.springframework.core.convert.ConversionFailedException: Failed to
convert from type [java.lang.String] to type [java.lang.Integer] for
value 'asdf'; nested exception is java.lang.NumberFormatException: For
input string: "asdf" at
org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:80)
~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] at
org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:52)
~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] at
org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:692)
~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE] at
org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttributeFromRequestValue(ServletModelAttributeMethodProcessor.java:141)
~[spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE
My Class:
#Entity
#Table(name = "departamento")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Departamento.findAll", query = "SELECT d FROM Departamento d")})
public class Departamento implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Column(name = "id_departamento")
private Integer idDepartamento;
#Size(max = 20)
#Column(name = "departamento")
private String departamento;
public Departamento() {
}
public Departamento(Integer idDepartamento) {
this.idDepartamento = idDepartamento;
}
public Integer getIdDepartamento() {
return idDepartamento;
}
public void setIdDepartamento(Integer idDepartamento) {
this.idDepartamento = idDepartamento;
}
public String getDepartamento() {
return departamento;
}
public void setDepartamento(String departamento) {
this.departamento = departamento;
}
#Override
public int hashCode() {
int hash = 0;
hash += (idDepartamento != null ? idDepartamento.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Departamento)) {
return false;
}
Departamento other = (Departamento) object;
if ((this.idDepartamento == null && other.idDepartamento != null) || (this.idDepartamento != null && !this.idDepartamento.equals(other.idDepartamento))) {
return false;
}
return true;
}
#Override
public String toString() {
return "com.carrduci.gestionycontrol.model.Departamento[ idDepartamento=" + idDepartamento + " ]";
}
}
UPDATE
<th:block th:include="fragments/encabezados :: encabezados"></th:block>
<div class="container">
<div class="row">
<div class="col-md-offset-4 col-sm-offset-0">
<div class="row">
<div class="col-sm-12"> <h4>Departamento</h4></div>
</div>
<div class="row">
<div class="col-sm-12 col-md-8 ">
<form th:action="${departamento.idDepartamento>0}?
#{/costos/admin/departamento/modificar}:
#{/costos/admin/departamento}"
method="post" th:object="${departamento}">
<div class="row">
<div class="form-group col-xs-12">
<input type="hidden" th:field="*{idDepartamento}">
<div class="input-group">
<span class="input-group-addon">Nombre</i></span>
<input class="form-control input-lg" type="text" th:field="*{departamento}">
<div class="alert alert-danger" th:if="${#fields.hasErrors('departamento')}" th:errors="*{departamento}" ></div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12 text-right">
<a type="button" class="btn btn-danger BOTON_LIMPIAR" href="/index"> <span class=" glyphicon glyphicon-remove"></span> Cancelar</a>
<button type="submit" class="btn btn-success">
<span class="glyphicon glyphicon-floppy-save"></span>
<span th:text="${departamento.idDepartamento>0}?
#{Modificar}:
#{Guardar}">
</span>
</button>
</div>
</div>
</form>
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-8 ">
<hr>
<th:block th:include="fragments/tabla :: tabla"></th:block>
</div>
</div>
</div>
</div>
</div>
<th:block th:include="fragments/pieDePagina :: pieDePagina"></th:block>

Resources