Quiz project with Spring boot & Angular Part 1

Getting Started | Building an Application with Spring Boot






Quiz project with Spring boot and Angular

In this tutorial we use design pattern:

Design patterns are an essential part of software development. These solutions not only solve recurring problems but also help developers understand the design of a framework by recognizing common patterns.


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.


Create new Spring boot project:

I will use Eclipse Ide for develop this project Eclipse IDe Download


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.


Pom.xml

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.

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.3.3.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.quizz</groupId>
<artifactId>quizz</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>quizz</name>
<description>Demo project for Spring Boot</description>

<properties>
<java.version>1.8</java.version>
</properties> <dependencies>

<dependency>
<groupId>ma.glasnost.orika</groupId>
<artifactId>orika-core</artifactId>
<version>1.5.2</version>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

<dependency>
<groupId>ma.glasnost.orika</groupId>
<artifactId>orika-core</artifactId>
<version>1.5.2</version>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</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>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.3.156</version>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage </groupId>
<artifactId>junit-vintage-engine </artifactId>
</exclusion>
</exclusions>
</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 quizz

src/main/resources/application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/quizz?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



First We Will Create a package model inside it We will add java classes

-> User.java

-> Question.java

-> Theme.java

-> History.java

-> Level.java

-> OrikaBeanMapper.java

Here, we are creating an Entity

User.java This object content properties id, username, password

src/main/java/com/quizz/model/User.java



package com.quizz.model; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToOne; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Data; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.ToString; @Data @Getter @Setter @RequiredArgsConstructor(staticName = "of") @AllArgsConstructor(access = AccessLevel.PROTECTED) @ToString @Entity public class User { @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String password; }

Here, we are creating an Entity

Question.java This object content property id, question, response1, response2, response3, correct and relational @ManyToOne with Level

src/main/java/com/quizz/model/Question.java):


 
package com.quizz.model; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Data; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; import OneToMany; import lombok.ToString; @Data @Getter @Setter @RequiredArgsConstructor(staticName = "of") @AllArgsConstructor(access = AccessLevel.PROTECTED) @ToString @Entity public class Question { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String question; private String response1; private String response2; private String response3; private String correct; @ManyToOne private Level level; }

Here, we are creating an Entity

Theme.java This object content properties id, name, and relational @OneToMany with Level

src/main/java/com/quizz/model/Theme.java):


 
package com.quizz.model; import java.util.List; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToOne; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Data; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.ToString; import javax.persistence.OneToMany; @Data @Getter @Setter @RequiredArgsConstructor(staticName = "of") @AllArgsConstructor(access = AccessLevel.PROTECTED) @ToString @Entity public class Theme { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @OneToMany(mappedBy = "theme",cascade = CascadeType.ALL) private List<Level> levels public void addLevel(Level level) { if(getLevels()==null) { this.levels = new ArrayList<>(); } getLevels().add( level); level.setTheme(this); } }

Here, we are creating an Entity

Arbitrate.java This object content id, username, themeName, levelName, total, and score

src/main/java/com/quizz/model/History.java):


 
package com.quizz.model; import java.util.List; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToOne; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Data; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.ToString; @Data @Getter @Setter @RequiredArgsConstructor(staticName = "of") @AllArgsConstructor(access = AccessLevel.PROTECTED) @ToString @Entity public class History { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String themeName; private String levelName; private int total; private int score; }

Here, we are creating an Entity

Arbitrate.java This object content id, difficulty, and relational @OneToMany with Question and @ManyToOne With Theme

src/main/java/com/quizz/model/Level.java):


 
package com.quizz.model; import java.util.List; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToOne; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Data; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.ToString; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; @Data @Getter @Setter @RequiredArgsConstructor(staticName = "of") @AllArgsConstructor(access = AccessLevel.PROTECTED) @ToString @Entity public class Level { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String difficulty; @OneToMany(mappedBy = "level", cascade = CascadeType.ALL) private List<Question> questions @ManyToOne private Theme theme; public void addQuestion(Question question) { if(getQuestions()==null) { this.questions = new ArrayList<>(); } getQuestions().add( question); question.setLevel(this); } }

