JAVA-11535 Move spring-data related modules to persistence-modules (#12126)

This commit is contained in:
anuragkumawat
2022-04-26 19:28:06 +05:30
committed by GitHub
parent daf47d8a06
commit 9cd8524f24
74 changed files with 6 additions and 9 deletions

View File

@@ -0,0 +1,24 @@
## Spring Data REST
This module contains articles about Spring Data REST
### Relevant Articles:
- [Introduction to Spring Data REST](https://www.baeldung.com/spring-data-rest-intro)
- [Working with Relationships in Spring Data REST](https://www.baeldung.com/spring-data-rest-relationships)
- [AngularJS CRUD Application with Spring Data REST](https://www.baeldung.com/angularjs-crud-with-spring-data-rest)
- [Projections and Excerpts in Spring Data REST](https://www.baeldung.com/spring-data-rest-projections-excerpts)
- [Spring Data REST Events with @RepositoryEventHandler](https://www.baeldung.com/spring-data-rest-events)
- [Customizing HTTP Endpoints in Spring Data REST](https://www.baeldung.com/spring-data-rest-customize-http-endpoints)
- [Spring Boot with SQLite](https://www.baeldung.com/spring-boot-sqlite)
### The Course
The "REST With Spring" Classes: http://bit.ly/restwithspring
# Running the project
The application uses [Spring Boot](http://projects.spring.io/spring-boot/), so it is easy to run. You can start it any of a few ways:
* Run the `main` method from `SpringDataRestApplication`
* Use the Maven Spring Boot plugin: `mvn spring-boot:run`
* Package the application as a JAR and run it using `java -jar intro-spring-data-rest.jar`
# Viewing the running application
To view the running application, visit [http://localhost:8080](http://localhost:8080) in your browser

View File

@@ -0,0 +1,96 @@
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-data-rest</artifactId>
<version>1.0</version>
<name>spring-data-rest</name>
<packaging>jar</packaging>
<description>Intro to Spring Data REST</description>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-2</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>maven-apt-plugin</artifactId>
<version>${maven.version}</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<properties>
<start-class>com.baeldung.books.SpringDataRestApplication</start-class>
<maven.version>1.0</maven.version>
</properties>
</project>

View File

@@ -0,0 +1,13 @@
package com.baeldung.books;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringDataRestApplication {
public static void main(String[] args) {
SpringApplication.run(SpringDataRestApplication.class, args);
}
}

View File

@@ -0,0 +1,87 @@
package com.baeldung.books.config;
import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
@Configuration
@EnableJpaRepositories(basePackages = "com.baeldung.books.repositories")
// @PropertySource("persistence-h2.properties")
// @PropertySource("persistence-hsqldb.properties")
// @PropertySource("persistence-derby.properties")
// @PropertySource("persistence-sqlite.properties")
public class DbConfig {
@Autowired
private Environment env;
@Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("driverClassName"));
dataSource.setUrl(env.getProperty("url"));
dataSource.setUsername(env.getProperty("user"));
dataSource.setPassword(env.getProperty("password"));
return dataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { "com.baeldung.books.models" });
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
em.setJpaProperties(additionalProperties());
return em;
}
final Properties additionalProperties() {
final Properties hibernateProperties = new Properties();
if (env.getProperty("hibernate.hbm2ddl.auto") != null) {
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
}
if (env.getProperty("hibernate.dialect") != null) {
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
}
if (env.getProperty("hibernate.show_sql") != null) {
hibernateProperties.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
}
return hibernateProperties;
}
}
@Configuration
@Profile("h2")
@PropertySource("classpath:persistence-h2.properties")
class H2Config {
}
@Configuration
@Profile("hsqldb")
@PropertySource("classpath:persistence-hsqldb.properties")
class HsqldbConfig {
}
@Configuration
@Profile("derby")
@PropertySource("classpath:persistence-derby.properties")
class DerbyConfig {
}
@Configuration
@Profile("sqlite")
@PropertySource("classpath:persistence-sqlite.properties")
class SqliteConfig {
}

View File

@@ -0,0 +1,42 @@
package com.baeldung.books.config;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.baeldung.books.events.AuthorEventHandler;
import com.baeldung.books.events.BookEventHandler;
@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
public MvcConfig() {
super();
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Bean
WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> enableDefaultServlet() {
return (factory) -> factory.setRegisterDefaultServlet(true);
}
@Bean
AuthorEventHandler authorEventHandler() {
return new AuthorEventHandler();
}
@Bean
BookEventHandler bookEventHandler() {
return new BookEventHandler();
}
}

View File

@@ -0,0 +1,18 @@
package com.baeldung.books.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import com.baeldung.books.projections.CustomBook;
@Configuration
public class RestConfig implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration repositoryRestConfiguration,
CorsRegistry cors) {
repositoryRestConfiguration.getProjectionConfiguration().addProjection(CustomBook.class);
}
}

View File

@@ -0,0 +1,78 @@
package com.baeldung.books.dialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.identity.IdentityColumnSupport;
import java.sql.Types;
public class SQLiteDialect extends Dialect {
public SQLiteDialect() {
registerColumnType(Types.BIT, "integer");
registerColumnType(Types.TINYINT, "tinyint");
registerColumnType(Types.SMALLINT, "smallint");
registerColumnType(Types.INTEGER, "integer");
registerColumnType(Types.BIGINT, "bigint");
registerColumnType(Types.FLOAT, "float");
registerColumnType(Types.REAL, "real");
registerColumnType(Types.DOUBLE, "double");
registerColumnType(Types.NUMERIC, "numeric");
registerColumnType(Types.DECIMAL, "decimal");
registerColumnType(Types.CHAR, "char");
registerColumnType(Types.VARCHAR, "varchar");
registerColumnType(Types.LONGVARCHAR, "longvarchar");
registerColumnType(Types.DATE, "date");
registerColumnType(Types.TIME, "time");
registerColumnType(Types.TIMESTAMP, "timestamp");
registerColumnType(Types.BINARY, "blob");
registerColumnType(Types.VARBINARY, "blob");
registerColumnType(Types.LONGVARBINARY, "blob");
registerColumnType(Types.BLOB, "blob");
registerColumnType(Types.CLOB, "clob");
registerColumnType(Types.BOOLEAN, "integer");
}
public IdentityColumnSupport getIdentityColumnSupport() {
return new SQLiteIdentityColumnSupport();
}
public boolean hasAlterTable() {
return false;
}
public boolean dropConstraints() {
return false;
}
public String getDropForeignKeyString() {
return "";
}
public String getAddForeignKeyConstraintString(String constraintName, String[] foreignKey, String referencedTable, String[] primaryKey, boolean referencesPrimaryKey) {
return "";
}
public String getAddPrimaryKeyConstraintString(String constraintName) {
return "";
}
public String getForUpdateString() {
return "";
}
public String getAddColumnString() {
return "add column";
}
public boolean supportsOuterJoinForUpdate() {
return false;
}
public boolean supportsIfExistsBeforeTableName() {
return true;
}
public boolean supportsCascadeDelete() {
return false;
}
}

View File

@@ -0,0 +1,22 @@
package com.baeldung.books.dialect;
import org.hibernate.MappingException;
import org.hibernate.dialect.identity.IdentityColumnSupportImpl;
public class SQLiteIdentityColumnSupport extends IdentityColumnSupportImpl {
@Override
public boolean supportsIdentityColumns() {
return true;
}
@Override
public String getIdentitySelectString(String table, String column, int type) throws MappingException {
return "select last_insert_rowid()";
}
@Override
public String getIdentityColumnString(int type) throws MappingException {
return "integer";
}
}

View File

@@ -0,0 +1,45 @@
package com.baeldung.books.events;
import java.util.logging.Logger;
import org.springframework.data.rest.core.annotation.HandleAfterCreate;
import org.springframework.data.rest.core.annotation.HandleAfterDelete;
import org.springframework.data.rest.core.annotation.HandleBeforeCreate;
import org.springframework.data.rest.core.annotation.HandleBeforeDelete;
import org.springframework.data.rest.core.annotation.RepositoryEventHandler;
import com.baeldung.books.models.Author;
@RepositoryEventHandler
public class AuthorEventHandler {
Logger logger = Logger.getLogger("Class AuthorEventHandler");
public AuthorEventHandler() {
super();
}
@HandleBeforeCreate
public void handleAuthorBeforeCreate(Author author) {
logger.info("Inside Author Before Create....");
String name = author.getName();
}
@HandleAfterCreate
public void handleAuthorAfterCreate(Author author) {
logger.info("Inside Author After Create ....");
String name = author.getName();
}
@HandleBeforeDelete
public void handleAuthorBeforeDelete(Author author) {
logger.info("Inside Author Before Delete ....");
String name = author.getName();
}
@HandleAfterDelete
public void handleAuthorAfterDelete(Author author) {
logger.info("Inside Author After Delete ....");
String name = author.getName();
}
}

View File

@@ -0,0 +1,27 @@
package com.baeldung.books.events;
import java.util.logging.Logger;
import org.springframework.data.rest.core.annotation.HandleBeforeCreate;
import org.springframework.data.rest.core.annotation.RepositoryEventHandler;
import com.baeldung.books.models.Author;
import com.baeldung.books.models.Book;
@RepositoryEventHandler
public class BookEventHandler {
Logger logger = Logger.getLogger("Class BookEventHandler");
@HandleBeforeCreate
public void handleBookBeforeCreate(Book book) {
logger.info("Inside Book Before Create ....");
book.getAuthors();
}
@HandleBeforeCreate
public void handleAuthorBeforeCreate(Author author) {
logger.info("Inside Author Before Create ....");
author.getBooks();
}
}

View File

@@ -0,0 +1,54 @@
package com.baeldung.books.models;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
@Entity
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(nullable = false)
private String location;
@OneToOne(mappedBy = "address")
private Library library;
public Address() {
}
public Address(String location) {
super();
this.location = location;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public Library getLibrary() {
return library;
}
public void setLibrary(Library library) {
this.library = library;
}
}

View File

@@ -0,0 +1,60 @@
package com.baeldung.books.models;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
@Entity
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(nullable = false)
private String name;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "book_author", joinColumns = @JoinColumn(name = "book_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "author_id", referencedColumnName = "id"))
private List<Book> books;
public Author() {
}
public Author(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public List<Book> getBooks() {
return books;
}
public void setBooks(List<Book> books) {
this.books = books;
}
}

View File

@@ -0,0 +1,82 @@
package com.baeldung.books.models;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(nullable = false)
private String title;
private String isbn;
@ManyToOne
@JoinColumn(name = "library_id")
private Library library;
@ManyToMany(mappedBy = "books", fetch = FetchType.EAGER)
private List<Author> authors;
public Book() {
}
public Book(String title) {
super();
this.title = title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public Library getLibrary() {
return library;
}
public void setLibrary(Library library) {
this.library = library;
}
public List<Author> getAuthors() {
return authors;
}
public void setAuthors(List<Author> authors) {
this.authors = authors;
}
}

View File

@@ -0,0 +1,74 @@
package com.baeldung.books.models;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import org.springframework.data.rest.core.annotation.RestResource;
@Entity
public class Library {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column
private String name;
@OneToOne
@JoinColumn(name = "address_id")
@RestResource(path = "libraryAddress")
private Address address;
@OneToMany(mappedBy = "library")
private List<Book> books;
public Library() {
}
public Library(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public List<Book> getBooks() {
return books;
}
public void setBooks(List<Book> books) {
this.books = books;
}
}

View File

@@ -0,0 +1,37 @@
package com.baeldung.books.models;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Subject {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(nullable = false)
private String name;
public Subject() {
}
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;
}
}

View File

@@ -0,0 +1,22 @@
package com.baeldung.books.projections;
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.rest.core.config.Projection;
import com.baeldung.books.models.Author;
import com.baeldung.books.models.Book;
@Projection(name = "customBook", types = { Book.class })
public interface CustomBook {
@Value("#{target.id}")
long getId();
String getTitle();
List<Author> getAuthors();
@Value("#{target.getAuthors().size()}")
int getAuthorCount();
}

View File

@@ -0,0 +1,9 @@
package com.baeldung.books.repositories;
import org.springframework.data.repository.CrudRepository;
import com.baeldung.books.models.Address;
public interface AddressRepository extends CrudRepository<Address, Long> {
}

View File

@@ -0,0 +1,9 @@
package com.baeldung.books.repositories;
import org.springframework.data.repository.CrudRepository;
import com.baeldung.books.models.Author;
public interface AuthorRepository extends CrudRepository<Author, Long> {
}

View File

@@ -0,0 +1,11 @@
package com.baeldung.books.repositories;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import com.baeldung.books.models.Book;
import com.baeldung.books.projections.CustomBook;
@RepositoryRestResource(excerptProjection = CustomBook.class)
public interface BookRepository extends CrudRepository<Book, Long> {
}

View File

@@ -0,0 +1,9 @@
package com.baeldung.books.repositories;
import org.springframework.data.repository.CrudRepository;
import com.baeldung.books.models.Library;
public interface LibraryRepository extends CrudRepository<Library, Long> {
}

View File

@@ -0,0 +1,16 @@
package com.baeldung.books.repositories;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RestResource;
import com.baeldung.books.models.Subject;
public interface SubjectRepository extends PagingAndSortingRepository<Subject, Long> {
@RestResource(path = "nameContains")
public Page<Subject> findByNameContaining(@Param("name") String name, Pageable p);
}

View File

@@ -0,0 +1 @@
spring.profiles.default=h2

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@@ -0,0 +1,8 @@
driverClassName=org.apache.derby.jdbc.EmbeddedDriver
url=jdbc:derby:memory:myD;create=true
username=sa
password=
hibernate.dialect=org.hibernate.dialect.DerbyDialect
hibernate.show_sql=true
hibernate.hbm2ddl.auto=create-drop

View File

@@ -0,0 +1,8 @@
driverClassName=org.h2.Driver
url=jdbc:h2:mem:myDb;DB_CLOSE_DELAY=-1
username=sa
password=
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.show_sql=true
hibernate.hbm2ddl.auto=create-drop

View File

@@ -0,0 +1,8 @@
driverClassName=org.hsqldb.jdbc.JDBCDriver
url=jdbc:hsqldb:mem:myDb
username=sa
password=
hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.show_sql=true
hibernate.hbm2ddl.auto=create-drop

View File

@@ -0,0 +1,7 @@
driverClassName=org.sqlite.JDBC
url=jdbc:sqlite:memory:myDb?cache=shared
username=sa
password=sa
hibernate.dialect=com.baeldung.dialect.SQLiteDialect
hibernate.hbm2ddl.auto=create-drop
hibernate.show_sql=true

View File

@@ -0,0 +1,51 @@
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="ISO-8859-1">
<title>User CRUD</title>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="view/app.js"></script>
<style>
a {
cursor: pointer;
background-color: lightblue;
}
</style>
</head>
<body>
<div ng-controller="UserCRUDCtrl">
<table>
<tr>
<td width="100">ID:</td>
<td><input type="text" id="id" ng-model="user.id" /></td>
</tr>
<tr>
<td width="100">Name:</td>
<td><input type="text" id="name" ng-model="user.name" /></td>
</tr>
<tr>
<td width="100">Email:</td>
<td><input type="text" id="email" ng-model="user.email" /></td>
</tr>
</table>
<br /> <br />
<a ng-click="getUser(user.id)">Get User</a>
<a ng-click="updateUser(user.id,user.name,user.email)">Update User</a>
<a ng-click="addUser(user.name,user.email)">Add User</a>
<a ng-click="deleteUser(user.id)">Delete User</a>
<br /> <br />
<p style="color: green">{{message}}</p>
<p style="color: red">{{errorMessage}}</p>
<br />
<br />
<a ng-click="getAllUsers()">Get all Users</a><br />
<br /> <br />
<div ng-repeat="usr in users">
{{usr.name}} {{usr.email}}
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,122 @@
var app = angular.module('app',[]);
app.controller('UserCRUDCtrl', ['$scope','UserCRUDService', function ($scope,UserCRUDService) {
$scope.updateUser = function () {
UserCRUDService.updateUser($scope.user.id,$scope.user.name,$scope.user.email)
.then(function success(response){
$scope.message = 'User data updated!';
$scope.errorMessage = '';
},
function error(response){
$scope.errorMessage = 'Error updating user!';
$scope.message = '';
});
}
$scope.getUser = function () {
var id = $scope.user.id;
UserCRUDService.getUser($scope.user.id)
.then(function success(response){
$scope.user = response.data;
$scope.user.id = id;
$scope.message='';
$scope.errorMessage = '';
},
function error (response ){
$scope.message = '';
if (response.status === 404){
$scope.errorMessage = 'User not found!';
}
else {
$scope.errorMessage = "Error getting user!";
}
});
}
$scope.addUser = function () {
if ($scope.user != null && $scope.user.name) {
UserCRUDService.addUser($scope.user.name, $scope.user.email)
.then (function success(response){
$scope.message = 'User added!';
$scope.errorMessage = '';
},
function error(response){
$scope.errorMessage = 'Error adding user!';
$scope.message = '';
});
}
else {
$scope.errorMessage = 'Please enter a name!';
$scope.message = '';
}
}
$scope.deleteUser = function () {
UserCRUDService.deleteUser($scope.user.id)
.then (function success(response){
$scope.message = 'User deleted!';
$scope.user = null;
$scope.errorMessage='';
},
function error(response){
$scope.errorMessage = 'Error deleting user!';
$scope.message='';
})
}
$scope.getAllUsers = function () {
UserCRUDService.getAllUsers()
.then(function success(response){
$scope.users = response.data._embedded.users;
$scope.message='';
$scope.errorMessage = '';
},
function error (response ){
$scope.message='';
$scope.errorMessage = 'Error getting users!';
});
}
}]);
app.service('UserCRUDService',['$http', function ($http) {
this.getUser = function getUser(userId){
return $http({
method: 'GET',
url: 'users/'+userId
});
}
this.addUser = function addUser(name, email){
return $http({
method: 'POST',
url: 'users',
data: {name:name, email:email}
});
}
this.deleteUser = function deleteUser(id){
return $http({
method: 'DELETE',
url: 'users/'+id
})
}
this.updateUser = function updateUser(id,name,email){
return $http({
method: 'PATCH',
url: 'users/'+id,
data: {name:name, email:email}
})
}
this.getAllUsers = function getAllUsers(){
return $http({
method: 'GET',
url: 'users'
});
}
}]);

View File

@@ -0,0 +1,17 @@
package com.baeldung;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.baeldung.books.SpringDataRestApplication;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringDataRestApplication.class)
public class SpringContextTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
}

View File

@@ -0,0 +1,31 @@
package com.baeldung.books.events;
import com.baeldung.books.events.AuthorEventHandler;
import com.baeldung.books.models.Author;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.data.rest.core.annotation.RepositoryEventHandler;
import static org.mockito.Mockito.mock;
public class AuthorEventHandlerUnitTest {
@Test
public void whenCreateAuthorThenSuccess() {
Author author = mock(Author.class);
AuthorEventHandler authorEventHandler = new AuthorEventHandler();
authorEventHandler.handleAuthorBeforeCreate(author);
Mockito.verify(author, Mockito.times(1)).getName();
}
@Test
public void whenDeleteAuthorThenSuccess() {
Author author = mock(Author.class);
AuthorEventHandler authorEventHandler = new AuthorEventHandler();
authorEventHandler.handleAuthorAfterDelete(author);
Mockito.verify(author, Mockito.times(1)).getName();
}
}

View File

@@ -0,0 +1,30 @@
package com.baeldung.books.events;
import com.baeldung.books.events.BookEventHandler;
import com.baeldung.books.models.Author;
import com.baeldung.books.models.Book;
import org.junit.Test;
import org.mockito.Mockito;
import static org.mockito.Mockito.mock;
public class BookEventHandlerUnitTest {
@Test
public void whenCreateBookThenSuccess() {
Book book = mock(Book.class);
BookEventHandler bookEventHandler = new BookEventHandler();
bookEventHandler.handleBookBeforeCreate(book);
Mockito.verify(book, Mockito.times(1)).getAuthors();
}
@Test
public void whenCreateAuthorThenSuccess() {
Author author = mock(Author.class);
BookEventHandler bookEventHandler = new BookEventHandler();
bookEventHandler.handleAuthorBeforeCreate(author);
Mockito.verify(author, Mockito.times(1)).getBooks();
}
}

View File

@@ -0,0 +1,90 @@
package com.baeldung.books.projections;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import java.util.Arrays;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.junit4.SpringRunner;
import com.baeldung.books.SpringDataRestApplication;
import com.baeldung.books.models.Author;
import com.baeldung.books.models.Book;
import com.baeldung.books.repositories.AuthorRepository;
import com.baeldung.books.repositories.BookRepository;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringDataRestApplication.class, webEnvironment = WebEnvironment.DEFINED_PORT)
public class SpringDataProjectionLiveTest {
private static final String BOOK_ENDPOINT = "http://localhost:8080/books";
private static final String AUTHOR_ENDPOINT = "http://localhost:8080/authors";
@Autowired
private BookRepository bookRepo;
@Autowired
private AuthorRepository authorRepo;
@Before
public void setup() {
if (!bookRepo.findById(1L).isPresent()) {
Book book = new Book("Animal Farm");
book.setIsbn("978-1943138425");
book = bookRepo.save(book);
Author author = new Author("George Orwell");
author = authorRepo.save(author);
author.setBooks(Arrays.asList(book));
author = authorRepo.save(author);
}
}
@Test
public void whenGetBook_thenOK() {
final Response response = RestAssured.get(BOOK_ENDPOINT + "/1");
assertEquals(200, response.getStatusCode());
assertTrue(response.asString().contains("isbn"));
assertFalse(response.asString().contains("authorCount"));
// System.out.println(response.asString());
}
@Test
public void whenGetBookProjection_thenOK() {
final Response response = RestAssured.get(BOOK_ENDPOINT + "/1?projection=customBook");
assertEquals(200, response.getStatusCode());
assertFalse(response.asString().contains("isbn"));
assertTrue(response.asString().contains("authorCount"));
// System.out.println(response.asString());
}
@Test
public void whenGetAllBooks_thenOK() {
final Response response = RestAssured.get(BOOK_ENDPOINT);
assertEquals(200, response.getStatusCode());
assertFalse(response.asString().contains("isbn"));
assertTrue(response.asString().contains("authorCount"));
// System.out.println(response.asString());
}
@Test
public void whenGetAuthorBooks_thenOK() {
final Response response = RestAssured.get(AUTHOR_ENDPOINT + "/1/books");
assertEquals(200, response.getStatusCode());
assertFalse(response.asString().contains("isbn"));
assertTrue(response.asString().contains("authorCount"));
System.out.println(response.asString());
}
}