CodeNewbie Community 🌱

Nil Madhab
Nil Madhab

Posted on

Let’s Develop an E-Commerce Application From Scratch Using Java

We are going to build an e-commerce application using Java, Spring backend, build web UI in Vue.js, and mobile UI using android. Stay tuned!

Every E-Commerce platform needs users, so in the first tutorial, we are going to create and display user-profiles. We are going to first build the backend APIs using Java and Springboot, then we are going to create UI in Vue.js and android mobile app.

Live Demo

You can test the API at the following swagger link. You can create and list all the users.

Link

About Spring Framework

The Spring Framework is a major open-source Java/J2EE application development framework for more productive application development. It is the most popular Java framework with a 30% share of usage. The Spring Framework features enable efficient development from simple Web to complex enterprise applications.

The main concepts that the Spring Framework depends on are:

  1. Dependency Injection (DI)
  2. Aspect-Oriented Programming (AOP)
  3. Java Persistence API (JPA) ## Prerequisites
  4. Knowledge in Core Java
  5. Coding skills
  6. Knowledge in Servlet and JSP
  7. Java Development Kit (JDK)
  8. IntelliJ IDEA Ultimate — open-source (recommended)
  9. MySQL database — You can get it here!
  10. A good browser (Chrome — recommended)

Make sure you have all the listed prerequisites software installed and have basic knowledge of the request-response cycle as well as web containers. What more? Let’s jump into the tutorial!

Project Setup

  • Open Spring Tool Suite application
  • Click File -> New -> Project ->Spring Starter Project
  • Give the essential data in the opened dialog box ## Dependencies The dependencies I am adding to this project are given below. You can either add them during the creation of the project itself or later search for them in the Maven repository and add the tags of the required version in the pom.xml file.
  • Spring boot starter web
  • Tomcat embed jasper
  • Spring boot starter Data JPA
  • Mysql connector java
  • Spring boot starter test
  • Swagger 2
  • Swagger UI ## Project Hierarchy The hierarchy is the important thing to notice in the Spring boot Application design structure. My project hierarchy is as below.

Overview of our Backend Application

In this Spring Application following are important packages that you have to know before starting.

This is the spring architecture. The outside world calls the REST Apis, which interacts with the Service. Service calls the repository. The repository interacts with the database. We follow this pattern to make the codebase maintainable, instead of having spaghetti code which can be a nightmare in long term.

Let's look at first Rest controllers

Controller

package com.webtutsplus.ecommerce.controller;

import java.util.List;

import javax.validation.Valid;

import com.webtutsplus.ecommerce.model.UserProfile;
import com.webtutsplus.ecommerce.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
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.webtutsplus.ecommerce.common.ApiResponse;

@RestController
@RequestMapping("/user")
public class    UserController {

    @Autowired private UserService userService;

    @GetMapping("/")
    public ResponseEntity<List<UserProfile>> getUsers() {
        List<UserProfile> dtos = userService.listProfiles();
        return new ResponseEntity<List<UserProfile>>(dtos, HttpStatus.OK);
    }

    @PostMapping("/add")
    public ResponseEntity<ApiResponse> addSurvey(@RequestBody @Valid UserProfile profile) {
        userService.addProfile(profile);
        return new ResponseEntity<>(new ApiResponse(true, "Profile has been created."), HttpStatus.CREATED);
    }   
}
Enter fullscreen mode Exit fullscreen mode

The User Controller class provides two HTTP methods GET and Post. The Get mapping function return a complete list of Users and the Post Mapping Function saves the new user profile in the Database.

As we can see UserControllers has a reference to UserService.

Service

As we know the spring boot framework follows the POJO model and every controller has its own service interface, which provides the methods / Operation that is performed in the application.

In service class, there are only two methods list Profiles and add Profiles, which provide information. We can extend or add more functionality in the future according to requirements.

package com.webtutsplus.ecommerce.service;

import java.util.List;

import com.webtutsplus.ecommerce.model.UserProfile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.webtutsplus.ecommerce.repository.UserProfileRepository;

@Service
public class UserService {

    @Autowired private UserProfileRepository userRepo;


    public void addProfile(UserProfile userProfile) {
        userRepo.save(userProfile);
    }