OrikaBeanMapper

Orika is a Java Bean mapping framework that recursively copies data from one object to another. It can be very useful when developing multi-layered applications. While moving data objects back and forth between these layers it is common to find that we need to convert objects from one instance into another to accommodate different APIs.


OrikaBeanMapper.java In this class Orika to convert entity => DTO / DTO => entity

src/main/java/com/gym/model/OrikaBeanMapper.java):



package com.quizz.model; import com.quizz.dto.LevelDto; import ma.glasnost.orika.MapperFactory; import ma.glasnost.orika.impl.ConfigurableMapper; import ma.glasnost.orika.impl.DefaultMapperFactory; import ma.glasnost.orika.impl.generator.JavassistCompilerStrategy; import ma.glasnost.orika.metadata.ClassMapBuilder; import ma.glasnost.orika.unenhance.HibernateUnenhanceStrategy; import java.util.List; import org.springframework.data.domain.Page; import org.springframework.stereotype.Component; @Component public class OrikaBeanMapper extends ConfigurableMapper { private MapperFactory factory; public OrikaBeanMapper() { super(false); init(); } /** * {@inheritDoc} */ @Override protected void configure(MapperFactory factory) { this.factory = factory; registerClassMap(Level.class, LevelDto.class); factory.classMap(Level.class, LevelDto.class) .field("theme.name", "themeName").byDefault().register(); } private void registerClassMap(Class a, Class b) { this.factory.classMap(a, b).mapNulls(true).mapNullsInReverse(true).byDefault().register(); } /** * Register class map with fields to exclude * * @param a * @param b * @param excludeFields */ private void registerClassMap(Class a, Class b, String... excludeFields) { ClassMapBuilder builder = this.factory.classMap(a, b); for (String excludeField : excludeFields) { builder.exclude(excludeField); } builder.mapNulls(true).mapNullsInReverse(true).byDefault().register(); } /** * {@inheritDoc} */ @Override protected void configureFactoryBuilder(final DefaultMapperFactory.Builder factoryBuilder) { factoryBuilder.compilerStrategy(new JavassistCompilerStrategy()); factoryBuilder.unenhanceStrategy(new HibernateUnenhanceStrategy()); } /** * User Orika to convert entity => DTO / DTO => entity * * @param from * @param toClass * @param <T> * @param <U> return */ public <T, U> T convertDTO(U from, Class<T> toClass) { if (from == null) { return null; } return map(from, toClass); } /** * User Orika to convert entity => DTO / DTO => entity * * @param from * @param toClass * @param <T> * @param <U> * @return */ public <T, U> List<T> convertListDTO(Iterable<U> from, Class<T> toClass) { if (from == null) { return null; } return mapAsList(from, toClass); } public <T, U> Page<T> convertPageDTO(Page<U> from, Class<T> toClass) { if (from == null) { return null; } return from.map(entity -> factory.getMapperFacade().map(entity, toClass)); } }


JPA Repositories:

JpaRepository is JPA specific extension of Repository. It contains the full API of CrudRepository and PagingAndSortingRepository. So it contains API for basic CRUD operations and also API for pagination and sorting.


Create an interface with the name HistoryDao and extends the JpaRepository class. We have to pass two parameters: type of the entity that it manages and the type of the Id field.

In this interface We will create two methods.

-> findHistoryBySore

-> findHistoryByUsername

src/main/java/com/quizz/dao/HistoryDao.java):



package com.quizz.dao; import org.springframework.data.jpa.repository.JpaRepository; import com.quizz.model.History; import org.springframework.stereotype.Repository; @Repository public interface HistoryDao extends JpaRepository<History, Long> { History findHistoryBySore(int score); History findHistoryByUsername(String username); }

