Getting Started | Building an Application with Spring Boot
Build an application ecommerce with Spring boot and Angular use Jpa
Objective:
In this tutorial We are going to build an application Ecommerce. The project content user, category, product, comment and cart for the user, we will create to parts backend use Spring boot and frontend use Angular. The admin can add, modfily and delete, the user after login can add a comment or buy products as will choose to delivery also can add to his cart.
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.ecommerce</groupId>
<artifactId>ecommerce</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ecommerce</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</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>org.springframework.security</groupId>
<artifactId>spring-security-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 ecommerce
src/main/resources/application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/ecommerce?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 these entities
- Cart
- Category
- Comment
- Order
- OrderProduct
- OrderProductPk
- Product
- Tag
- User
Here, we are creating an Entity
Cart.java This object content id, name, price, quantity, pictureUrl and relational @ManyToOne with User
src/main/java/com/ecommerce/model/Cart.java):
package com.ecommerce.modal;
import javax.persistence.*;
import com.fasterxml.jackson.annotation.JsonBackReference;
@Entity
@Table(name = "carts")
public class Cart {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Double price;
private int quantity;
private String pictureUrl;
@JsonBackReference(value = "user")
@ManyToOne
private User user;
public Cart() {
super();
}
public Cart(String name, Double price, int quantity,
String pictureUrl, User user) {
super();
this.name = name;
this.price = price;
this.quantity = quantity;
this.pictureUrl = pictureUrl;
this.user = user;
}
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 Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public String getPictureUrl() {
return pictureUrl;
}
public void setPictureUrl(String pictureUrl) {
this.pictureUrl = pictureUrl;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
Here, we are creating an Entity
Category.java This object content id, name, and relational @ManyToOne with User and @OneToMany with Product
src/main/java/com/ecommerce/model/Category.java):
package com.ecommerce.modal;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonProperty.Access;
@Entity
@Table(name = "categoires")
public class Category {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@JsonBackReference(value = "user")
@ManyToOne
private User user;
@JsonProperty(access = Access.WRITE_ONLY)
@OneToMany(cascade = CascadeType.ALL, mappedBy = "category")
private List<Product> products;
public Category() {
super();
}
public Category(String name, User user, List<Product> products) {
super();
this.name = name;
this.user = user;
this.products = products;
}
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 User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
public void addProductToCategory(Product product) {
if (getProducts()==null) {
this.products = new ArrayList<>();
}
getProducts().add(product);
product.setCategory(this);
}
}
Here, we are creating an Entity
Comment.java This object content id, title, message, addedBy, addedAt and relational @ManyToOne with Product
src/main/java/com/ecommerce/model/Comment.java):
package com.ecommerce.modal;
import java.util.Date;
import javax.persistence.*;
import com.fasterxml.jackson.annotation.JsonBackReference;
@Entity
@Table(name="comments")
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
@Lob
@Column( length = 100000 )
private String message;
private String addedBy;
@Temporal(TemporalType.TIMESTAMP)
private Date addedAt;
@JsonBackReference(value = "product")
@ManyToOne
private Product product;
public Comment() {
super();
}
public Comment(String title, String message, String addedBy, Date addedAt, Product product) {
super();
this.title = title;
this.message = message;
this.addedBy = addedBy;
this.addedAt = addedAt;
this.product = product;
}
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 getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getAddedBy() {
return addedBy;
}
public void setAddedBy(String addedBy) {
this.addedBy = addedBy;
}
public Date getAddedAt() {
return addedAt;
}
public void setAddedAt(Date addedAt) {
this.addedAt = addedAt;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
}
Here, we are creating an Entity
Order.java This object content id, dateCreated, status, and relational @ManyToOne with orderProducts
src/main/java/com/ecommerce/model/Order.java):
package com.ecommerce.modal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import javax.persistence.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
@Entity
@Table(name = "orders")
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="orderProducts")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@JsonFormat(pattern="dd/MM/yyyy")
private LocalDate dateCreated;
private String status;
@OneToMany(mappedBy="pk.order")
private List<OrderProduct> orderProducts = new ArrayList<OrderProduct>();
public () {
super();
}
public Order(LocalDate dateCreated, String status, List<OrderProduct> orderProducts) {
super();
this.dateCreated = dateCreated;
this.status = status;
this.orderProducts = orderProducts;
}
public Long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
publicLocalDate getDateCreated() {
return dateCreated;
}
public void setDateCreated(LocalDate dateCreated) {
this.dateCreated = dateCreated;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public List<OrderProduct> getOrderProducts() {
return orderProducts;
}
public voidsetOrderProducts(List<OrderProduct> orderProducts) {
this.orderProducts = orderProducts;
}
}
Here, we are creating an Entity
OrderProduct.java This object content quantity @EmbeddedId in OrderProductPK We need to Overriding equals() method
Java SE defines a contract that our implementation of the equals() method must fulfill. Most of the criteria are common sense. The equals() method must be:
reflexive: an object must equal itself
symmetric: x.equals(y) must return the same result as y.equals(x)
transitive: if x.equals(y) and y.equals(z) then also x.equals(z)
consistent: the value of equals() should change only if a property that is contained in equals() changes (no randomness allowed)
src/main/java/com/ecommerce/model/OrderProduct.java):
package com.ecommerce.modal;
import javax.persistence.*;
import com.fasterxml.jackson.annotation.JsonIgnore;
@Entity
@Table(name = "orderProducts")
public class OrderProduct {
@EmbeddedId
@JsonIgnore
private OrderProductPK pk;
@Column(nullable = false)
private Integer quantity = 1;
public OrderProduct(Order order, Product product, Integer quantity) {
pk = new OrderProductPK();
pk.setOrder(order);
pk.setProduct(product);
this.quantity = quantity;
}
public OrderProductPK getPk() {
return pk;
}
public void setPk(OrderProductPK pk) {
this.pk = pk;
}
public Integer getQuantity() {
return quantity;
}
public void setQuantity(Integer quantity) {
this.quantity = quantity;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
OrderProduct other = (OrderProduct) obj;
if (pk == null) {
if (other.pk != null) {
return false;
}
} else if (!pk.equals(other.pk)) {
return false;
}
return true;
}
}
Here, we are creating an Entity
OrderProductPK.java This object content relational @ManyToOne with Order and Product We need to Override hashCode() and equals() methods
hashCode() returns an integer representing the current instance of the class. We should calculate this value consistent with the definition of equality for the class. Thus if we override the equals() method, we also have to override hashCode().src/main/java/com/ecommerce/model/OrderProductPK.java):
package com.ecommerce.modal;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import javax.persistence.*;
import java.io.Serializable;
@Embeddable
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "order")
public class OrderProductPK implements Serializable {
private static final long serialVersionUID = 1L;
@ManyToOne(optional=false, fetch = FetchType.LAZY)
@JoinColumn(name="orderId")
private Order order;
@ManyToOne(optional=false, fetch = FetchType.LAZY)
@JoinColumn(name="productId")
private Product product;
public OrderProductPK() {
super();
}
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((order.getId() == null)
? 0
: order
.getId()
.hashCode());
result = prime * result + ((product.getId() == null)
? 0
: product
.getId()
.hashCode());
return result ;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
OrderProductPK other = (OrderProductPK) obj;
if (order == null) {
if (other.order != null) {
return false;
}
}else if (!order.equals(other.order)) {
return false;
}
if (product == null) {
if (other.product != null) {
return false;
}
}else if (!product.equals(other.product)) {
return false;
}
return true;
}
}
Here, we are creating an Entity
Product.java This object content id, name, price, description, pictureUrl and relational @ManyToOne with Category @ManyToMany with Tag @OneToMany with Comment
src/main/java/com/ecommerce/model/Product.java):
package com.ecommerce.modal;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonProperty.Access;
@Entity
@Table(name = "products")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String description;
private Double price;
private String pictureUrl;
@JsonBackReference(value = "category")
@ManyToOne
private Category category;
@JsonProperty(access = Access.WRITE_ONLY)
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "tag_products", joinColumns = @JoinColumn(name = "tag_id"), inverseJoinColumns = @JoinColumn(name = "product_id"))
private List<Tag> tags;
@JsonProperty(access = Access.WRITE_ONLY)
@OneToMany(cascade = CascadeType.ALL, mappedBy = "product")
private List<Comment> comments;
public () {
super();
}
public Product(String name, String description, Double price, String pictureUrl, Category category, List<Tag> tags,
List<Comment> comments) {
super();
this.name = name;
this.description = description;
this.price = price;
this.pictureUrl = pictureUrl;
this.category = category;
this.tags = tags;
this.comments = comments;
}
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 String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public String getPictureUrl() {
return pictureUrl;
}
public void setPictureUrl(String pictureUrl) {
this.pictureUrl = pictureUrl;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
public List<Tag> getTags() {
return tags;
}
public void setTags(List<Tag> tags) {
this.tags = tags;
}
public List<Comment> getComments() {
return comments;
}
public void setComments(List<Comment> comments) {
this.comments = comments;
}
public void addCommentToProduct(Comment comment) {
if (getComments() == null) {
this.comments = new ArrayList<>();
}
getComments().add(comment);
comment.setProduct(this);
}
public void addTag(Tag tag) {
if (getTags() == null) {
this.tags = new ArrayList<>();
}
if (!getTags().contains(tag)) {
getTags().add(tag);
}
}
}
Here, we are creating an Entity
Tag.java This object content id, name and relational @ManyToOne with Product and @ManyToMany with Product
src/main/java/com/ecommerce/model/Tag.java):
package com.ecommerce.modal;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonProperty.Access;
@Entity
@Table(name = "tags")
public class Tag {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@JsonBackReference(value = "product")
@ManyToOne
private Product product;
@JsonProperty(access = Access.WRITE_ONLY)
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "product_tags",
joinColumns = @JoinColumn(name = "product_id"),
inverseJoinColumns = @JoinColumn(name = "tag_id"))
private List<Product> products;
public Tag() {
super();
}
public Tag(String name, Product product, List<Product> products) {
super();
this.name = name;
this.product = product;
this.products = products;
}
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 Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
public void addProductToTag(Product product) {
if(getProducts()==null) {
this.products = new ArrayList<>();
}
if (!getProducts().contains(product)) {
getProducts().add(product);
}
}
}
Here, we are creating an Entity
User.java This object content id, username, password, admin, email, nameOnCard, cardNumber, cvv, address and relational @ManyToOne with Category and Cart
src/main/java/com/ecommerce/model/User.java):
package com.ecommerce.modal;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonProperty.Access;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String username;
private String password;
private boolean admin;
private String email;
private String nameOnCard;
private String cardNumber;
private int cvv;
private String address;
@JsonProperty(access = Access.AUTO)
@OneToMany(cascade = CascadeType.ALL, mappedBy = "user")
private List<Category> categories;
@JsonProperty(access = Access.AUTO)
@OneToMany(cascade = CascadeType.MERGE, mappedBy = "user")
private List<Cart> carts;
public User() {
super();
}
public User(String username, String password, boolean admin, String email, String nameOnCard,
String cardNumber, int cvv, String address, List<Category> categories, List<Cart> carts) {
super();
this.username = username;
this.password = password;
this.admin = admin;
this.email = email;
this.nameOnCard = nameOnCard;
this.cardNumber = cardNumber;
this.cvv = cvv;
this.address = address;
this.categories = categories;
this.carts = carts;
}
public Long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isAdmin() {
return admin;
}
public void setAdmin(boolean admin) {
this.admin = admin;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getNameOnCard() {
return nameOnCard;
}
public void setNameOnCard(String nameOnCard) {
this.nameOnCard = nameOnCard;
}
public String getCardNumber() {
return cardNumber;
}
public void setCardNumber(String cardNumber) {
this.cardNumber = cardNumber;
}
public int getCvv() {
return cvv;
}
public void setCvv(int cvv) {
this.cvv = cvv;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public List<Category> getCategories() {
return categories;
}
public void setCategories(List<Category> categories) {
this.categories = categories;
}
public List<Cart> getCarts() {
return carts;
}
public void setCarts(List<Cart> carts) {
this.carts = carts;
}
public void addCategoryToUser(Category category) {
if (getCategories()==null) {
this.categories = new ArrayList<>();
}
getCategories().add(category);
category.setUser(this);
}
public void addCartToUser(Cart cart) {
if(getCarts()==null) {
this.carts = new ArrayList<>();
}
getCarts().add(cart);
cart.setUser(this);
}
public void removeFromCart(Cart cart) {
if (getCarts()!=null) {
getCarts().remove(cart);
}
}
}
Here, we are creating an enum OrderStatus
src/main/java/com/ecommerce/model/OrderStatus.java):
import com.ecommerce.modal;
public enum OrderStatus {
PAID
}
Here, we are creating an Entity Dto
src/main/java/com/ecommerce/dto/OrderProductDto.java):
package com.ecommerce.dto;
import com.ecommerce.modal.Product;
public class OrderProductDto {
private Product product;
private Integer quantity;
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public Integer getQuantity() {
return quantity;
}
public void setQuantity(Integer quantity) {
this.quantity = quantity;
}
}
Here, we are creating an interface ResourceNotFoundException
src/main/java/com/ecommerce/exception/ResourceNotFoundException.java):
package com.ecommerce.exception;
public class ResourceNotFoundException extends RuntimeException {
private static final long serialVersionUID = 5861310537366287163L;
public ResourceNotFoundException() {
super();
}
public ResourceNotFoundException(final String message, final Throwable cause) {
super(message, cause);
}
public ResourceNotFoundException(final String message) {
super(message);
}
public ResourceNotFoundException(final Throwable cause) {
super(cause);
}
}
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 interfaces Dao
- CartDao
- CategoryDao
- CommentDao
- OrderDao
- OrderProductDao
- ProductDao
- TagDao
- UserDao
Here, we are creating an interface CartDao
src/main/java/com/ecommerce/dao/CartDao.java):
package com.ecommerce.dao;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import com.ecommerce.modal.Cart;
public interface CartDao extends JpaRepository<Cart, Long>{
Optional<Cart> findByName(String name);
}
Here, we are creating an interface CategoryDao
src/main/java/com/ecommerce/dao/CategoryDao.java):
package com.ecommerce.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import com.ecommerce.modal.Category;
public interface CategoryDao extends JpaRepository<Category, Long>{
}
Here, we are creating an interface CommentDao
src/main/java/com/ecommerce/dao/CommentDao.java):
package com.ecommerce.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import com.ecommerce.modal.Comment;
public interface CommentDao extends JpaRepository<Comment, Long> {
}
Here, we are creating an interface OrderDao
src/main/java/com/ecommerce/dao/OrderDao.java):
package com.ecommerce.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import com.ecommerce.modal.Order;
public interface OrderDao extends JpaRepository<Order, Long> {
}
Here, we are creating an interface OrderProductDao
src/main/java/com/ecommerce/dao/OrderProductDao.java):
package com.ecommerce.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import com.ecommerce.modal.OrderProduct;
public interface OrderProductDao extends JpaRepository<OrderProduct, Long> {
}
Here, we are creating an interface ProductDao
src/main/java/com/ecommerce/dao/ProductDao.java):
package com.ecommerce.dao;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import com.ecommerce.modal.Product;
public interface ProductDao extends JpaRepository<Product, Long>{
@Query("SELECT p FROM Product p WHERE p.name LIKE :n")
List<Product> findByName(@Param("n") String name);
}
Here, we are creating an interface TagDao
src/main/java/com/ecommerce/dao/TagDao.java):
package com.ecommerce.dao;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import com.ecommerce.modal.Tag;
public interface TagDao extends JpaRepository<Tag, Long>{
@Query("SELECT p FROM Tag p WHERE p.name LIKE :n")
List<Tag> findByName(@Param("n") String name);
}
Here, we are creating an interface UserDao
src/main/java/com/ecommerce/dao/UserDao.java):
package com.ecommerce.dao;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import com.ecommerce.modal.User;
public interface UserDao extends JpaRepository<User, Long>{
Optional<User> findByUsername(String name);
}
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 two interfaces in service package:
- CartService
- CategoryService
- CommentService
- OrderService
- OrderProductService
- ProductService
- TagService
- UserService
What's the difference between @Component, @Repository and @Service
Can @Component, @Repository and @Service annotations be used interchangeably in Spring or do they provide any particular functionality besides acting as a notation device?
In other words, if I have a Service class and I change the annotation from @Service to @Component, will it still behave the same way?
Here, we are creating an interface CartService
src/main/java/com/ecommerce/service/CartService.java):
package com.ecommerce.service;
import java.util.List;
import com.ecommerce.modal.Cart;
public interface CartService {
Cart addCartToUser(Cart cart, long idUser);
void deleteCart(long id);
List<Cart> findCartsForUser(long idUser);
Cart findCartById(long id);
void removeFromCart(long idCart, long idUser);
Cart findByCartName(String name);
}
Here, we are creating an interface CategoryService
src/main/java/com/ecommerce/service/CategoryService.java):
package com.ecommerce.service;
import java.util.List;
import com.ecommerce.modal.Category;
public interface CategoryService {
Category addCategoryToUser(Category category, long idUser);
Category editCategory(Category category, long id);
Category findCategoryById(long id);
void deleteCategory(long id);
List<Category> findAllCategories();
List<Category> findCategoriesForUser(long id);
}
Here, we are creating an interface CommentService
src/main/java/com/ecommerce/service/CommentService.java):
package com.ecommerce.service;
import java.util.List;
import com.ecommerce.modal.Comment;
public interface CommentService {
Comment addCommentToProduct(Comment comment, long idProduct);
Comment editComment(Comment comment, long id);
Comment findCommentById(long id);
void deleteComment(long id);
List<Comment> findCommentsForProduct(long idProduct);
List<Comment> findAllComments();
}
Here, we are creating an interface OrderProductService
src/main/java/com/ecommerce/service/OrderProductService.java):
package com.ecommerce.service;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.springframework.validation.annotation.Validated;
import com.ecommerce.modal.OrderProduct;
@Validated
public interface OrderProductService {
OrderProduct create(@NotNull(message = "The products for order cannot be null.") @Valid OrderProduct orderProduct);
}
Here, we are creating an interface OrderService
src/main/java/com/ecommerce/service/OrderService.java):
package com.ecommerce.service;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.springframework.validation.annotation.Validated;
import com.ecommerce.modal.Order;
@Validated
public interface OrderService {
@NotNull
Iterable<Order> getAllOrders();
Order create(@NotNull(message = "The order cannot be null.") @Valid Order order);
void update (@NotNull(message = "The order cannot be null.") @Valid Order order);
}
Here, we are creating an interface ProductService
src/main/java/com/ecommerce/service/ProductService.java):
package com.ecommerce.service;
import java.util.List;
import com.ecommerce.modal.Product;
public interface ProductService {
Product addProductToCategory(Product product, long idCategory);
Product editProduct(Product product, long id);
Product findProductById(long id);
void deleteProduct(long id);
List<Product> findAllProducts();
List<Product> findProductsForCategory(long idCategory);
Product getProduct(long id);
}
Here, we are creating an interface CartDao
src/main/java/com/ecommerce/service/Arbitrate.java):
package com.ecommerce.service;
import java.util.List;
import com.ecommerce.modal.Product;
import com.ecommerce.modal.Tag;
public interface TagService {
void addTagToProduct(long idProduct, long idTag);
List<Tag> findTagsForProduct(long idProduct);
List<Tag> findAllTags();
void deleteTagFromProduct(long idTag, long idProduct);
Tag addTag(Tag tag);
void deleteTag(long id);
Tag findTagById(long id);
List<Product> findProductsForTag(long idTag);
}
Here, we are creating an interface UserService
src/main/java/com/ecommerce/service/UserService.java):
package com.ecommerce.service;
import java.util.List;
import com.ecommerce.modal.User;
public interface UserService {
User addUser(User user);
List<User> findAllUsers();
User editUser(User user, long id);
User findUserById(long id);
void deleteUser(long id);
User findByUsername(String name);
}
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 these classes in the impl package
- CartServiceImpl
- CategoryServiceImpl
- CommentServiceImpl
- OrderServiceImpl
- OrderProductServiceImpl
- ProductServiceImpl
- TagServiceImpl
- UserServiceImpl
Here, we are creating an class CartServiceImpl
src/main/java/com/ecommerce/impl/CartServiceImpl.java):
package com.ecommerce.impl;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.ecommerce.dao.CartDao;
import com.ecommerce.dao.UserDao;
import com.ecommerce.modal.Cart;
import com.ecommerce.modal.User;
import com.ecommerce.service.CartService;
@Transactional
@Component
public class CartServiceImpl implements CartService {
@Autowired
private CartDao cartDao;
@Autowired
private UserDao userDao;
@Override
public Cart addCartToUser(Cart cart, long idUser) {
User user = userDao.findById(idUser).orElse(null);
user.addCartToUser(cart);
return userDao;.save(cart);
}
@Override
public void deleteCart(long id) {
userDao;.deleteById(id);
}
@Override
public List<Cart> findCartsForUser(long idUser) {
User user = userDao.findById(idUser).orElse(null);
return user.getCarts();
}
@Override
public Cartv findCartById(long id) {
return userDao;.findById(id).orElse(null);
}
@Override
public void removeFromCart(long idCart, long idUser) {
User user = userDao.findById(idUser).orElse(null);
Cart cart = userDao;.findById(idCart).orElse(null);
user.removeFromCart(cart);
userDao;.delete(cart);
}
@Override
public Cart findByCartName(String name) {
Optional<Cart> carts = userDao;.findByName(name);
if (carts.isPresent()) {
Cart cart = carts.get();
return cart;
}
return null;
}
}
Here, we are creating an class CategoryServiceImpl
src/main/java/com/ecommerce/impl/CategoryServiceImpl.java):
package com.ecommerce.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.ecommerce.dao.CategoryDao;
import com.ecommerce.dao.UserDao;
import com.ecommerce.modal.Category;
import com.ecommerce.modal.User;
import com.ecommerce.service.CategoryService;
@Transactional
@Component
public class CategoryServiceImpl implements CategoryService {
@Autowired
private CategoryDao categoryDao;
@Autowired
private UserDao userDao;
@Override
public Category addCategoryToUser(Category category, long idUser) {
User user = userDao.findById(idUser).orElse(null);
user.addCategoryToUser(category);
return categoryDao.save(category);
}
@Override
public Category editCategory(Category category, long id) {
Category existsCategory = categoryDao.findById(id).orElse(null);
existsCategory.setName(category.getName());
return categoryDao.save(existsCategory);
}
@Override
public Category findCategoryById(long id) {
return categoryDao.findById(id).orElse(null);
}
@Override
public void deleteCategory(long id) {
categoryDao.deleteById(id);
}
@Override
public List<Category> findAllCategories() {
return categoryDao.findAll();
}
@Override
public List<Category> findCategoriesForUser(long id) {
User user = userDao.findById(id).orElse(null);
return user.getCategories();
}
}
Here, we are creating an class CommentServiceImpl
src/main/java/com/ecommerce/impl/CommentServiceImpl.java):
package com.ecommerce.impl;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.ecommerce.dao.CommentDao;
import com.ecommerce.dao.ProductDao;
import com.ecommerce.modal.Comment;
import com.ecommerce.modal.Product;
import com.ecommerce.service.CommentService;
@Transactional
@Component
public class CommentServiceImpl implements CommentService{
@Autowired
private CommentDao commentDao;
@Autowired
private ProductDao productDao;
@Override
public Comment addCommentToProduct(Comment comment, long idProduct) {
Product product = productDao.findById(idProduct).orElse(null);
comment.setAddedAt(new Date());
product.addCommentToProduct(comment);
return commentDao.save(comment);
}
@Override
public Comment editComment(Comment comment, long id) {
Comment existComponent = commentDao.findById(id).orElse(null);
existComponent.setTitle(comment.getTitle());
existComponent.setMessage(comment.getMessage());
existComponent.setAddedAt(new Date());
existComponent.setAddedBy(comment.getAddedBy());
return commentDao.save(existComponent);
}
@Override
public Comment findCommentById(long id) {
return commentDao.findById(id).orElse(null);
}
@Override
public void deleteComment(long id) {
commentDao.deleteById(id);
}
@Override
public List<Comment> findCommentsForProduct(long idProduct) {
Product product = productDao.findById(idProduct).orElse(null);
return product.getComments();
}
@Override
public List<Comment> findAllComments() {
return commentDao.findAll();
}
}
Here, we are creating an class OrderProductServiceImpl
src/main/java/com/ecommerce/impl/OrderProductServiceImpl.java):
package com.ecommerce.impl;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.ecommerce.dao.OrderProductDao;
import com.ecommerce.modal.OrderProduct;
import com.ecommerce.service.OrderProductService;
@Transactional
@Component
public class OrderProductServiceImpl implements OrderProductService {
@Autowired
private OrderProductDao orderProductDao;
@Override
public OrderProduct create(@NotNull(message = "The products for order cannot be null.") @Valid OrderProduct orderProduct) {
return this.orderProductDao.save(orderProduct);
}
}
Here, we are creating an class OrderServiceImpl
src/main/java/com/ecommerce/impl/OrderServiceImpl.java):
package com.ecommerce.impl;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ecommerce.dao.OrderDao;
import com.ecommerce.modal.Order;
import com.ecommerce.service.OrderService;
@Service
@Transactional
public class OrderServiceImpl implements OrderService {
private OrderDao orderDao;
public OrderServiceImpl(OrderDao orderDao) {
this.orderDao = orderDao;
}
@Override
public @NotNull Iterable<Order> getAllOrders() {
return this.orderDao.findAll();
}
@Override
public Order create(@NotNull(message = "The order cannot be null.") @Valid Order order) {
return this.orderDao.save(order);
}
@Override
public void update(@NotNull(message = "The order cannot be null.") @Valid Order order) {
this.orderDao.save(order);
}
}
Here, we are creating an class ProductServiceImpl
src/main/java/com/ecommerce/impl/ProductServiceImpl.java):
package com.ecommerce.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.ecommerce.dao.CategoryDao;
import com.ecommerce.dao.ProductDao;
import com.ecommerce.modal.Category;
import com.ecommerce.modal.Product;
import com.ecommerce.service.ProductService;
@Transactional
@Component
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductDao productDao;
@Autowired
private CategoryDao categoryDao;
@Override
public Product addProductToCategory(Product product, long idCategory) {
Category category = categoryDao.findById(idCategory).orElse(null);
category.addProductToCategory(product);
return categoryDao.save(product);
}
@Override
public Product editProduct(Product product, long id) {
Product existProduct = categoryDao.findById(id).orElse(null);
existProduct.setName(product.getName());
existProduct.setDescription(product.getDescription());
existProduct.setPictureUrl(product.getPictureUrl());
existProduct.setPrice(product.getPrice());
return categoryDao.save(existProduct);
}
@Override
public Product findProductById(long id) {
return categoryDao.findById(id).orElse(null);
}
@Override
public void deleteProduct(long id) {
categoryDao.deleteById(id);
}
@Override
public List<Product> findAllProducts() {
return categoryDao.findAll();
}
@Override
public List<Product> findProductsForCategory(long idCategory) {
Category category = categoryDao.findById(idCategory).orElse(null);
return category.getProducts();
}
@Override
public Product getProduct(long id) {
return categoryDao.findById(id).orElse(null);
}
}
Here, we are creating an class CartDao
src/main/java/com/ecommerce/impl/Arbitrate.java):
package com.ecommerce.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.ecommerce.dao.ProductDao;
import com.ecommerce.dao.TagDao;
import com.ecommerce.modal.Product;
import com.ecommerce.modal.Tag;
import com.ecommerce.service.TagService;
@Transactional
@Component
public class TagServiceeImpl implements TagService {
@Autowired
private TagDao tagDao;
@Autowired
private ProductDao productDao;
@Override
public void addTagToProduct(long idProduct, long idTag) {
Product product = productDao.findById(idProduct).orElse(null);
Tag tag = tagDao.findById(idTag).orElse(null);
tag.addProductToTag(product);
product.addTag(tag);
}
@Override
public List<Tag> findTagsForProduct(long idProduct) {
Product product = productDao.findById(idProduct).orElse(null);
return product.getTags();
}
@Override
public void deleteTagFromProduct(long idTag, long idProduct) {
Product product = productDao.findById(idProduct).orElse(null);
Tag tag = tagDao.findById(idTag).orElse(null);
product.getTags().remove(tag);
}
@Override
pupublicblic Tag addTag(Tag tag) {
return tagDao.save(tag);
}
@Override
public void deleteTag(long id) {
tagDao.deleteById(id);
}
@Override
public Tag findTagById(long id) {
return tagDao.findById(id).orElse(null);
}
@Override
public List<Tag> findAllTags() {
return tagDao.findAll();
}
@Override
public List<Product> findProductsForTag(long idTag) {
Tag tag = tagDao.findById(idTag).orElse(null);
return tag.getProducts();
}
}
Here, we are creating an class UserServiceImpl
src/main/java/com/ecommerce/impl/UserServiceImpl.java):
package com.ecommerce.impl;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.ecommerce.dao.UserDao;
import com.ecommerce.modal.User;
import com.ecommerce.service.UserService;
@Transactional
@Component
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public User addUser(User user) {
List<User> users = userDao.findAll();
if (users.size() == 0) {
user.setAdmin(true);
}
for (User existUser : users) {
if (user.getUsername().equals(existUser.getUsername())) {
existUser.setUsername(existUser.getUsername());
existUser.setPassword(existUser.getPassword());
return userDao.save(existUser);
}
}
return userDao.save(user);
}
@Override
public List<User> findAllUsers() {
return userDao.findAll();
}
@Override
public User editUser(User user, long id) {
User existUser = userDao.findById(id).orElse(null);
existUser.setUsername(user.getUsername());
existUser.setPassword(user.getPassword());
existUser.setAdmin(user.isAdmin());
existUser.setEmail(user.getEmail());
existUser.setNameOnCard(user.getNameOnCard());
existUser.setCardNumber(user.getCardNumber());
existUser.setCvv(user.getCvv());
existUser.setAddress(user.getAddress());
return userDao.save(existUser);
}
@Override
public User findUserById(long id) {
return userDao.findById(id).orElse(null);
}
@Override
public void deleteUser(long id) {
userDao.deleteById(id);
}
@Override
public User findByUsername(String username) {
Optional<User> users = userDao.findByUsername(username);
if (users.isPresent()) {
User user = users.get();
return user;
}
return null;
}
}
@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 these classes in controller package:
- CartController
- CategoryController
- CommentController
- OrderController
- ProductController
- TagController
- UserController
In The Controller We'll inject this bean into the controller bean using @Autowired on the field definition: We need to add map requests with request mapping annotations e.g. @RequestMapping, @GetMapping and @PostMapping
Here, we are creating an class CartController
src/main/java/com/ecommerce/controller/CartController.java):
package com.ecommerce.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ecommerce.modal.Cart;
import com.ecommerce.service.CartService;
@RestController
@RequestMapping(value = "/api")
@CrossOrigin(origins = "*")
public class CartController {
@Autowired
private CartService cartService;
@PostMapping("/addCartToUser/{idUser}")
Cart addCartToUser(@RequestBody Cart cart, @PathVariable long idUser) {
return cartService.addCartToUser(cart, idUser);
}
@DeleteMapping("/deleteCart/{id}")
void deleteCart(@PathVariable long id) {
cartService.deleteCart(id);
}
@GetMapping("/findCartsForUser/{idUser}")
List<Cart> findCartsForUser(@PathVariable long idUser) {
return cartService.findCartsForUser(idUser);
}
@GetMapping("/findCartById/{id}")
Cart findCartById(@PathVariable long id) {
return cartService.findCartById(id);
}
@DeleteMapping("/removeFromCart/{idCart}/{idUser}")
void removeFromCart(@PathVariable long idCart, @PathVariable long idUser) {
cartService.removeFromCart(idCart, idUser);
}
@GetMapping("/findByCartName/{name}")
Cart findByCartName(@PathVariable String name) {
return cartService.findByCartName(name);
}
}
Here, we are creating an class CommentController
src/main/java/com/ecommerce/controller/CommentController.java):
package com.ecommerce.controller;
import com.ecommerce.modal.Comment;
import com.ecommerce.service.CommentService;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping(value = "/api")
@CrossOrigin(origins = "*")
public class CommentController {
@Autowired
private CommentService commentService;
@PostMapping("/addCommentToProduct/{idProduct}")
return addCommentToProduct(@RequestBody Comment comment, @PathVariable long idProduct) {
return commentService.addCommentToProduct(comment, idProduct);
}
@PutMapping("/editComment/{id}")
Comment editComment(@RequestBody Comment comment, @PathVariable long id) {
return commentService.editComment(comment, id);
}
@GetMapping("/findCommentById/{id}")
Comment findCommentById(@PathVariable long id) {
return commentService.findCommentById(id);
}
@DeleteMapping("/deleteComment/{id}")
void deleteComment(@PathVariable long id) {
commentService.deleteComment(id);
}
@GetMapping("/findCommentsForProduct/{idProduct}")
List<Comment> findCommentsForProduct(@PathVariable long idProduct) {
return commentService.findCommentsForProduct(idProduct);
}
@GetMapping("/findAllComments")
List<Comment> findAllComments() {
return commentService.findAllComments();
}
}
Here, we are creating an class OrderController
src/main/java/com/ecommerce/controller/OrderController.java):
package com.ecommerce.controller;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import javax.validation.constraints.NotNull;
import java.util.Objects;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import com.ecommerce.dto.OrderProductDto;
import com.ecommerce.exception.ResourceNotFoundException;
import com.ecommerce.modal.Order;
import com.ecommerce.modal.OrderProduct;
import com.ecommerce.modal.OrderStatus;
import com.ecommerce.service.OrderProductService;
import com.ecommerce.service.OrderService;
import com.ecommerce.service.ProductService;
@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/api/orders")
public class OrderController {
private ProductService productService;
private OrderService orderService;
private OrderProductService orderProductService;
public OrderController(ProductService productService, OrderService orderService,
OrderProductService orderProductService) {
suber();
this.productService = productService;
this.orderService = orderService;
this.orderProductService = orderProductService;
}
@GetMapping
@ResponseStatus(HttpStatus.OK)
public @NotNull Iterable<Order> list(){
return this.orderService.getAllOrders();
}
@PostMapping("/orders")
public ResponseEntity<Order> create(@RequestBody OrderForm form){
List<OrderProductDto> formDtos = form.getpOrderProductDtos();
validateProductsExistance(formDtos);
Order order = new Order();
order.setStatus(OrderStatus.PAID.name());
order = this.orderService.create(order);
List<OrderProduct> orderProducts = new ArrayList<OrderProduct>();
for(OrderProductDto dto: formDtos) {
orderProducts.add(orderService.create(new OrderProduct(order, productService.getProduct(dto.getProduct().getId()), dto.getQuantity())));
}
order.setOrderProducts(orderProducts);
this.orderService.update(order);
String uri = ServletUriComponentsBuilder
.fromCurrentServletMapping()
.path("/orders/{id}")
.buildAndExpand(order.getId())
.toString();
HttpHeaders headers = new HttpHeaders();
headers.add("Location", uri);
return new ResponseEntity<>(order, headers, HttpStatus.CREATED);
}
private void validateProductsExistance(List<OrderProductDto> orderProducts) {
List<OrderProductDto> list = orderProducts
.stream()
.filter(op -> Objects.isNull(productService.getProduct(op.getProduct().getId())))
.collect(Collectors.toList());
if (!CollectionUtils.isEmpty(list)) {
new ResourceNotFoundException("Product not found");
}
}
public static class OrderForm {
private List<OrderProductDto> orderProductDtos;
public List<OrderProductDto> getpOrderProductDtos() {
return orderProductDtos;
}
public void setpOrderProductDtos(List<OrderProductDto> orderProductDtos) {
this.orderProductDtos = orderProductDtos;
}
}
}
Here, we are creating an class ProductController
src/main/java/com/ecommerce/controller/ProductController.java):
package com.ecommerce.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ecommerce.dao.ProductDao;
import com.ecommerce.modal.Product;
import com.ecommerce.service.ProductService;
@RestController
@RequestMapping(value = "/api")
@CrossOrigin(origins = "*")
public class ProductController {
@Autowired
private ProductService productService;
@Autowired
private ProductDao productDao;
@PostMapping("/addProductToCategory/{idCategory}")
Product addProductToCategory(@RequestBody Product product, @PathVariable long idCategory) {
return productService.addProductToCategory(product, idCategory);
}
@PutMapping("/editProduct/{id}")
Product editProduct(@RequestBody Product product, @PathVariable long id) {
return productService.editProduct(product, id);
}
@GetMapping("/findProductById/{id}")
Product findProductById(@PathVariable long id) {
return productService.findProductById(id);
}
@DeleteMapping("/deleteProduct/{id}")
void deleteProduct(@PathVariable long id) {
productService.deleteProduct(id);
}
@GetMapping("/findAllProducts")
List<Product> findAllProducts() {
return productService.findAllProducts();
}
@GetMapping("/findProductsForCategory/{idCategory}")
List<Product> findProductsForCategory(@PathVariable long idCategory) {
return productService.findProductsForCategory(idCategory);
}
@GetMapping("/findByName/{name}")
List<Product> findByName(@PathVariable String name) {
return productDao.findByName("%" + name + "%");
}
}
Here, we are creating an class TagController
src/main/java/com/ecommerce/controller/TagController.java):
package com.ecommerce.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ecommerce.dao.TagDao;
import com.ecommerce.modal.Product;
import com.ecommerce.modal.Tag;
import com.ecommerce.service.TagService;
@RestController
@RequestMapping(value = "/api")
@CrossOrigin(origins = "*")
public class TagController {
@Autowired
private TagService tagService;
@Autowired
private TagDao tagDao;
@PostMapping("/addTagToProduct/{idProduct}/{idTag}")
void addTagToProduct(@PathVariable long idProduct, @PathVariable long idTag) {
tagService.addTagToProduct(idProduct, idTag);
}
@GetMapping("/findTagsForProduct/{idProduct}")
List<Tag> findTagsForProduct(@PathVariable long idProduct) {
return tagService.findTagsForProduct(idProduct);
}
@GetMapping("/findAllTags")
List<Tag> findAllTags() {
return tagService.findAllTags();
}
@DeleteMapping("/deleteTagFromProduct")
void deleteTagFromProduct(@PathVariable long idTag, @PathVariable long idProduct) {
tagService.deleteTagFromProduct(idTag, idProduct);
}
@PostMapping("/addTag")
Tag addTag(@RequestBody Tag tag) {
return tagService.addTag(tag);
}
@DeleteMapping("/deleteTag/{id}")
void deleteTag(@PathVariable long id) {
tagService.deleteTag(id);
}
@GetMapping("/findTagById/{id}")
Tag findTagById(@PathVariable long id) {
return tagService.findTagById(id);
}
@GetMapping("/findAllTagByName/{name}")
List<Tag> findAllTagByName(@PathVariable String name) {
return tagDao.findByName("%" + name + "%");
}
@GetMapping("/findProductsForTag/{idTag}")
List<Product> findProductsForTag(@PathVariable long idTag) {
return tagService.findProductsForTag(idTag);
}
}
Here, we are creating an class UserController
src/main/java/com/ecommerce/controller/UserController.java):
package com.ecommerce.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ecommerce.modal.User;
import com.ecommerce.service.UserService;
@RestController
@RequestMapping(value = "/api")
@CrossOrigin(origins = "*")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/addUser")
User addUser(@RequestBody User user) {
return userService.addUser(user);
}
@GetMapping("/admin/findAllUsers")
List<User> findAllUsers() {
return userService.findAllUsers();
}
@PutMapping("/editUser/{id}")
User editUser(@RequestBody User user, @PathVariable long id) {
return userService.editUser(user, id);
}
@GetMapping("/findUserById/{id}")
User findUserById(@PathVariable long id) {
return userService.findUserById(id);
}
@DeleteMapping("/deleteUser/{id}")
void deleteUser(@PathVariable long id) {
userService.deleteUser(id);
}
@GetMapping("/findByUsername/{username}")
User findByUsername(@PathVariable String username) {
return userService.findByUsername(username);
}
}
EcommerceApplication
@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/EcommerceApplication.java):
package com.ecommerce;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class EcommerceApplication {
public static void main(String[] args) {
SpringApplication.run(EcommerceApplication.class, args);
System.out.println("App started....");
}
}
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.