    public List<UserProfile> listProfiles(){
        return userRepo.findAll();      
    }

}
Enter fullscreen mode Exit fullscreen mode

Service calls UserProfileRepository which interacts with the database in form of models. Let's have a look at UserModel.

Model

The model class is a mirror of the user_profile table in the database in form of a java object. All attributes can be accessed through this class. You can also update the attribute values using the model class, which also makes changes in a database table.

package com.webtutsplus.ecommerce.model;


import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;


@Entity
@Table(name="user_profile")
public class UserProfile {

    private long id;
    private String username;
    private String email;
    private String firstName;
    private String lastName;

    public UserProfile() {}

    public UserProfile(long id, String username, String email, String firstName, String lastName) {
        super();
        this.id = id;
        this.username = username;
        this.email = email;
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    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 getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

}
Enter fullscreen mode Exit fullscreen mode

Result

After this save the file and run the application. Now you tomcat is listening on 8182 port.

[Link] 138.68.64.95:8080/api/swagger-ui.html#/user-controller

What is Swagger

Swagger is an Interface Description Language for describing RESTful APIs expressed using JSON. Swagger is used together with a set of open-source software tools to design, build, document, and use RESTful web services. Swagger includes automated documentation, code generation, and test-case generation.

You can access the application documentation by entering the following URL in your browser.

You can edit your API information in documentation.swaggerConfig.java class and getApiInfo() method.

Swagger is very useful on the developer side because it provides very user-friendly API information as well as provide a way to test the API.

    private ApiInfo getApiInfo() {
        Contact contact = new Contact("webtutsplus", "http://webtutsplus.com", "contact.webtutsplus@gmail.com");
        return new ApiInfoBuilder()
                .title("User Profile API")
                .description("Documentation User profile api")
                .version("1.0.0")
                .license("Apache 2.0")
                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0")
                .contact(contact)
                .build();
}
Enter fullscreen mode Exit fullscreen mode

Now we are going to look at some extra classes, which play an important role too.

common

In this package, there are two classes

· ApiResponse.java

package com.webtutsplus.ecommerce.common;

import java.time.LocalDateTime;

public class ApiResponse {
    private final boolean success;
    private final String message;

    public ApiResponse(boolean success, String message) {
        this.success = success;
        this.message = message;
    }

    public boolean isSuccess() {
        return success;
    }

    public String getMessage() {
        return message;
    }

    public String getTimestamp() {
        return LocalDateTime.now().toString();
    }
}
Enter fullscreen mode Exit fullscreen mode

This class provides the status of API response. It has three methods is Success (), get Message (), get Timestamp (). The get Timestamp () method returns the Current Date and Time in String format.
PagedList.java

package com.webtutsplus.ecommerce.common;

import java.util.List;

public class PagedList<T> {
    private int totalPages;
    private long totalElements;
    private boolean hasNext;
    private boolean hasPrevious;

    private List<T> data;

    public int getTotalPages() {
        return totalPages;
    }
    public void setTotalPages(int totalPages) {
        this.totalPages = totalPages;
    }
    public long getTotalElements() {
        return totalElements;
    }
    public void setTotalElements(long totalElements) {
        this.totalElements = totalElements;
    }
    public boolean isHasNext() {
        return hasNext;
    }
    public void setHasNext(boolean hasNext) {
        this.hasNext = hasNext;
    }
    public boolean isHasPrevious() {
        return hasPrevious;
    }
    public void setHasPrevious(boolean hasPrevious) {
        this.hasPrevious = hasPrevious;
    }

    public List<T> getData() {
        return data;
    }
    public void setData(List<T> data) {
        this.data = data;
    }
}
Enter fullscreen mode Exit fullscreen mode

This class contains all the information about the pages in the List data structure and provides total Pages, total Elements, has Next, has Previous attributes getter and setter.

Config

In these packages, there are two sub-packages named documentation and security.

· Documentation

In this Package, it provides information about the product and API.

Product API method provides information about the product and gets the Api Info method return information about Api like contact, Title, version, license.

package com.webtutsplus.ecommerce.config.documentation;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket productApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(getApiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.webtutsplus.ecommerce"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo getApiInfo() {
        Contact contact = new Contact("Umar Draz", "-", "umar.umar82@gmail.com");
        return new ApiInfoBuilder()
                .title("User Profile API")
                .description("Documentation User profile api")
                .version("1.0.0")
                .license("Apache 2.0")
                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0")
                .contact(contact)
                .build();
    }
}
Enter fullscreen mode Exit fullscreen mode