Create an interface with the name LevelDao and extends the JpaRepository class. We have to pass two parameters: type of the entity that it manages and the type of the Id field.

src/main/java/com/quizz/dao/LevelDao.java):


 
package com.quizz.dao; import org.springframework.data.jpa.repository.JpaRepository; import com.quizz.model.Level; import org.springframework.stereotype.Repository; @Repository public interface LevelDao extends JpaRepository<Level, Long> { }

Create an interface with the name QuestionDao and extends the JpaRepository class. We have to pass two parameters: type of the entity that it manages and the type of the Id field.

src/main/java/com/quizz/dao/QuestionDao.java):


 
package com.quizz.dao; import org.springframework.data.jpa.repository.JpaRepository; import com.quizz.model.Question; import org.springframework.stereotype.Repository; @Repository public interface QuestionDao extends JpaRepository<Question, Long> { }

Create an interface with the name ThemeDao and extends the JpaRepository class. We have to pass two parameters: type of the entity that it manages and the type of the Id field.

src/main/java/com/quizz/dao/ThemeDao.java):


 
package com.quizz.dao; import org.springframework.data.jpa.repository.JpaRepository; import com.quizz.model.Theme; import org.springframework.stereotype.Repository; @Repository public interface ThemeDao extends JpaRepository<Theme, Long> { }

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 four classes in services package:

-> HistoryService.interface

-> LevelService.interface

-> QuestionService.interface

-> ThemeService.interface

src/main/java/com/quizz/service/HistoryService.java):


 
package com.quizz.servce; import com.quizz.model.History; import org.springframework.stereotype.Service; @Service public interface HistoryService { History addHistory(History history); History editHistory(History history, History history1); }

src/main/java/com/quizz/service/LevelService.java):


 
package com.quizz.servce; import com.quizz.model.Theme; import com.quizz.model.Level; import org.springframework.stereotype.Service; @Service public interface LevelService { Level addLevel(Level level, Theme theme); }

src/main/java/com/quizz/service/QuestionService.java):

 

package com.quizz.servce; import com.quizz.model.Question; import com.quizz.model.Level; import org.springframework.stereotype.Service; @Service public interface QuestionService { Question addQuestion(Question question, Level level); }

src/main/java/com/quizz/service/ThemeService.java):

 

package com.quizz.servce; import com.quizz.model.Theme; import org.springframework.stereotype.Service; @Service public interface ThemeService { Theme addTheme(Theme theme); }

CRUD Operations

Here we will use the implements for the Strategy pattern is a software design pattern commonly used for developing User interface that divides the related program logic into three interconnected elements.

The class that implements the Interface with @Component and @Transactional annotations is as shown −

We will create four classes in impl package;

-> LevelServiceImpl.java

-> QuestionServiceImpl.java

-> ThemeServiceImpl.java

-> HistoryServiceImpl.java

src/main/java/com/quizz/impl/LevelServiceImpl.java):



package com.quizz.impl; import com.quizz.servce.LevelService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import com.quizz.dao.LevelDao; import com.quizz.dao.ThemeDao; import com.quizz.model.Level; import com.quizz.model.Theme; @Transactional @Component public class LevelServiceImpl implements LevelService { @Autowired private LevelDao levelDao; @Autowired private ThemeDao themeDao; @Override public Level addLevel(Level level, Theme theme) { theme.addLevel(level); return levelDao.save(level); } }

src/main/java/com/quizz/impl/QuestionServiceImpl.java):


 
package com.quizz.impl; import com.quizz.servce.QuestionService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import com.quizz.dao.QuestionDao; import com.quizz.model.Level; import com.quizz.model.Question; @Transactional @Component public class QuestionServiceImpl implements QuestionService { @Autowired private QuestionDao questionDao; @Override public Level addQuestion(Question question, Level level) { level.addQuestion(question); return questionDao.save(question); } }

