diff --git a/pom.xml b/pom.xml
index 6905f5a7..4cc70463 100644
--- a/pom.xml
+++ b/pom.xml
@@ -32,6 +32,14 @@
h2
runtime
+
+ org.springframework.boot
+ spring-boot-h2console
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
org.springframework.boot
spring-boot-starter-data-jpa-test
diff --git a/src/main/java/guru/springframework/spring7webapp/bootstrap/BootstrapData.java b/src/main/java/guru/springframework/spring7webapp/bootstrap/BootstrapData.java
new file mode 100644
index 00000000..a52524bb
--- /dev/null
+++ b/src/main/java/guru/springframework/spring7webapp/bootstrap/BootstrapData.java
@@ -0,0 +1,75 @@
+package guru.springframework.spring7webapp.bootstrap;
+
+import guru.springframework.spring7webapp.domain.Author;
+import guru.springframework.spring7webapp.domain.Book;
+import guru.springframework.spring7webapp.domain.Publisher;
+import guru.springframework.spring7webapp.repositories.AuthorRepository;
+import guru.springframework.spring7webapp.repositories.BookRepository;
+import guru.springframework.spring7webapp.repositories.PublisherRepository;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.stereotype.Component;
+
+@Component
+public class BootstrapData implements CommandLineRunner {
+ private final AuthorRepository authorRepository;
+ private final BookRepository bookRepository;
+ private final PublisherRepository publisherRepository;
+
+ public BootstrapData(
+ AuthorRepository authorRepository,
+ BookRepository bookRepository,
+ PublisherRepository publisherRepository
+ ) {
+ this.authorRepository = authorRepository;
+ this.bookRepository = bookRepository;
+ this.publisherRepository = publisherRepository;
+ }
+
+ @Override
+ public void run(String... args) throws Exception {
+ Author joop = new Author();
+ joop.setFirstName("Joop");
+ joop.setLastName("Appelstroop");
+
+ Book ddd = new Book();
+ ddd.setTitle("DomainDrivenDesign");
+ ddd.setIsbn("123128384");
+
+ Author joopSaved = authorRepository.save(joop);
+ Book dddSaved = bookRepository.save(ddd);
+
+ Author piet = new Author();
+ piet.setFirstName("Piet");
+ piet.setLastName("Vergeetmijniet");
+
+ Book edd = new Book();
+ edd.setTitle("Event Driven Design");
+ edd.setIsbn("01293434597");
+
+ Author pietSaved = authorRepository.save(piet);
+ Book eddSaved = bookRepository.save(edd);
+
+ Publisher publisher = new Publisher();
+ publisher.setAddress("teststreet 26");
+ publisher.setCity("New York");
+ publisher.setState("New York");
+ publisher.setPublisherName("El publicity");
+
+ Publisher savedPublisher = publisherRepository.save(publisher);
+
+ dddSaved.setPublisher(savedPublisher);
+ eddSaved.setPublisher(savedPublisher);
+
+ Book test = bookRepository.save(eddSaved);
+ Book test2 = bookRepository.save(dddSaved);
+ authorRepository.save(joopSaved);
+ authorRepository.save(pietSaved);
+
+ System.out.println("Authors count: " + authorRepository.count());
+ System.out.println("Book count: " + bookRepository.count());
+ System.out.println("Publisher count: " + publisherRepository.count());
+
+ System.out.println("Publisher count: " + test.getPublisher().getPublisherName());
+ System.out.println("Publisher count: " + test2.getPublisher().getPublisherName());
+ }
+}
diff --git a/src/main/java/guru/springframework/spring7webapp/controllers/AuthorController.java b/src/main/java/guru/springframework/spring7webapp/controllers/AuthorController.java
new file mode 100644
index 00000000..693c1fa3
--- /dev/null
+++ b/src/main/java/guru/springframework/spring7webapp/controllers/AuthorController.java
@@ -0,0 +1,23 @@
+package guru.springframework.spring7webapp.controllers;
+
+import guru.springframework.spring7webapp.services.AuthorService;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Controller
+public class AuthorController {
+
+ private final AuthorService authorService;
+
+ public AuthorController(AuthorService authorService) {
+ this.authorService = authorService;
+ }
+
+ @RequestMapping(path = "/authors")
+ public String authors(Model model) {
+ model.addAttribute("authors", this.authorService.findAll());
+
+ return "authors";
+ }
+}
diff --git a/src/main/java/guru/springframework/spring7webapp/controllers/BookController.java b/src/main/java/guru/springframework/spring7webapp/controllers/BookController.java
new file mode 100644
index 00000000..a5eff8a7
--- /dev/null
+++ b/src/main/java/guru/springframework/spring7webapp/controllers/BookController.java
@@ -0,0 +1,25 @@
+package guru.springframework.spring7webapp.controllers;
+
+import guru.springframework.spring7webapp.domain.Book;
+import guru.springframework.spring7webapp.services.Bookservice;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Controller
+public class BookController {
+
+ private final Bookservice bookservice;
+
+ public BookController(Bookservice bookservice) {
+ this.bookservice = bookservice;
+ }
+
+ @RequestMapping(path = "/books")
+ public String getBooks(Model model) {
+ model.addAttribute("books", this.bookservice.findAll());
+
+ return "books";
+ }
+}
diff --git a/src/main/java/guru/springframework/spring7webapp/domain/Author.java b/src/main/java/guru/springframework/spring7webapp/domain/Author.java
new file mode 100644
index 00000000..4ea012a6
--- /dev/null
+++ b/src/main/java/guru/springframework/spring7webapp/domain/Author.java
@@ -0,0 +1,76 @@
+package guru.springframework.spring7webapp.domain;
+
+import jakarta.persistence.*;
+
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+@Entity
+public class Author {
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ @Column(nullable = false)
+ private Long id;
+
+ private String firstName;
+ private String lastName;
+
+ @ManyToMany(mappedBy = "authors")
+ private Set books;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ 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 Set getBooks() {
+ return books = new HashSet<>();
+ }
+
+ public void setBooks(Set books) {
+ this.books = books;
+ }
+
+ @Override
+ public String toString() {
+ return "Author{" +
+ "id=" + id +
+ ", firstName='" + firstName + '\'' +
+ ", lastName='" + lastName + '\'' +
+ ", books=" + books +
+ '}';
+ }
+
+ @Override
+ public final boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Author author)) return false;
+
+ return Objects.equals(getId(), author.getId());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(getId());
+ }
+}
diff --git a/src/main/java/guru/springframework/spring7webapp/domain/Book.java b/src/main/java/guru/springframework/spring7webapp/domain/Book.java
new file mode 100644
index 00000000..398bcf61
--- /dev/null
+++ b/src/main/java/guru/springframework/spring7webapp/domain/Book.java
@@ -0,0 +1,93 @@
+package guru.springframework.spring7webapp.domain;
+
+import jakarta.persistence.*;
+
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+@Entity
+public class Book {
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ @Column(nullable = false)
+ private Long id;
+
+ private String title;
+ private String isbn;
+
+ @ManyToMany
+ @JoinTable(
+ name = "author_book",
+ joinColumns = @JoinColumn(name = "book_id"),
+ inverseJoinColumns = @JoinColumn(name = "author_id")
+ )
+ private Set authors;
+
+ @ManyToOne
+ @JoinColumn(name = "publisher_id")
+ private Publisher publisher;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getIsbn() {
+ return isbn;
+ }
+
+ public void setIsbn(String isbn) {
+ this.isbn = isbn;
+ }
+
+ public Set getAuthors() {
+ return authors = new HashSet<>();
+ }
+
+ public void setAuthors(Set authors) {
+ this.authors = authors;
+ }
+
+ @Override
+ public String toString() {
+ return "Book{" +
+ "id=" + id +
+ ", title='" + title + '\'' +
+ ", isbn='" + isbn + '\'' +
+ ", authors=" + authors +
+ '}';
+ }
+
+ @Override
+ public final boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Book book)) return false;
+
+ return Objects.equals(getId(), book.getId());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(getId());
+ }
+
+ public Publisher getPublisher() {
+ return publisher;
+ }
+
+ public void setPublisher(Publisher publisher) {
+ this.publisher = publisher;
+ }
+}
diff --git a/src/main/java/guru/springframework/spring7webapp/domain/Publisher.java b/src/main/java/guru/springframework/spring7webapp/domain/Publisher.java
new file mode 100644
index 00000000..b253a642
--- /dev/null
+++ b/src/main/java/guru/springframework/spring7webapp/domain/Publisher.java
@@ -0,0 +1,106 @@
+package guru.springframework.spring7webapp.domain;
+
+import jakarta.persistence.*;
+
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+@Entity
+public class Publisher {
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ @Column(nullable = false)
+ private Long id;
+
+ @OneToMany(mappedBy = "publisher")
+ private Set books;
+
+ private String publisherName;
+ private String address;
+ private String city;
+ private String state;
+ private String zip;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Set getBooks() {
+ return books = new HashSet<>();
+ }
+
+ public void setBooks(Set books) {
+ this.books = books;
+ }
+
+ public String getPublisherName() {
+ return publisherName;
+ }
+
+ public void setPublisherName(String name) {
+ this.publisherName = name;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+
+ public String getZip() {
+ return zip;
+ }
+
+ public void setZip(String zip) {
+ this.zip = zip;
+ }
+
+ @Override
+ public String toString() {
+ return "Publisher{" +
+ "id=" + id +
+ ", books=" + books +
+ ", publisherName='" + publisherName + '\'' +
+ ", address='" + address + '\'' +
+ ", city='" + city + '\'' +
+ ", state='" + state + '\'' +
+ ", zip='" + zip + '\'' +
+ '}';
+ }
+
+ @Override
+ public final boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Publisher publisher)) return false;
+
+ return Objects.equals(getId(), publisher.getId());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(getId());
+ }
+}
diff --git a/src/main/java/guru/springframework/spring7webapp/repositories/AuthorRepository.java b/src/main/java/guru/springframework/spring7webapp/repositories/AuthorRepository.java
new file mode 100644
index 00000000..bcd59fc7
--- /dev/null
+++ b/src/main/java/guru/springframework/spring7webapp/repositories/AuthorRepository.java
@@ -0,0 +1,7 @@
+package guru.springframework.spring7webapp.repositories;
+
+import guru.springframework.spring7webapp.domain.Author;
+import org.springframework.data.repository.CrudRepository;
+
+public interface AuthorRepository extends CrudRepository {
+}
diff --git a/src/main/java/guru/springframework/spring7webapp/repositories/BookRepository.java b/src/main/java/guru/springframework/spring7webapp/repositories/BookRepository.java
new file mode 100644
index 00000000..144b45e9
--- /dev/null
+++ b/src/main/java/guru/springframework/spring7webapp/repositories/BookRepository.java
@@ -0,0 +1,7 @@
+package guru.springframework.spring7webapp.repositories;
+
+import guru.springframework.spring7webapp.domain.Book;
+import org.springframework.data.repository.CrudRepository;
+
+public interface BookRepository extends CrudRepository {
+}
diff --git a/src/main/java/guru/springframework/spring7webapp/repositories/PublisherRepository.java b/src/main/java/guru/springframework/spring7webapp/repositories/PublisherRepository.java
new file mode 100644
index 00000000..d9bf28fa
--- /dev/null
+++ b/src/main/java/guru/springframework/spring7webapp/repositories/PublisherRepository.java
@@ -0,0 +1,8 @@
+package guru.springframework.spring7webapp.repositories;
+
+import guru.springframework.spring7webapp.domain.Book;
+import guru.springframework.spring7webapp.domain.Publisher;
+import org.springframework.data.repository.CrudRepository;
+
+public interface PublisherRepository extends CrudRepository {
+}
diff --git a/src/main/java/guru/springframework/spring7webapp/services/AuthorService.java b/src/main/java/guru/springframework/spring7webapp/services/AuthorService.java
new file mode 100644
index 00000000..73903c35
--- /dev/null
+++ b/src/main/java/guru/springframework/spring7webapp/services/AuthorService.java
@@ -0,0 +1,9 @@
+package guru.springframework.spring7webapp.services;
+
+import guru.springframework.spring7webapp.domain.Author;
+
+public interface AuthorService {
+
+ public Iterable findAll();
+
+}
diff --git a/src/main/java/guru/springframework/spring7webapp/services/AuthorServiceImpl.java b/src/main/java/guru/springframework/spring7webapp/services/AuthorServiceImpl.java
new file mode 100644
index 00000000..7e605023
--- /dev/null
+++ b/src/main/java/guru/springframework/spring7webapp/services/AuthorServiceImpl.java
@@ -0,0 +1,20 @@
+package guru.springframework.spring7webapp.services;
+
+import guru.springframework.spring7webapp.domain.Author;
+import guru.springframework.spring7webapp.repositories.AuthorRepository;
+import org.springframework.stereotype.Service;
+
+@Service
+public class AuthorServiceImpl implements AuthorService {
+
+ private final AuthorRepository authorRepository;
+
+ public AuthorServiceImpl(AuthorRepository authorRepository) {
+ this.authorRepository = authorRepository;
+ }
+
+ @Override
+ public Iterable findAll() {
+ return this.authorRepository.findAll();
+ }
+}
diff --git a/src/main/java/guru/springframework/spring7webapp/services/Bookservice.java b/src/main/java/guru/springframework/spring7webapp/services/Bookservice.java
new file mode 100644
index 00000000..64afc2d6
--- /dev/null
+++ b/src/main/java/guru/springframework/spring7webapp/services/Bookservice.java
@@ -0,0 +1,7 @@
+package guru.springframework.spring7webapp.services;
+
+import guru.springframework.spring7webapp.domain.Book;
+
+public interface Bookservice {
+ public Iterable findAll();
+}
diff --git a/src/main/java/guru/springframework/spring7webapp/services/BookserviceImpl.java b/src/main/java/guru/springframework/spring7webapp/services/BookserviceImpl.java
new file mode 100644
index 00000000..a2b12b7f
--- /dev/null
+++ b/src/main/java/guru/springframework/spring7webapp/services/BookserviceImpl.java
@@ -0,0 +1,20 @@
+package guru.springframework.spring7webapp.services;
+
+import guru.springframework.spring7webapp.domain.Book;
+import guru.springframework.spring7webapp.repositories.BookRepository;
+import org.springframework.stereotype.Service;
+
+@Service
+public class BookserviceImpl implements Bookservice {
+
+ private final BookRepository bookRepository;
+
+ public BookserviceImpl(BookRepository bookRepository) {
+ this.bookRepository = bookRepository;
+ }
+
+ @Override
+ public Iterable findAll() {
+ return bookRepository.findAll();
+ }
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 8b137891..0db082b8 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1 +1 @@
-
+spring.h2.console.enabled=true
diff --git a/src/main/resources/templates/authors.html b/src/main/resources/templates/authors.html
new file mode 100644
index 00000000..28cd6275
--- /dev/null
+++ b/src/main/resources/templates/authors.html
@@ -0,0 +1,24 @@
+
+
+
+
+ Title
+
+
+
+
+
+ | ID |
+ Firstname |
+ Lastname |
+
+
+
+ |
+ |
+ |
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/templates/books.html b/src/main/resources/templates/books.html
new file mode 100644
index 00000000..a50f20d0
--- /dev/null
+++ b/src/main/resources/templates/books.html
@@ -0,0 +1,24 @@
+
+
+
+
+ Title
+
+
+
+
+
+ | ID |
+ Title |
+ Publisher |
+
+
+
+ |
+ |
+ |
+
+
+
+
+
\ No newline at end of file