Build an application reserve a ticket for cinema with Spring boot and Angular part 1

Getting Started | Building an Application with Spring Boot




Build an application reserve a ticket for cinema with Spring boot and Angular use Jpa

Objective:

In This tutorial we will build an application reserve a ticket for cinema using Spring boot and Angular. the user can surfing the list of movies by city, cinema and display details time, price and more details as well description, director, realse date and title he can choose his ticket or more tickets.


Used Skills in this project:

Java, SpringBoot, MicroServices, REST WebServices, JPA, Hibernate, MySQL Database, Maven, Angular, GitHub, SpringBoot Embedded Tomcat Server, STS-Eclipse IDE


Tools to be used

° Use any IDE to develop the Spring and Hibernate project. It may be STS/Eclipse/Netbeans. Here, we are using STS (Spring Tool Suite).

° Mysql for the database.

° Use any IDE to develop the Angular project. It may be Visual Studio Code/Sublime. Here, we are using Visual Studio Code.

° Server: Apache Tomcat/JBoss/Glassfish/Weblogic/Websphere.


Spring MVC

Spring MVC is the primary web framework built on the Servlet API. It is build on the popular MVC design pattern. MVC (Model-View-Controller) is a software architecture pattern, which separates application into three areas: model, view, and controller. The model represents a Java object carrying data. The view represents the visualization of the data that the model contains. The controller controls the data flow into model object and updates the view when the data changes. It separates the view and model.


Spring Boot Architecture



Spring Boot is a module of the Spring Framework. It is used to create stand-alone, production-grade Spring Based Applications with minimum efforts. It is developed on top of the core Spring Framework.



Introduction mysql to database

MySQL is a database management system that allows you to manage relational databases. It is open source software backed by Oracle. It means you can use MySQL without paying a dime. Also, if you want, you can change its source code to suit your needs. MySQL can run on various platforms UNIX, Linux, Windows, etc. You can install it on a server or even in a desktop. Besides, MySQL is reliable, scalable, and fast.



Introduction to the POM

POM A Project Object Model or POM is the fundamental unit of work in Maven. It is an XML file that contains information about the project and configuration details used by Maven to build the project. It contains default values for most projects. Examples for this is the build directory, which is target; the source directory, which is src/main/java; the test source directory, which is src/main/java; and so on. When executing a task or goal, Maven looks for the POM in the current directory. It reads the POM, gets the needed configuration information, then executes the goal.

pom.xml

    
  
  
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0>/modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.1</version> <relativePath/> </parent> <groupId>org.issamdrmas</groupId> <artifactId>cinema</artifactId> <version>0.0.1-SNAPSHOT</version> <name>cinema</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>

Properties File

Properties files are used to keep ‘N’ number of properties in a single file to run the application in a different environment. In Spring Boot, properties are kept in the application.properties file under the classpath.

The application.properties file is located in the src/main/resources directory. The code for sample application.properties


We need to create database name it cinema

src/main/resources/application.properties

    
  
spring.datasource.url=jdbc:mysql://localhost:3306/cinema?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC spring.datasource.username=root spring.activemq.password= spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect spring.jpa.hibernate.ddl-auto=create-drop server.port=8080

Class Diagram



Modals / Entities

An entity is a lightweight persistence domain object. Typically, an entity represents a table in a relational database, and each entity instance corresponds to a row in that table. The primary programming artifact of an entity is the entity class, although entities can use helper classes.


We need to create neuf entities

- Category

- Cinema

- City

- Film

- Place

- Projection

- Salle

- Seance

- Ticket


Here, we are creating an Entity

Category.java This object content id, name, and relational @OneToMany with Film

src/main/java/org/issamdrmas/entities/Category.java):



package org.issamdrmas.cinema.entites; import java.io.Serializable; import java.util.Collection; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToMany; import com.fasterxml.jackson.annotation.JsonIgnore; @Entity public class Category implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @Column(length = 75) @OneToMany(mappedBy = "category") @JsonIgnore private Collection<Film> films; public Category() { super(); } public Category(String name, Collection<Film> films) { super(); this.name = name; this.films = films; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Collection<Film> getFilms() { return films; } public void setFilms(Collection<Film> films) { this.films = films; } }