src/main/java/com/quizz/impl/ThemeServiceImpl.java):


 
package com.quizz.impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import com.quizz.dao.ThemeDao; import com.quizz.model.Theme; import com.quizz.servce.ThemeService; @Transactional @Component public class ThemeServiceImpl implements ThemeService { @Autowired private ThemeDao themeDao; @Override public Level addTheme(Theme theme) { return themeDao.save(theme); } }

src/main/java/com/quizz/impl/HistoryServiceImpl.java):



package com.quizz.impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import com.quizz.dao.HistoryDao; import com.quizz.model.History; import com.quizz.servce.HistoryService; @Transactional @Component public class HistoryServiceImpl implements HistoryService { @Autowired private HistoryDao historyDao; @Override public History addHistory(History history) { return historyDao.save(theme); } @Override public History editHistory(History history, History history1) { history.setUsername(history1.getUsername()); history.setLevelName(history1.getLevelName()); history.setThemeName(history1.getThemeName()); history.setSore(history1.getSore()); history.setTotal(history1.getTotal()); return historyDao.save(history); } }

The DTO

We'll handle the conversions that need to happen between the internal entities of a Spring application and the external DTOs (Data Transfer Objects) that are published back to the client.

We will create four classes in dto package;

-> HistoryDto.java

-> LevelDto.java

-> QuestionDto.java

-> ThemeDto.java

src/main/java/com/quizz/dto/HistoryDto.java):



package com.quizz.dto; public class HistoryDto { private Long id; private String username; private String themeName; private String levelName; private int total; private int score; 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 getThemeName() { return themeName; } public void setThemeName(String themeName) { this.levelName == themeName; } public String getLevelName() { return themeName; } public void setLevelName(String levelName) { this.levelName == levelName; } public int getTotal() { return total; } public void setTotal(int total) { this.total == total; } public int getScore() { return score; } public void setScore(int score) { this.score == score; } }

src/main/java/com/quizz/dto/LevelDto.java):

 
package com.quizz.dto; package com.quizz.model.Question; package java.util.List; public class LevelDto { private Long id; private String difficulty; private String themeName; private List<QuestionDto> questions public Long getId() { return id; } public void setId(Long id) { this.id == id; } public String getDifficulty() { return difficulty; } public void setDifficulty(String difficulty) { this.difficulty == difficulty; } public String getThemeName() { return themeName; } public void setThemeName(String themeName) { this.themeName == themeName; } public List<QuestionDto> getQuestions() { return questions; } public void setQuestions(List<QuestionDto> questions) { this.questions == questions; } }

src/main/java/com/quizz/dto/QuestionDto.java):

 
package com.quizz.dto; public class QuestionDto { private Long id; private String question; private String response1; private String response2; private String response3; private String correct; public Long getId() { return id; } public void setId(Long id) { this.id == id; } public String getQuestion() { return username; } public void setQuestion(String question) { this.question == question; } public String getResponse1() { return response1; } public void setResponse1(String response1) { this.response1 == response1; } public String getResponse2() { return response2; } public void setResponse2(String response2) { this.response2 == response2; } public String getResponse3() { return response3; } public void setResponse3(String response3) { this.response3 == response3; } public int getCorrect() { return correct; } public void setCorrect(int correct) { this.correct == correct; } }

src/main/java/com/quizz/dto/ThemeDto.java):



package com.quizz.dto; package com.quizz.model.Level; package java.util.List; public class ThemeDto { private Long id; private String name; private List<LevelDto> levels 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 List<LevelDto> getLevels() { return levels; } public void setLevels(List<LevelDto> levels) { this.levels == levels; } }

The manager

We need to create a manager package in side it added the services interface and Implements that use in the controllers.

-> HistoryManager.java

