Spring Boot and RESTful API(一)Prepare ENV and Web Layer
Spring Boot and RESTful API(1)Prepare ENV and Web Layer
Spring Boot and RESTful API(1)Prepare ENV and Web Layer
Follow this document
https://spring.io/guides/gs/actuator-service/
https://spring.io/guides/gs/consuming-rest-restjs/
Some Information Endpoint
http://localhost:8080/application/health
http://localhost:8080/application/info
http://localhost:8080/application/metrics
http://localhost:8080/application/trace
http://localhost:8080/api/books/1
List of the SQL
http://localhost:8080/application/flyway
Console of H2
http://localhost:8080/h2-console
Maven Flyway Plugin
https://flywaydb.org/getstarted/firststeps/maven
http://qinghua.github.io/flyway/
webflux cassandra
https://github.com/bijukunjummen/sample-webflux-annot-cassandra
https://dzone.com/articles/spring-webflux-first-steps
Prepare the ENV gradle
http://wiki.jikexueyuan.com/project/gradle/java-quickstart.html
install gradle
http://sillycat.iteye.com/blog/2090147
http://sillycat.iteye.com/blog/1074642
https://gradle.org/install#manually
I chose to Install that manually
>wget https://downloads.gradle.org/distributions/gradle-3.5-bin.zip
Directly Unzip the file and place in the working area, add the bin to the PATH
>gradle --version
------------------------------------------------------------
Gradle 3.5
------------------------------------------------------------
Build time: 2017-04-10 13:37:25 UTC
Revision: b762622a185d59ce0cfc9cbc6ab5dd22469e18a6
Groovy: 2.4.10
Ant: Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM: 1.8.0_121 (Oracle Corporation 25.121-b13)
OS: Mac OS X 10.12.5 x86_64
>gradle build
Reactor Introduction
https://www.ibm.com/developerworks/cn/java/j-cn-with-reactor-response-encode/index.html
Flux - 0 - N sequence of items. sequence of items, sequence ends and sequence error.
If message produce, subscribe will be called with these methods onNext(), onComplete(), onError()
Mono - 0 - 1 If we put 2 Mono Sequence together, that is Flux.
Create Flux Static Method
just()
fromArray()
fromInterable()
fromStream
empty()
error(Throwable error)
Create Mono Static Method
just()
empty()
error()
Important Operation
filter
Flux.range(1, 10).filter(i->i%2 ==0).subscribe(System.out::println);
window - buffer
Flux.range(1, 100).window(20).subscribe(System.out::println):
Flux.intervalMillis(100).windowMillis(1001).take(2).toStream().forEach(System.out::println);
zipWith take reduce reduceWith merge mergeSequential flatMap flatMapSequential concatMap combineLatest
Inputer1 ——event —> Service Handler —> Dispatch — > Request Handler1
—> Dispatch —> Request Handler2
Inputer2 —— event —> —> Dispatch —> Request Handler3
Set Up the WebFlux on HTTP REST Layer
We can have reactor in the DAO layer as well by the supporting from latest spring. But it is fine. It is easy to use that only on top of the controller layer.
My pom.xml is as follow:
<?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>
<groupId>com.j2c</groupId>
<artifactId>jobs-monitor-api</artifactId>
<version>1.0.0</version>
<name>Jobs Monitor API</name>
<description>spring boot/cassandra/solr/webflux</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.M1</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- spring-boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- tools -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
</project>
Application Class to start the Web JobsMonitorAPIApplication.java
package com.sillycat.jobsmonitorapi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class JobsMonitorAPIApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(JobsMonitorAPIApplication.class);
}
}
Sample Controller JobsController.java
package com.sillycat.jobsmonitorapi.web;
import java.util.ArrayList;
import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.j2c.jobsmonitorapi.dto.JobDto;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/api1.0/jobs")
public class JobController {
@GetMapping(path = "/{id}", produces = MediaTypes.JSON_UTF_8)
public Mono<JobDto> get(@PathVariable("id") Long id) {
JobDto dto = new JobDto();
dto.id = 1l;
dto.description = "java, scala, python, groovy, golang";
dto.status = "LIVE";
dto.title = "fullstack";
dto.url = "sillycat.ddns.net";
return Mono.just(dto);
}
@PostMapping(produces = MediaTypes.JSON_UTF_8)
public Mono<ResponseEntity<JobDto>> save(@RequestBody JobDto dto) {
return Mono.just(new ResponseEntity<>(dto, HttpStatus.CREATED));
}
@PutMapping(path = "/{id}", produces = MediaTypes.JSON_UTF_8)
public Mono<ResponseEntity<JobDto>> update(@PathVariable("id") Long id, @RequestBody JobDto dto) {
if (id == 0) {
return Mono.just(new ResponseEntity<>(HttpStatus.NOT_FOUND));
} else {
return Mono.just(new ResponseEntity<>(dto, HttpStatus.CREATED));
}
}
@DeleteMapping(path = "/{id}", produces = MediaTypes.JSON_UTF_8)
public Mono<ResponseEntity<String>> delete(@PathVariable("id") Long id) {
return Mono.just(new ResponseEntity<>(HttpStatus.ACCEPTED));
}
@GetMapping(produces = MediaTypes.JSON_UTF_8)
public Flux<JobDto> load() {
JobDto dto1 = new JobDto();
dto1.id = 1l;
dto1.description = "java, scala, python, groovy, golang";
dto1.status = "LIVE";
dto1.title = "fullstack";
dto1.url = "sillycat.ddns.net";
JobDto dto2 = new JobDto();
dto2.id = 2l;
dto2.description = "java, scala, python, groovy, golang";
dto2.status = "LIVE";
dto2.title = "fullstack";
dto2.url = "sillycat.ddns.net";
List<JobDto> list = new ArrayList<JobDto>();
list.add(dto1);
list.add(dto2);
//return Flux.just(list.toArray(new JobDto[list.size()]));
return Flux.fromArray(list.toArray(new JobDto[list.size()]));
}
}
References:
http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#getting-started-first-application
bunch of samples
https://github.com/spring-projects/spring-boot/tree/v2.0.0.M1/spring-boot-samples
bean mapping
http://orika-mapper.github.io/orika-docs/intro.html
pom version
https://github.com/spring-projects/spring-boot/blob/d21a5076feb1ba24da3a6e2a0c72c8003cf3701f/spring-boot-dependencies/pom.xml
https://github.com/springside/springside4/wiki/Tutorial
Spring Boot and RESTful API(1)Prepare ENV and Web Layer
Follow this document
https://spring.io/guides/gs/actuator-service/
https://spring.io/guides/gs/consuming-rest-restjs/
Some Information Endpoint
http://localhost:8080/application/health
http://localhost:8080/application/info
http://localhost:8080/application/metrics
http://localhost:8080/application/trace
http://localhost:8080/api/books/1
List of the SQL
http://localhost:8080/application/flyway
Console of H2
http://localhost:8080/h2-console
Maven Flyway Plugin
https://flywaydb.org/getstarted/firststeps/maven
http://qinghua.github.io/flyway/
webflux cassandra
https://github.com/bijukunjummen/sample-webflux-annot-cassandra
https://dzone.com/articles/spring-webflux-first-steps
Prepare the ENV gradle
http://wiki.jikexueyuan.com/project/gradle/java-quickstart.html
install gradle
http://sillycat.iteye.com/blog/2090147
http://sillycat.iteye.com/blog/1074642
https://gradle.org/install#manually
I chose to Install that manually
>wget https://downloads.gradle.org/distributions/gradle-3.5-bin.zip
Directly Unzip the file and place in the working area, add the bin to the PATH
>gradle --version
------------------------------------------------------------
Gradle 3.5
------------------------------------------------------------
Build time: 2017-04-10 13:37:25 UTC
Revision: b762622a185d59ce0cfc9cbc6ab5dd22469e18a6
Groovy: 2.4.10
Ant: Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM: 1.8.0_121 (Oracle Corporation 25.121-b13)
OS: Mac OS X 10.12.5 x86_64
>gradle build
Reactor Introduction
https://www.ibm.com/developerworks/cn/java/j-cn-with-reactor-response-encode/index.html
Flux - 0 - N sequence of items. sequence of items, sequence ends and sequence error.
If message produce, subscribe will be called with these methods onNext(), onComplete(), onError()
Mono - 0 - 1 If we put 2 Mono Sequence together, that is Flux.
Create Flux Static Method
just()
fromArray()
fromInterable()
fromStream
empty()
error(Throwable error)
Create Mono Static Method
just()
empty()
error()
Important Operation
filter
Flux.range(1, 10).filter(i->i%2 ==0).subscribe(System.out::println);
window - buffer
Flux.range(1, 100).window(20).subscribe(System.out::println):
Flux.intervalMillis(100).windowMillis(1001).take(2).toStream().forEach(System.out::println);
zipWith take reduce reduceWith merge mergeSequential flatMap flatMapSequential concatMap combineLatest
Inputer1 ——event —> Service Handler —> Dispatch — > Request Handler1
—> Dispatch —> Request Handler2
Inputer2 —— event —> —> Dispatch —> Request Handler3
Set Up the WebFlux on HTTP REST Layer
We can have reactor in the DAO layer as well by the supporting from latest spring. But it is fine. It is easy to use that only on top of the controller layer.
My pom.xml is as follow:
<?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>
<groupId>com.j2c</groupId>
<artifactId>jobs-monitor-api</artifactId>
<version>1.0.0</version>
<name>Jobs Monitor API</name>
<description>spring boot/cassandra/solr/webflux</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.M1</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- spring-boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- tools -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
</project>
Application Class to start the Web JobsMonitorAPIApplication.java
package com.sillycat.jobsmonitorapi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class JobsMonitorAPIApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(JobsMonitorAPIApplication.class);
}
}
Sample Controller JobsController.java
package com.sillycat.jobsmonitorapi.web;
import java.util.ArrayList;
import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.j2c.jobsmonitorapi.dto.JobDto;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/api1.0/jobs")
public class JobController {
@GetMapping(path = "/{id}", produces = MediaTypes.JSON_UTF_8)
public Mono<JobDto> get(@PathVariable("id") Long id) {
JobDto dto = new JobDto();
dto.id = 1l;
dto.description = "java, scala, python, groovy, golang";
dto.status = "LIVE";
dto.title = "fullstack";
dto.url = "sillycat.ddns.net";
return Mono.just(dto);
}
@PostMapping(produces = MediaTypes.JSON_UTF_8)
public Mono<ResponseEntity<JobDto>> save(@RequestBody JobDto dto) {
return Mono.just(new ResponseEntity<>(dto, HttpStatus.CREATED));
}
@PutMapping(path = "/{id}", produces = MediaTypes.JSON_UTF_8)
public Mono<ResponseEntity<JobDto>> update(@PathVariable("id") Long id, @RequestBody JobDto dto) {
if (id == 0) {
return Mono.just(new ResponseEntity<>(HttpStatus.NOT_FOUND));
} else {
return Mono.just(new ResponseEntity<>(dto, HttpStatus.CREATED));
}
}
@DeleteMapping(path = "/{id}", produces = MediaTypes.JSON_UTF_8)
public Mono<ResponseEntity<String>> delete(@PathVariable("id") Long id) {
return Mono.just(new ResponseEntity<>(HttpStatus.ACCEPTED));
}
@GetMapping(produces = MediaTypes.JSON_UTF_8)
public Flux<JobDto> load() {
JobDto dto1 = new JobDto();
dto1.id = 1l;
dto1.description = "java, scala, python, groovy, golang";
dto1.status = "LIVE";
dto1.title = "fullstack";
dto1.url = "sillycat.ddns.net";
JobDto dto2 = new JobDto();
dto2.id = 2l;
dto2.description = "java, scala, python, groovy, golang";
dto2.status = "LIVE";
dto2.title = "fullstack";
dto2.url = "sillycat.ddns.net";
List<JobDto> list = new ArrayList<JobDto>();
list.add(dto1);
list.add(dto2);
//return Flux.just(list.toArray(new JobDto[list.size()]));
return Flux.fromArray(list.toArray(new JobDto[list.size()]));
}
}
References:
http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#getting-started-first-application
bunch of samples
https://github.com/spring-projects/spring-boot/tree/v2.0.0.M1/spring-boot-samples
bean mapping
http://orika-mapper.github.io/orika-docs/intro.html
pom version
https://github.com/spring-projects/spring-boot/blob/d21a5076feb1ba24da3a6e2a0c72c8003cf3701f/spring-boot-dependencies/pom.xml
https://github.com/springside/springside4/wiki/Tutorial