Here, we are creating an Entity

Cinema.java This object content id, name, nombreSalles and relational @OneToMany with Sale

src/main/java/org/issamdrmas/entities/Cinema.java):



package org.issamdrmas.cinema.entites; import java.io.Serializable; import java.util.Collection; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; @Entity public class Cinema implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private int nombreSalles; @OneToMany(mappedBy = "cinema") private Collection<Salle> salles; @ManyToOne private City city; public Cinema() { super(); } public Cinema(String name, int nombreSalles, Collection<Salle> salles, City city) { super(); this.name = name; this.nombreSalles = nombreSalles; this.salles = salles; this.city = city; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getNombreSalles() { return nombreSalles; } public void setNombreSalles(int nombreSalles) { this.nombreSalles = nombreSalles; } public Collection<Salle> getSalles() { return salles; } public void setSalles(Collection<Salle> salles) { this.salles = salles; } public City getCity() { return city; } public voidsetCity(City city) { this.city = city; } }

Here, we are creating an Entity

City.java This object content id, name, and relational @OneToMany with Cinema

src/main/java/org/issamdrmas/entities/City.java):



package org.issamdrmas.cinema.entites; import java.io.Serializable; import java.util.Collection; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToMany; @Entity public class City implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @OneToMany(mappedBy = "city") private Collection<Cinema> cinemas; public City() { super(); } public City(String name, Collection<Cinema> cinemas) { super(); this.name = name; this.cinemas = cinemas; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Collection<Cinema> getCinemas() { return cinemas; } public void setCinemas(Collection<Cinema> cinemas) { this.cinemas = cinemas; } }

Here, we are creating an Entity

Film.java This object content id, name, description, photo, director, releaseDate, duration and relational @ManyToOne with Category and @OneToMany With Projection

src/main/java/org/issamdrmas/entities/Film.java):



package org.issamdrmas.cinema.entites; import java.io.Serializable; import java.util.Collection; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import com.fasterxml.jackson.annotation.JsonIgnore; @Entity public class Film implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String title; private String description; private String photo; private String director; private String releaseDate; private String duration; @OneToMany(mappedBy = "film") @JsonIgnore private Collection<Projection> projections; @ManyToOne private Category category; public Film() { super(); } public Film(String title, String description, String photo, String director, String releaseDate, String duration) { super(); this.title = title; this.description = description; this.photo = photo; this.director = director; this.releaseDate = releaseDate; this.duration = duration; } public Film(String title, String description, String photo, String director, String releaseDate, String duration, Collection<Projection> projections, Category category) { super(); this.title = title; this.description = description; this.photo = photo; this.director = director; this.releaseDate = releaseDate; this.duration = duration; this.projections = projections; this.category = category; } 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 getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getPhoto() { return photo; } public void setPhoto(String photo) { this.photo = photo; } public String getDirector() { return director; } public void setDirector(String director) { this.director = director; } public String getReleaseDate() { return releaseDate; } public void setReleaseDate(String releaseDate) { this.releaseDate = releaseDate; } public String getDuration() { return duration; } public void setDuration(String duration) { this.duration = duration; } public Collection<Projection> getProjections() { return projections; } public void setProjections(Collection<Projection> projections) { this.projections = projections; } public Category getCategory() { return category; } public void setCategory(Category category) { this.category = category; } }

Here, we are creating an Entity

Place.java This object content id, number, and relational @ManyToOne with Ticket and @OneToMany With Ticket

src/main/java/org/issamdrmas/entities/Place.java):



package org.issamdrmas.cinema.entites; import java.io.Serializable; import java.util.Collection; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty.Access; @Entity public class Place implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private int number; @ManyToOne private Salle salle; @OneToMany(mappedBy = "place") @JsonProperty(access = Access.WRITE_ONLY) private Collection<Ticket> tickets; public Place() { super(); } public Place(int number, Salle salle, Collection<Ticket> tickets) { super(); this.number = number; this.salle = salle; this.tickets = tickets; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } public Salle getSalle() { return salle; } public void setSalle(Salle salle) { this.salle = salle; } public Collection<Ticket> getTickets() { return tickets; } public void setTickets(Collection<Ticket> tickets) { this.tickets = tickets; } }