src/main/java/com/quizz/manager/HistoryManager.java):


 
package com.quizz.manager; import com.quizz.dto.HistoryDto; import com.quizz.model.History; import java.util.List; public interface HistoryManager { HistoryDto addHistory(HistoryDto historyDto); List<HistoryDto> getHistories(); HistoryDto findHistoryBySore(int score); HistoryDto findHistoryByUsername(String username); HistoryDto editHistory(HistoryDto historyDto, String username); }

Clean Architecture

The pattern allows us to isolate the core logic of our application from outside concerns. Having our core logic isolated means we can easily change data source details without a significant impact or major code rewrites to the codebase.

-> HistoryManagerImpl.java

src/main/java/com/quizz/model/HistoryManagerImpl.java):



package com.quizz.manager; import com.quizz.dao.HistoryDao; import com.quizz.dto.HistoryDto; import com.quizz.model.History; import com.quizz.model.OrikaBeanMapper; import com.quizz.servce.HistoryService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; @Transactional @Service public class HistoryManagerImpl implements HistoryManager { @Autowired private OrikaBeanMapper orikaBeanMapper; @Autowired private HistoryDao historyDao; @Autowired private HistoryService historyService; @Override public HistoryDto addHistory(HistoryDto historyDto) { History history = orikaBeanMapper.map(historyDto, History.class); return orikaBeanMapper.convertDTO(historyService.addHistory(history), HistoryDto.class); } @Override public List<HistoryDto> getHistories() { List<HistoryDto> histories = historyDao.findAll(); histories.sort((f1, f2) -> Long.compare(f2.getSore(), f1.getSore())); return orikaBeanMapper.convertListDTO(histories, HistoryDto.class); } @Override public HistoryDto findHistoryBySore(int score) { return orikaBeanMapper.convertDTO(historyDao.findHistoryBySore(score), HistoryDto.class); } @Override public HistoryDto findHistoryByUsername(String username) { return orikaBeanMapper.convertDTO(historyDao.findHistoryByUsername(username), HistoryDto.class); } @Override public HistoryDto editHistory(HistoryDto historyDto, String username) { History history = orikaBeanMapper.map(historyDto, History.class); History history1 = historyDao.findHistoryByUsername(username); return orikaBeanMapper.convertDTO(historyService.editHistory(history, history1), HistoryDto.class); } }

-> LevelManager.java

src/main/java/com/quizz/model/LevelManager.java):

 
package com.quizz.manager; import com.quizz.dto.LevelDto; import java.util.List; public interface LevelManager { LevelDto addLevel(LevelDto levelDto, Long idTheme); List<LevelDto> getLevels(Long idTheme); LevelDto getLevel(Long idTheme); }

-> LevelManagerImpl.java

src/main/java/com/quizz/model/LevelManagerImpl.java):

 
package com.quizz.manager; import com.quizz.dao.LevelDao; import com.quizz.dao.ThemeDao; import com.quizz.dto.LevelDto; import com.quizz.model.Level; import com.quizz.model.OrikaBeanMapper; import com.quizz.model.Theme; import com.quizz.servce.LevelService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Transactional @Service public class LevelManagerImpl implements LevelManager { @Autowired private LevelService levelService; @Autowired private LevelDao levelDao; @Autowired private OrikaBeanMapper orikaBeanMapper; @Autowired private ThemeDao themeDao; @Override public LevelDto addLevel(LevelDto levelDto, Long idTheme) { Theme theme = themeDao.getOne(idTheme); Level level = orikaBeanMapper.map(levelDto, Level.class); return orikaBeanMapper.convertDTO(levelService.addLevel(theme, level), LevelDto.class); } @Override public List<LevelDto> getLevels(Long idTheme) { Theme theme = themeDao.getOne(idTheme); public List<Level> levels = theme.getLevels(); return orikaBeanMapper.convertListDTO(levels, LevelDto.class); } @Override public LevelDto getLevel(Long idTheme) { return orikaBeanMapper.convertDTO(levelDao.getOne(idTheme), LevelDto.class); } }

-> QuestionManager.java