Security

This class is very important for applications because it provides the basic security for the whole application over HTTP or HTTPS protocol. It also implements configuration for users that which users have access to which pages or repositories.

package com.webtutsplus.ecommerce.config.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
    @Override
    protected void configure(HttpSecurity http) throws Exception 
    {
        http
         .csrf().disable()
         .authorizeRequests().anyRequest().authenticated()
         .and()
         .httpBasic();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) 
            throws Exception 
    {
        auth.inMemoryAuthentication()
            .withUser("admin")
            .password("admin")
            .roles("USER");
    }

    @Override
    public void configure(WebSecurity registry) throws Exception {
        registry.ignoring()
        .antMatchers("/docs/**").antMatchers("/actuator/**").antMatchers("/v2/api-docs", "/configuration/ui",
                "/swagger-resources/**", "/configuration/security", "/swagger-ui.html", "/webjars/**");
    }
}
Enter fullscreen mode Exit fullscreen mode

Exception

This class is used in case of exception in any stage of the application. It has two classes Exception handler and validation exception, which throws when there is a validation error in the application at run time.

ExceptionHandlerAdvice.java

package com.webtutsplus.ecommerce.exception;

import com.webtutsplus.ecommerce.common.ApiResponse;
import org.springframework.core.NestedExceptionUtils;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;


@ControllerAdvice
public class ExceptionHandlerAdvice {

    @ExceptionHandler(DataIntegrityViolationException.class)
    public ResponseEntity<ApiResponse> conflict(DataIntegrityViolationException ex){
        String message = getMostSpecificMessage(ex);

        return new ResponseEntity<ApiResponse>(new ApiResponse(false, message), HttpStatus.CONFLICT);
    }

//  @ExceptionHandler(AccessDeniedException.class)
//  public ResponseEntity<ApiResponse> accessDenied(AccessDeniedException ex){
//      String message = ex.getMessage();
//      
//      return new ResponseEntity<ApiResponse>(new ApiResponse(false, message), HttpStatus.FORBIDDEN);
//  }

    @ExceptionHandler(ValidationException.class)
    public ResponseEntity<ApiResponse> validationException(ValidationException ex){
        String message = ex.getMessage();

        return new ResponseEntity<ApiResponse>(new ApiResponse(false, message), HttpStatus.UNPROCESSABLE_ENTITY);
    }

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public ResponseEntity<ApiResponse> methodArgumentTypeMismatchException(MethodArgumentTypeMismatchException ex){
        ex.printStackTrace();

        String message = ex.getMessage();
        return new ResponseEntity<ApiResponse>(new ApiResponse(false, message), HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<ApiResponse> unhandledExceptions(Exception ex){
        String message = NestedExceptionUtils.getMostSpecificCause(ex).getMessage();

        ex.printStackTrace();

        return new ResponseEntity<ApiResponse>(new ApiResponse(false, message), HttpStatus.INTERNAL_SERVER_ERROR);
    }

    private String getMostSpecificMessage(DataIntegrityViolationException ex) {
        String message = NestedExceptionUtils.getMostSpecificCause(ex).getMessage();

        if(message.contains("Detail:")) {
            message = message.substring(message.indexOf("Detail:")+"Detail:".length());
        }

        return message;
    }
}
Enter fullscreen mode Exit fullscreen mode

ValidationException.java

package com.webtutsplus.ecommerce.exception;

public class ValidationException extends RuntimeException{
    private static final long serialVersionUID = 6064663768170825752L;

    public ValidationException(String message) {
        super(message);
    }

    public ValidationException(String message, Throwable cause) {
        super(message, cause);
    }
}
Enter fullscreen mode Exit fullscreen mode

Hope you had a great session with us! Follow us for such great and awesome tutorials!

Follow the next tutorial where we will build UI in both Vue.js and Android.

Oldest comments (1)

Collapse
 
ladyefuru profile image
Efuru Anthony

Thanks !