Here, we are creating an Entity

Projection.java This object content id, name, dateProjection, price, and relational @ManyToOne with Salle, Film, Ticket and @ManyToOne Seance

src/main/java/org/issamdrmas/entities/Projection.java):



package org.issamdrmas.cinema.entites; import java.io.Serializable; import java.util.Collection; import java.util.Date; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty.Access; @Entity public class Projection implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private Date dateProjection; private double price; @ManyToOne @JsonProperty(access=Access.WRITE_ONLY) private Salle salle; @ManyToOne private Film film; @OneToMany(mappedBy = "projection") @JsonProperty(access=Access.WRITE_ONLY) private Collection<Ticket> tickets; @ManyToOne private Seance seance; public Projection() { super(); } public Projection(Date dateProjection, double price, Salle salle, Film film, Collection<Ticket> tickets, Seance seance) { super(); this.dateProjection = dateProjection; this.price = price; this.salle = salle; this.film = film; this.tickets = tickets; this.seance = seance; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Date getDateProjection() { return dateProjection; } public void setDateProjection(Date dateProjection) { this.dateProjection = ateProjection; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public Salle getSalle() { return salle; } public void setSalle(Salle salle) { this.salle = salle; } public Film getFilm() { return film; } public void setFilm(Film film) { this.film = film; } public Collection<Ticket> getTickets() { return tickets; } public void setTickets(Collection<Ticket> tickets) { this.tickets = tickets; } public Seance getSeance() { return seance; } public void setSeance(Seance seance) { this.seance = seance; } }

Here, we are creating an Entity

Salle.java This object content id, name, placeNumber and relational @ManyToOne with Cinema and @OneToMany with Place and Projection

src/main/java/org/issamdrmas/entities/Salle.java):



package org.issamdrmas.cinema.entites; import java.io.Serializable; import java.util.Collection; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty.Access; @Entity public class Salle implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private int placeNumber; @ManyToOne @JsonProperty(access = Access.WRITE_ONLY) private Cinema cinema; @OneToMany(mappedBy = "salle") @JsonProperty(access = Access.WRITE_ONLY) private Collection<Place> places; @JsonProperty(access = Access.WRITE_ONLY) @OneToMany(mappedBy = "salle") private Collection<Projection> projections; public Salle() { super(); } public Salle(String name, int placeNumber, Cinema cinema, Collection<Place> places, Collection<Projection> projections) { super(); this.name = name; this.placeNumber = placeNumber; this.cinema = cinema; this.places = places; this.projections = projections; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPlaceNumber() { return placeNumber; } public void setPlaceNumber(int placeNumber) { this.placeNumber = placeNumber; } public Cinema getCinema() { return cinema; } public void setCinema(Cinema cinema) { this.cinema = cinema; } public Collection<Place> getPlaces() { return places; } public void setPlaces(Collection<Place> places) { this.places = places; } public Collection<Projection> getProjections() { return projections; } public void setProjections(Collection<Projection> projections) { this.projections = projections; } }

Here, we are creating an Entity

Seance.java This object content id, startTime and relational @OneToMany with Projection

src/main/java/org/issamdrmas/entities/Seance.java):



package org.issamdrmas.cinema.entites; import java.io.Serializable; import java.util.Collection; import java.util.Date; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Temporal; import javax.persistence.TemporalType; @Entity public class Seance implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Temporal(TemporalType.TIME) private Date startTime; @OneToMany(mappedBy = "seance") private Collection<Projection> projections; public Category() { super(); } public Seance(Date startTime, Collection<Projection> projections) { super(); this.startTime = startTime; this.projections = projections; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Date getStartTime() { return startTime; } public void setStartTime(Date startTime) { this.startTime = startTime; } public Collection<Projection> getProjections() { return projections; } public void setProjections(Collection<Projection> projections) { this.projections = projections; } }

Here, we are creating an Entity

Ticket.java This object content id, name, and relational @ManyToOne with Place and Projection

src/main/java/org/issamdrmas/entities/Ticket.java):



