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.javaWe 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
- CinemaInitServiceImplHere, 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:
- CinemaResControllerHere, 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.
part 2?
ReplyDeleteHello
ReplyDeleteHere the Part 2 With Angular https://programming-with-drmas.blogspot.com/2022/01/build-application-reserve-ticket-for_44.html