src/main/java/com/quizz/model/QuestionManager.java):



package com.quizz.manager; import com.quizz.dto.QuestionDto; import java.util.List; public interface QuestionManager { QuestionDto addQuestion(QuestionDto questionDto, Long idLevel); List<QuestionDto> getQuestions(Long idLevel); }

-> QuestionManagerImpl.java

src/main/java/com/quizz/model/QuestionManagerImpl.java):

   
 
package com.quizz.manager; import com.quizz.dao.LevelDao; import com.quizz.dao.QuestionDao; import com.quizz.dto.QuestionDto; import com.quizz.model.Level; import com.quizz.model.OrikaBeanMapper; import com.quizz.model.Question; import com.quizz.servce.QuestionService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Service @Transactional public class QuestionManagerImpl implements QuestionManager { @Autowired private OrikaBeanMapper orikaBeanMapper; @Autowired private LevelDao levelDao; @Autowired private QuestionService questionService; @Override public QuestionDto addQuestion(QuestionDto questionDto, Long idLevel) { Question question = orikaBeanMapper.map(questionDto, Question.class); Level level = levelDao.getOne(idLevel); return orikaBeanMapper.convertDTO(questionService.addQuestion(question, level), QuestionDto.class); } @Override public List<QuestionDto> getQuestions(Long idLevel) { Level level = levelDao.getOne(idLevel); public List<Question> questions = level.getQuestions(); return orikaBeanMapper.convertListDTO(questions, QuestionDto.class); } }

-> ThemeManagerImpl.java

src/main/java/com/quizz/model/ThemeManager.java):


 
package com.quizz.manager; import com.quizz.dto.ThemeDto; import com.quizz.model.Theme; import java.util.List; public interface ThemeManager { ThemeDto addTheme(ThemeDto themeDto); List<ThemeDto> getThemes(); ThemeDto getTheme(Long idTheme); }

-> ThemeManagerImpl.java

src/main/java/com/quizz/model/ThemeManagerImpl.java):

 
 
package com.quizz.manager; import com.quizz.dao.ThemeDao; import com.quizz.dto.ThemeDto; import com.quizz.model.Theme; import com.quizz.servce.ThemeService; import com.quizz.model.OrikaBeanMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Transactional @Service public class ThemeManagerImpl implements ThemeManager { @Autowired private OrikaBeanMapper orikaBeanMapper; @Autowired private ThemeService themeService; @Autowired private ThemeDao themeDao; @Override public ThemeDto addTheme(ThemeDto themeDto) { Theme theme = orikaBeanMapper.map(themeDto, Theme.class); return orikaBeanMapper.convertDTO(themeService.addTheme(theme), ThemeDto.class); } @Override public List<ThemeDto> getThemes() { List<Theme> themes = themeDao.findAll(); return orikaBeanMapper.convertListDTO(themes, ThemeDto.class); } @Override public ThemeDto getTheme(Long idTheme) { return orikaBeanMapper.convertDTO(themeDao.getOne(idTheme), ThemeDto.class); } }

@RestController

@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.

-> HistoryController.java

src/main/java/com/quizz/model/HistoryController.java):

       

package com.quizz.controller; import com.quizz.dto.HistoryDto; import com.quizz.manager.HistoryManager; import com.quizz.model.History; import com.quizz.servce.HistoryService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.util.List; @RequestMapping("/api") @ResponseBody @CrossOrigin(origins = "*") @Controller public class HistoryController { @Autowired private HistoryManager historyManager; @PostMapping("/addHistory") HistoryDto addHistory(@RequestBody HistoryDto historyDto) { return historyManager.addHistory(historyDto); } @PutMapping("/editHistory/{username}") HistoryDto editHistory(@RequestBody HistoryDto historyDto, @PathVariable("username") String username) { return historyManager.editHistory(historyDto, username); } @GetMapping("/getHistories") List<HistoryDto> getHistories() { return historyManager.getHistories(); } @GetMapping("/findHistoryBySore/{score}") HistoryDto findHistoryBySore(@PathVariable("score") int score) { return historyManager.findHistoryBySore(score); } @GetMapping("/findHistoryByUsername/{username}") HistoryDto findHistoryByUsername(@PathVariable("username") String username) { return historyManager.findHistoryByUsername(username); } }