package org.issamdrmas.cinema.entites; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToOne; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty.Access; @Entity public class Ticket implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String nameClient; private double price; @Column(unique = false, nullable=true) private int codePayement; private boolean reserve; @ManyToOne private Place place; @ManyToOne @JsonProperty(access=Access.WRITE_ONLY) private Projection projection; public Category() { super(); } public Ticket(String nameClient, double price, int codePayement, boolean reserve, Place place, Projection projection) { super(); this.nameClient = nameClient; this.price = price; this.codePayement = codePayement; this.reserve = reserve; this.place = place; this.projection = projection; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getNameClient() { return nameClient; } public void setNameClient(String nameClient) { this.nameClient = nameClient; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public int getCodePayement() { return codePayement; } public void setCodePayement(int codePayement) { this.codePayement = codePayement; } public boolean isReserve() { return reserve; } public void setReserve(boolean reserve) { this.reserve = reserve; } public Place getPlace() { return place; } public void setPlace(Place place) { this.place = place; } public Projection getProjection() { return projection; } public void setProjection(Projection projection) { this.projection = projection; } }

Spring Data JPA Projections

When using Spring Data JPA to implement the persistence layer, the repository typically returns one or more instances of the root class. However, more often than not, we don't need all the properties of the returned objects.


In such cases, it may be desirable to retrieve data as objects of customized types. These types reflect partial views of the root class, containing only properties we care about. This is where projections come in handy.

We need to create these methods

- getId

- getPrice

- getDateProjection

- getSalle

- getFilm

- getSeance

- getTickets


Here, we are creating an interface Projection

Initial Setup The first step is to set up the project and populate the database.

src/main/java/org/issamdrmas/entities/ProjectionProj.java):



package org.issamdrmas.cinema.entites; import java.util.Collection; import java.util.Date; import org.springframework.data.rest.core.config.Projection; @Projection(name="p1", types= {org.issamdrmas.cinema.entites.Projection.class}) public interface ProjectionProj { public long getId(); public double getPrice(); public Date getDateProjection(); public Salle getSalle(); public Film getFilm(); public Seance getSeance(); public Collection<Ticket> getTickets(); }

We need to create these methods

- getId

- getNameClient

- getPrice

- getCodePayement

- getReserve

- getPlace


Here, we are creating an interface TicketProjection

src/main/java/org/issamdrmas/entities/TicketProjection.java):



package org.issamdrmas.cinema.entites; import org.springframework.data.rest.core.config.Projection; @Projection(name="ticketsProj", types= {org.issamdrmas.cinema.entites.Ticket.class}) public interface TicketProjection { public Long getId(); public String getNameClient(); public double getPrice(); public int getCodePayement(); public boolean getReserve(); public Place getPlace(); }

JPA Repositories

The JPA module of Spring Data contains a custom namespace that allows defining repository beans. It also contains certain features and element attributes that are special to JPA. Generally, the JPA repositories can be set up by using the repositories element, as shown in the following example:


Spring Repositories Spring has supported the concept of a repository for some time now. Repository is one of Spring's core stereotypes and you should plan on using them in your data access layer, regardless of your chosen data access layer API and framework.


We need to create three interfaces dao

- CategoryRepository

- CinemaRepository

- CityRepository

- FilmRepository

- PlaceRepository

- ProjectionRepository

- SalleRepository

- SeanceRepository

- TicketRepository


Here, we are creating an interface

src/main/java/com/issamdrmas/dao/CategoryRepository.java):



package org.issamdrmas.cinema.dao; import org.issamdrmas.cinema.entites.Category; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; import org.springframework.web.bind.annotation.CrossOrigin; @RepositoryRestResource @CrossOrigin(origins = "*") public interface CategoryRepository extends JpaRepository<Category, Long> { }

Here, we are creating an interface

src/main/java/com/issamdrmas/dao/CinemaRepository.java):



package org.issamdrmas.cinema.dao; import org.issamdrmas.cinema.entites.Cinema; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; import org.springframework.web.bind.annotation.CrossOrigin; @RepositoryRestResource @CrossOrigin(origins = "*") public interface CinemaRepository extends JpaRepository<Cinema, Long> { }

Here, we are creating an interface

src/main/java/com/issamdrmas/dao/CinemaRepository.java):



package org.issamdrmas.cinema.dao; import org.issamdrmas.cinema.entites.City; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; import org.springframework.web.bind.annotation.CrossOrigin; @RepositoryRestResource @CrossOrigin(origins = "*") public interface CityRepository extends JpaRepository<City, Long> { }

Here, we are creating an interface

src/main/java/com/issamdrmas/dao/FilmRepository.java):



package org.issamdrmas.cinema.dao; import org.issamdrmas.cinema.entites.Film; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; import org.springframework.web.bind.annotation.CrossOrigin; @RepositoryRestResource @CrossOrigin(origins = "*") public interface FilmRepository extends JpaRepository<Film, Long> { }

Here, we are creating an interface

src/main/java/com/issamdrmas/dao/PlaceRepository.java):



package org.issamdrmas.cinema.dao; import org.issamdrmas.cinema.entites.Place; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; import org.springframework.web.bind.annotation.CrossOrigin; @RepositoryRestResource @CrossOrigin(origins = "*") public interface PlaceRepository extends JpaRepository<Place, Long> { }

Here, we are creating an interface

src/main/java/com/issamdrmas/dao/ProjectionRepository.java):



package org.issamdrmas.cinema.dao; import org.issamdrmas.cinema.entites.Projection; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; import org.springframework.web.bind.annotation.CrossOrigin; @RepositoryRestResource @CrossOrigin(origins = "*") public interface ProjectionRepository extends JpaRepository<Projection, Long> { }

Here, we are creating an interface

src/main/java/com/issamdrmas/dao/ProjectionRepository.java):



package org.issamdrmas.cinema.dao; import org.issamdrmas.cinema.entites.Salle; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; import org.springframework.web.bind.annotation.CrossOrigin; @RepositoryRestResource @CrossOrigin(origins = "*") public interface SalleRepository extends JpaRepository<Salle, Long> { }

Here, we are creating an interface

src/main/java/com/issamdrmas/dao/ProjectionRepository.java):



package org.issamdrmas.cinema.dao; import org.issamdrmas.cinema.entites.Seance; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; import org.springframework.web.bind.annotation.CrossOrigin; @RepositoryRestResource @CrossOrigin(origins = "*") public interface SeanceRepository extends JpaRepository<Seance, Long> { }

Here, we are creating an interface

src/main/java/com/issamdrmas/dao/ProjectionRepository.java):



package org.issamdrmas.cinema.dao; import org.issamdrmas.cinema.entites.Ticket; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; import org.springframework.web.bind.annotation.CrossOrigin; @RepositoryRestResource @CrossOrigin(origins = "*") public interface TicketRepository extends JpaRepository<Ticket, Long> { }

The services

Service Components are the class file which contains @Service annotation. These class files are used to write business logic in a different layer, separated from @RestController class file. The logic for creating a service component class file is shown here


We will create this interfaces in the service package:

- ICinemaInitService.java

We need to create these methods

- initCities

- initCinemas

- initSalles

- initPlaces

- initSeances

- initCategories

- initFilms

- initProjections

- initTickets


Here, we are creating an interface ICinemaInitService

src/main/java/org/issamdrmas/service/ICinemaInitService.java):



package org.issamdrmas.cinema.Service; public interface ICinemaInitService { public void initCities(); public void initCinemas(); public void initSalles(); public void initPlaces(); public void initSeances(); public void initCategories(); public void initFilms(); public void initProjections(); public void initTickets(); }

The managers classes implementation

An impl class is usually a class that implements the behaviour described by one of these interfaces. While the internal implementation class, With transactions configured, we can now annotation a bean with @Transactional and @Service either at the class or method level. Then conversion Entity to DTO. This is stands for Data Transfer Object and is a simple Plain Old Java Object which contains class properties and getters and settings methods for accessing those properties.


We will create this class in the service package

- CinemaInitServiceImpl

Here, we are creating a CinemaInitServiceImpl class

CinemaInitServiceImpl.java In this class we will add static data after override the methods from ICinemaInitService