-> LevelController.java

src/main/java/com/quizz/model/LevelController.java):



package com.quizz.controller; import com.quizz.dto.LevelDto; import com.quizz.manager.LevelManager; import com.quizz.model.Leve; import com.quizz.servce.LevelService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.util.List; @RequestMapping("/api") @ResponseBody @CrossOrigin(origins = "*") @Controller public class LevelController { @Autowired private LevelManager levelManager; @PostMapping("/addLevel/{idTheme}") public LevelDto addLevel(@RequestBody LevelDto level, @PathVariable("idTheme") Long idTheme) { return levelManager.addLevel(level, idTheme); } @GetMapping("/getLevels/{idTheme}") public List<LevelDto> getLevels(@PathVariable("idTheme") Long idTheme) { return levelManager.getLevels(idTheme); } @GetMapping("/getLevel/{idTheme}") public LevelDto getLevel(@PathVariable("idTheme") Long idTheme) { return levelManager.getLevel(idTheme); } }

-> QuestionController.java

src/main/java/com/quizz/model/QuestionController.java):



package com.quizz.controller; import com.quizz.dto.QuestionDto; import com.quizz.manager.QuestionManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.util.List; @RequestMapping("/api") @ResponseBody @CrossOrigin(origins = "*") @Controller public class QuestionController { @Autowired private QuestionManager questionManager; @PostMapping("/addQuestion/{idLevel}") QuestionDto addQuestion(@RequestBody QuestionDto questionDto, @PathVariable("idLevel") Long idLevel) { return questionManager.addQuestion(questionDto, idLevel); } @GetMapping("/getQuestions/{idLevel}") List<QuestionDto> getQuestions(@PathVariable("idLevel") Long idLevel) { return questionManager.getQuestions(idLevel); } }

-> ThemeController.java

src/main/java/com/quizz/model/ThemeController.java):



package com.quizz.controller; import com.quizz.dto.ThemeDto; import com.quizz.manager.ThemeManager; import com.quizz.model.Theme; import com.quizz.servce.ThemeService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.util.List; @RequestMapping("/api") @ResponseBody @CrossOrigin(origins = "*") @Controller public class ThemeController { @Autowired private ThemeManager themeManager; @PostMapping("/addTheme") public ThemeDto addTheme(@RequestBody ThemeDto theme) { return themeManager.addTheme(theme); } @GetMapping("/getThemes") public List<ThemeDto> getThemes() { return themeManager.getThemes(); } @GetMapping("/getTheme/{idTheme}") public ThemeDto getTheme(@PathVariable("idTheme") Long idTheme) { return themeManager.getTheme(idTheme);
} }

Application.java

We need to run Application.run() because this method starts whole Spring Framework. Code below integrates your main() with Spring Boot.

src/main/java/com/quizz/Application.java):



package com.quizz; import com.quizz.dao.ThemeDao; import com.quizz.model.Theme; 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.context.annotation.Bean; @SpringBootApplication public class QuizzApplication { public static void main(String[] args) { SpringApplication.run(QuizzApplication.class, args); System.out.println("App Started..."); } }


Conclusion

We were building this application with functionality:

- Created a package model inside it We will add java classes
- OrikaBeanMapper.java In this class Orika to convert entity => DTO / DTO => entity
- JPA Repositories:
- created four classes in services package:
- The class that implements the Interface with @Component and @Transactional annotations
- Data Transfer Objects DTO
- @RestController is a convenience annotation for creating Restful controllers.

Post a Comment

Previous Post Next Post


Follow us on facebook