src/main/java/org/issamdrmas/service/CinemaInitServiceImpl.java):



package org.issamdrmas.cinema.Service; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Random; import java.util.stream.Stream; import javax.transaction.Transactional; import org.issamdrmas.cinema.dao.CategoryRepository; import org.issamdrmas.cinema.dao.CinemaRepository; import org.issamdrmas.cinema.dao.FilmRepository; import org.issamdrmas.cinema.dao.PlaceRepository; import org.issamdrmas.cinema.dao.ProjectionRepository; import org.issamdrmas.cinema.dao.SalleRepository; import org.issamdrmas.cinema.dao.SeanceRepository; import org.issamdrmas.cinema.dao.TicketRepository; import org.issamdrmas.cinema.dao.CityRepository; import org.issamdrmas.cinema.entites.Category; import org.issamdrmas.cinema.entites.Cinema; import org.issamdrmas.cinema.entites.Film; import org.issamdrmas.cinema.entites.Place; import org.issamdrmas.cinema.entites.Projection; import org.issamdrmas.cinema.entites.Salle; import org.issamdrmas.cinema.entites.Seance; import org.issamdrmas.cinema.entites.Ticket; import org.issamdrmas.cinema.entites.City; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service @Transactional public class CinemaInitServiceImpl implements ICinemaInitService { @Autowired private CityRepository cityRepository; @Autowired private CinemaRepository cinemaRepository; @Autowired private SalleRepository salleRepository; @Autowired private PlaceRepository placeRepository; @Autowired private SeanceRepository seanceRepository; @Autowired private CategoryRepository categoryRepository; @Autowired private FilmRepository filmRepository; @Autowired private ProjectionRepository projectionRepository; @Autowired private TicketRepository ticketRepository; @Override public void initCities() { Stream.of("Paris", "Marseille", "Lyon", "Bordeaux", "Toulouse", "Strasbourg", "Nantes", "Nice", "Montpellier", "Lille").forEach(cityName -> { City city = new City(); city.setName(cityName); cityRepository.save(city); }); } @Override public void initCinemas() { cityRepository.findAll().forEach(city -> { Stream.of("MegaRama", "IMax", "Fnoun", "Chaharazad", "Daoulizz", "UGC").forEach(cinemaName -> { Cinema cinema = new Cinema(); cinema.setName(cinemaName); cinema.setNombreSalles((int) (3 + Math.random() * 7)); cinema.setCity(city); cinemaRepository.save(cinema); }); }); } @Override public void initSalles() { cinemaRepository.findAll().forEach(cinema -> { this (int i = 0; i < cinema.getNombreSalles(); i++) { Salle salle = new Salle(); salle.setName("Salle " + i + 1); salle.setCinema(cinema); salle.setPlaceNumber((int) (15 + Math.random() * 20)); salleRepository.save(salle); } }); } @Override public void initPlaces() { salleRepository.findAll().forEach(salle -> { for (int i = 0; i < salle.getPlaceNumber(); i++) { Place place = new Place(); place.setNumber(i + 1); place.setSalle(salle); placeRepository.save(place); } }); } @Override public void initSeances() { DateFormat format = new SimpleDateFormat("HH:mm"); Stream.of("12:00", "15:00", "17:00", "19:00", "21:00").forEach(s -> { Seance seance = new Seance(); try { seance.setStartTime(format.parse(s)); seanceRepository.save(seance); } catch (ParseException e) { e.printStackTrace(); } }); } @Override public void initCategories() { Stream.of("Histoire", "Action", "Fiction", "Drama").forEach(cat -> { Category category = new Category(); category.setName(cat); categoryRepository.save(category); }); } @Override public void initFilms() { Film film1 = new Film("The Shawshank Redemption", "Two imprisoned men bond over a number of years, finding solace and eventual redemption through acts of common decency.", "https://zupimages.net/up/21/02/7vq5.jpg", "Francis Ford Coppola", "1994", "01H20"); Film film2 = new Film("The Godfather", "The aging patriarch of an organized crime dynasty transfers control of his clandestine empire to his reluctant son.", "https://zupimages.net/up/21/02/b0e6.jpg", "Frank Darabont", "1972", "01H30"); Film film3 = new Film("The Dark Knight", "The early life and career of Vito Corleone in 1920s new York City is portrayed, while his son, Michael, expands and tightens his grip on the family crime syndicate.","https://zupimages.net/up/21/02/hcko.jpg", "Francis Ford Coppola", "1974", "01H20" ); Film film4 = new Film("12 Angry Men", "When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, Batman must accept one of the greatest psychological","https://zupimages.net/up/21/02/u1h6.jpg", "Christopher Nolan", "2008", "01H40" ); Film film5 = new Film("Schindler is List", "Made Oskar Schindler famous, showing how the factory owner saved 1,200 Jews from World War II concentration camps.","https://zupimages.net/up/21/02/gyi2.jpg", "Steven Spielberg", "1957", "01H30"); Film film6 = new Film("The Lord of the Rings", "The Lord of the Rings is an epic high fantasy novel by the English author and scholar J. R. R. Tolkien. Set in Middle-earth, the world at some distant time in the", "https://zupimages.net/up/21/02/glw6.jpg", "Sidney Lumet", "1993", "01H20"); Film film7 = new Film("Pulp Fiction", "il est connu pour son humour parfois macabre, ses dialogues abondants et souvent cultes, ses nombreuses références cinématographiques ou encore son goût pour la violence extrême.","https://zupimages.net/up/21/02/bqrf.jpg", "Peter Jackson", "1993", "01H40"); Film film8 = new Film("The Good the Bad and the Ugly", "Alors que la guerre de Sécession fait rage aux Etats-Unis, trois bandits n'ont qu'une préoccupation : l'argent. Joe livre régulièrement à la justice son copain Tuco","https://zupimages.net/up/21/02/803q.jpg", "Quentin Tarantino", "2003", "01H30"); Film film9 = new Film("The Hard Way", "Après la mort de son frère lors d'une mission en Roumanie, un ancien soldat forme une équipe pour traquer un mystérieux ennemi et accomplir sa vengeance.","https://zupimages.net/up/21/02/d4el.jpg", "Peter Sehr", "1994", "01H30" ); Film film10 = new Film("Night Hunter", "Night Hunter est un film réalisé par David Raymond (II) avec Alexandra Daddario, Henry Cavill. Synopsis : Des forces de police traquent un prédateur en ligne","https://zupimages.net/up/21/02/xd2m.jpg", "Issamdrmas", "1966", "01H40" ); List<Category> categories = categoryRepository.findAll(); film1.setCategory(categories.get(new Random().nextInt(categories.size()))); film2.setCategory(categories.get(new Random().nextInt(categories.size()))); film3.setCategory(categories.get(new Random().nextInt(categories.size()))); film4.setCategory(categories.get(new Random().nextInt(categories.size()))); filmRepository.save(film1); filmRepository.save(film2); filmRepository.save(film3); filmRepository.save(film4); filmRepository.save(film5); filmRepository.save(film6); filmRepository.save(film7); filmRepository.save(film8); filmRepository.save(film9); filmRepository.save(film10); } @Override public voidinitProjections() { double[] prix = new double[] { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; List<Film> films = filmRepository.findAll(); cityRepository;.findAll().forEach(city -> { city.getCinemas().forEach(cinema -> { cinema.getSalles().forEach(salle -> { int index = new Random().nextInt(films.size()); Film film = films.get(index); seanceRepository.findAll().forEach(seance -> { Projection projection = new Projection(); projection.setDateProjection(new Date()); projection.setFilm(film); projection.setPrice(prix[new Random().nextInt(prix.length)]); projection.setSalle(salle); projection.setSeance(seance); projectionRepository.save(projection); }); }); }); }); } @Override public void initTickets() { projectionRepository.findAll().forEach(projection -> { projection.getSalle().getPlaces().forEach(place -> { Ticket ticket = new Ticket(); ticket.setPlace(place); ticket.setPrice(projection.getPrice()); ticket.setProjection(projection); ticket.setReserve(false); ticketRepository.save(ticket); }); }); } }

@RestController API

@RestController is a convenience annotation for creating Restful controllers. It is a specialization of @Component and is autodetected through classpath scanning. It adds the @Controller and @ResponseBody annotations. It converts the response to JSON or XML. It does not work with the view technology, so the methods cannot return ModelAndView. It is typically used in combination with annotated handler methods based on the @RequestMapping annotation.


We will create CinemaResController class in web package:

- CinemaResController

Here, we are creating a CinemaResController controller

CinemaResController.java We'll inject this bean into the ShoppingManagerService bean using @Autowired on the field definition: We need to add map requests with request mapping annotations e.g. @RequestMapping, @GetMapping and @PostMapping

src/main/java/org/issamdrmas/web/CinemaResController.java):



package org.issamdrmas.cinema.web; import java.util.ArrayList; import java.util.List; import javax.transaction.Transactional; import org.issamdrmas.cinema.dao.FilmRepository; import org.issamdrmas.cinema.dao.TicketRepository; import org.issamdrmas.cinema.entites.Film; import org.issamdrmas.cinema.entites.Ticket; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController @CrossOrigin(origins = "*") public class CinemaResController { @Autowired private FilmRepository filmRepository; @Autowired private TicketRepository ticketRepository; @GetMapping("findFilmById/{id}") public Film findFilmById(@PathVariable(name = "id") Long id) { return filmRepository.findById(id).orElse(null); } @PostMapping("/puyTickets") @Transactional public List<Ticket> puyTickets(@RequestBody TicketFrom ticketFrom) { List<Ticket> tickets = new ArrayList<Ticket>(); ticketFrom.getTickets().forEach(idTick -> { Ticket ticket = ticketRepository.findById(idTick).orElse(null); ticket.setNameClient(ticketFrom.getNameClient()); ticket.setReserve(true); ticketRepository.save(ticket); tickets.add(ticket); }); return tickets; } } class TicketFrom { private String nameClient; private int codePayement; private List<Long> tickets = new ArrayList<Long>(); public String getNameClient() { return nameClient; } public void setNameClient(String nameClient) { this.nameClient = nameClient; } public List<Long> getTickets() { return tickets; } public voidsetTickets(List<Long> tickets) { this.tickets = tickets; } public int getCodePayement() { return codePayement; } public void setCodePayement(int codePayement) { this.codePayement = codePayement; } }

CinemaApplication

@BookStoreApplication and its use in a simple Spring Boot application. We use the @SpringBootApplication annotation in our Application or Main class to enable a host of features, e.g. Java-based Spring configuration, component scanning, and in particular for enabling Spring


src/main/java/com/book/store/CinemaApplication.java):



package org.issamdrmas.cinema; import org.issamdrmas.cinema.Service.ICinemaInitService; import org.issamdrmas.cinema.entites.Film; import org.issamdrmas.cinema.entites.Salle; import org.issamdrmas.cinema.entites.Ticket; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.data.rest.core.config.RepositoryRestConfiguration; @SpringBootApplication public class CinemaApplication implements CommandLineRunner{ @Autowired private ICinemaInitService iCinemaInitService; @Autowired private RepositoryRestConfiguration repositoryRestConfiguration; public static void main(String[] args) { SpringApplication.run(CinemaApplication.class, args); System.out.println("App started...."); } @Override public void run(String... args) throws Exception { repositoryRestConfiguration.exposeIdsFor(Film.class, Salle.class, Ticket.class); iCinemaInitService.initCities(); iCinemaInitService.initCinemas(); iCinemaInitService.initSalles(); iCinemaInitService.initPlaces(); iCinemaInitService.initSeances(); iCinemaInitService.initCategories(); iCinemaInitService.initFilms(); iCinemaInitService.initProjections(); iCinemaInitService.initTickets(); } }


Conclusion

Now we have an overview of Spring Boot example when building a @RestController API.

We also take a look at client-server architecture for REST API using Spring Web MVC & Spring Data JPA, as well, we are gooing to continue with Angular 10 project structure for building a front-end app to make HTTP requests and consume responses.




2 Comments

  1. Hello
    Here the Part 2 With Angular https://programming-with-drmas.blogspot.com/2022/01/build-application-reserve-ticket-for_44.html

    ReplyDelete
Previous Post Next Post


Follow us on facebook