1. Summary

This project illustrate a compilation of different concepts and technical solution for a "modern".[1] technology stack.

The key requirements for this blueprint are:

  • onion architecture

    • SOLID, especially focus on D=Dependency inversion principle

  • reactivate

  • well documented

  • maintainable

2. Overview

This documentation gives an overview of the architecture and the existing interfaces (interfaces).

3. Requirements

The application complies with the following functional and non-functional requirements. However the focus on this blueprint are more the non-functional requirements.

3.1. Functional Requirements

See for a draft overview of the business use cases.

3.2. Non functional Requirements

  • Fulfil a clean/onion architecture

    • SOLID

    • No layer in the inner circle (lower layer) has a relationship to the outer (upper) layer

  • Resilience

  • Provide enough information to maintaine the application

    • Monitoring information

      • Log files

      • Metrics

        • Codahale metrics

        • Spring Actuactor

  • Provide a documentation of the application and interfaces

    • Documentation and Code at the same place

    • Generate the documentation

4. Architecture

The key benefit of the Blueprint application is the administration of notes. A note is a set of content data, tags, rubric, attachments and possible due date.

The application provides different endpoints and stores the data in a persistent storage.

The main concept is the onion architecture, mainly the Dependency inversion principle. The architecture contains the following "layers":

  • Core: which represents all the code for implementing the bounded context (Domain classes, services implementation). Main requirement is, that this layer do not know anything from the layers above. No dependencies to external libs (JAX-RS, JPA, Spring etc) are allowed. Every logic, which will be implemented with a 3rd lib, should provide an interface. This interface will be implemented in an other layer and this core layer stay loose coupled.

  • Infrastructure: Knows only the core layer. Realize some of the interface from the core layer using if necessary 3rd libs. Like repository implementation using a JPA implementation (EclipseLink, Spring Data JPA etc). Contains also own domain classes, like entity classes. Do not use the domain classes from the core layer for JPA logic. Otherwise is it necessary to add JPA annotations to the domain classes in the core layer. This violates the requirement, that the lower layer knows nothing from any upper one.

  • UI: Knows only infra and core layers. Represents any endpoint logic and libs, like REST, JSF etc. It is possible to use here the domain classes from the core layer, however it is not advisable to spread them out.

4.1. Components

diagram arch components general

4.1.1. Blueprint App

diagram arch class blueprint app

The following use cases are part and parcel of the application.

diagram arch usecase blueprint app

Regarding the clean/onion architecture looks the distribution of the components as follows:

diagram arch components blueprint app

The main idea behind the architecture is the concept of Dependency inversion principle.

component1
component2
component3
diag b81ea8607a5a83b49f17334699cc72e8

5. Interfaces

5.1. Overview

This chapters gives an overview of the existing interfaces. The interface documentation is completely generated with swagger.

5.2. Swagger

The rest interfaces are documented with swagger. The endpoint to the swagger UI is http://localhost:8099/swagger-ui.html

The swagger capabilities is reached with the following libs:

  • springfox-swagger2

  • springfox-swagger-ui: The UI

5.3. Swagger AsciiDoctor Integration

Swagger (or now https://www.openapis.org/) provides the toolset for defining a REST interface. The Swagger JSON definition will be used to generate AsciiDoc files which holds the information for every interface; totally generated. To achieve this is the following tool chain necessary

  • springfox

    • Configure and enable Swagger support

    • Generate swagger.json in a test unit using the /v2/api-docs?group=Note endpoint

    • Generate REST snippets (Request and Response examples) tbd

  • swagger2markup

    • Configure to generate based on swagger.json a documentation

    • include the generated adoc

Know bugs

  • AsciiDoctor-PDF: The generation a PDF from swagger documentation fails. The reason is a missing initialization in the internal lib

Open

  • Refactor the test unit to separate class

6. Monitoring

6.1. Overview

This chapter gives an overview about the monitoring mechanism in this application to fulfill different aspects like:

  • Application logs: represents the state of the application on business and technical point of view

  • Application metrics: Structured view on pre-defined measurement points, as well on business and technical point of view

  • System metrics: Any technical information outside of the application, like network traffic and system load

  • Request tracing: Trace the request and responses on the one hand, and the different hops caused from a client request

  • Health monitoring: Any information to monitor the stability and availability of the application

This rough categorization of the relevant monitoring facets have different requirements regarding the tooling, topicality and amount of data.

The spring (boot) ecosystem provides here a good integrated set of modules to gather and expose such data. In addition exists further enhancements to extend the interpretability of the collected data. This chapter goes into the usage and integration of the available spring modules and further enhancing modules, like:

  • Spring Actuator

  • Spring Sleuth

  • Codahale Metrics

  • Zipkin

  • Elastisearch and Beats (Metricbeat, Packetbeat, Filebeat, Heartbeat)

  • Prometheus

Extras

  • Jolokia and Metricbeat

  • Zipkin Chrome Extension

6.2. Spring Actuator

With the Spring actuator extension gather the application a lot of information like

Some of the information are very sensitive, this is reason why the security is in general active and disallows the access without credentials. To deactivate - for dev purposes ;-) - use this parameter in application.properties management.security.enabled=false.

A detailed list of the availabe endpoints and configuratoin possibilities are described here: https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html

To activate this module is only a dependency necessary

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

6.3. Coda Hale Metrics

Coda Hale metrics is one of the most famous metrics implementation. For providing own metrics is it advisable to use this lib for gather and deliver different kinds of metric information.

Spring automatically determine the existence of Coda Hale Metrics in the classpath and replace some of the own implementations with the one from Coda Hale/Dropwizard. The metrics will be also exposed via the /metrics endpoint.

To integrate Coda Hale/Dropwizard metrics add this dependency to the pom.xml

<dependency>
	<groupId>io.dropwizard.metrics</groupId>
	<artifactId>metrics-core</artifactId>
	<version>${dropwizard.metrics.version}</version>
</dependency>

For an usage look at the com.haddouti.pg.blueprint.note.infra.monitoring.NoteEventMonitoring<T> implementation and the result at the metrics endpoint; see in the next listing a result with the own metrics

  • com.haddouti.pg.blueprint.note.infra.monitoring.NoteEventMonitoring.responses.*: A timer metric holding different values for the response time

  • com.haddouti.pg.blueprint.note.infra.monitoring.NoteEventMonitoring.executed-events: Representing a counter metrics representing the number of events

{
	"mem": 508751,
	"mem.free": 216697,
	"processors": 2,
	"instance.uptime": 93563,
	"uptime": 105687,
	"systemload.average": 1.37,
	"heap.committed": 437248,
	"heap.init": 129024,
	"heap.used": 220550,
	"heap": 1815040,
	"nonheap.committed": 73488,
	"nonheap.init": 2496,
	"nonheap.used": 71503,
	"nonheap": 0,
	"threads.peak": 21,
	"threads.daemon": 19,
	"threads.totalStarted": 26,
	"threads": 21,
	"classes": 10317,
	"classes.loaded": 10317,
	"classes.unloaded": 0,
	"gc.ps_scavenge.count": 10,
	"gc.ps_scavenge.time": 195,
	"gc.ps_marksweep.count": 2,
	"gc.ps_marksweep.time": 189,
	"com.haddouti.pg.blueprint.note.infra.monitoring.NoteEventMonitoring.responses.snapshot.mean": 1,
	"gauge.response.metrics": 16.0,
	"com.haddouti.pg.blueprint.note.infra.monitoring.NoteEventMonitoring.executed-events": 4,
	"gauge.response.note.v1.note": 18.0,
	"counter.status.200.note.v1.note": 4,
	"com.haddouti.pg.blueprint.note.infra.monitoring.NoteEventMonitoring.responses.snapshot.75thPercentile": 2,
	"com.haddouti.pg.blueprint.note.infra.monitoring.NoteEventMonitoring.responses.snapshot.95thPercentile": 3,
	"gauge.response.star-star.favicon.ico": 4.0,
	"com.haddouti.pg.blueprint.note.infra.monitoring.NoteEventMonitoring.responses.snapshot.999thPercentile": 3,
	"com.haddouti.pg.blueprint.note.infra.monitoring.NoteEventMonitoring.responses.snapshot.98thPercentile": 3,
	"com.haddouti.pg.blueprint.note.infra.monitoring.NoteEventMonitoring.responses.snapshot.min": 0,
	"com.haddouti.pg.blueprint.note.infra.monitoring.NoteEventMonitoring.responses.snapshot.max": 3,
	"counter.status.200.star-star.favicon.ico": 4,
	"counter.status.200.metrics": 4,
	"com.haddouti.pg.blueprint.note.infra.monitoring.NoteEventMonitoring.responses.meanRate": 0.04149518995882756,
	"com.haddouti.pg.blueprint.note.infra.monitoring.NoteEventMonitoring.responses.snapshot.median": 2,
	"com.haddouti.pg.blueprint.note.infra.monitoring.NoteEventMonitoring.responses.snapshot.stdDev": 0,
	"com.haddouti.pg.blueprint.note.infra.monitoring.NoteEventMonitoring.responses.fifteenMinuteRate": 0.0044076009778713995,
	"com.haddouti.pg.blueprint.note.infra.monitoring.NoteEventMonitoring.responses.fiveMinuteRate": 0.013005185767779516,
	"com.haddouti.pg.blueprint.note.infra.monitoring.NoteEventMonitoring.responses.count": 4,
	"com.haddouti.pg.blueprint.note.infra.monitoring.NoteEventMonitoring.responses.snapshot.99thPercentile": 3,
	"com.haddouti.pg.blueprint.note.infra.monitoring.NoteEventMonitoring.responses.oneMinuteRate": 0.05895238133346083,
	"httpsessions.max": -1,
	"httpsessions.active": 0
}

6.4. Spring Cloud Sleuth

Spring Cloud Sleuth helps tracing a request from the ingress to the egress, including all hops. Every new incoming request represents a trace with a trace ID. Every hop to a component during processing this request is a new span with a span ID. A span may contains additional information like tags or metadata. Common tags are start and end timestamp.

Once added Spring Cloud Sleuth to the project, instruments automatically common communication channels:

  • Any Spring Cloud Stream binder (exists for Apache Kafka, RabbitMQ etc)

  • HTTP headers received over Spring MVC Controller

  • Any request made with Springs RestTemplate

6.4.1. Intregation

To integrate Spring Cloud Sleuth use this dependency

<dependencyManagement>
	<!-- Spring Cloud: Sleuth. Place this AFTER boot-dependencies to avoid
				the usage of 1.5.4 -->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-sleuth</artifactId>
		<version>${spring.sleuth.version}</version>
		<type>pom</type>
		<scope>import</scope>
	</dependency>
</dependencyManagement>

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

Every usage of SLF4J like

	private static Logger log = LoggerFactory.getLogger(RestNoteMaintenance.class);

	// ...
	log.info("putNote(): request={}", req);

produces an output using SLF4J MDC

2017-09-30 20:17:17.560  INFO [-,72eb71ec78f71000,72eb71ec78f71000,false] 5268 --- [nio-8099-exec-1] c.h.p.b.web.rest.RestNoteMaintenance     : putNote(): request=NoteRequest [items=[]]

Relevant are the following new information [bp,36ab5fc28f679a34,36ab5fc28f679a34,false] with the format [appname,traceId,spanId,exportable].

  • appname: defined in spring.application.name, e.g. in application.yml or bootstrap.yml

  • traceId: generated, represents a unique request

  • spanId: generated, every hop gets an own ID

  • exportable: whether the log should be exported to Zipkin or not.

7. Docker

7.1. Overview

This application provides also a docker image.

7.2. Docker Maven

For creating the docker image the dockerfile-maven-plugin is used. This plugin expects in a working directory (contextDirectory) all the necessary files, like Dockerfile, libs/jars etc. To achieve this, we used the maven-resources-plugin and maven-dependency-plugin to copy the Dockerfile and builded jar file(s) into the context directory.

See the blueprint-web/pom.xml for details. To build the docker image run use the profile dockerbuild:

mvn -Pdockerbuild package

To start the docker container:

docker run -it --rm -p 8099:8099 haf-tech/blueprint:0.0.1-SNAPSHOT

8. Docu

8.1. Overview

This chapters gives an overview over of the documentation and how is it generated. The toolchain for the documentation generated consists of a combination of AsciiDoctor, AsciiDoctorJ and some further AsciiDoctorJ Extensions like AsciiDoctorJ-Diagram for PlantUML usage.

8.2. Toolchain

Name URL Note

AsciiDoctor

AsciiDoctor is the main tool which provides the logic and markup for the whole files. The markup is similar to Markdown with some extensions.

AsciiDoctorJ

Is an AsciiDoctor extension for Java integration. Maven plugins exist

AsciiDoctorJ PDF

PDF extension for AsciiDoctorJ

AsciiDoctorJ Diagram

Extension to integrate ascii art for creating diagrams, using different syntaxs, like PlantUML integration.

PlantUML

Lib for generating different UML diagrams (UseCase, component, sequence etc) in ascii. In general this lib needs Graphviz and/dot as external execution. However PlantUML contains a alpha support for internal ploting logic (!pragma graphviz_dot jdot)

Swagger2Markup

Swagger2Markup, here AsciiDoc, using swagger.json to generate the AsciiDoc files.

8.3. Generation

The documentation will be generated with maven using the profile documentation:

mvn generate-resources -Pdocumentation

9. References

This chapter list all the relevant references.

9.1. Libs

Table 1. References
Name URL Note

Springfox

https://github.com/springfox/springfox

Lib for Swagger Support with Spring. Generates the necessary JSON docu

Swagger2Markup

https://github.com/Swagger2Markup/swagger2markup

Swagger to AsciiDoctor support

Swagger2Markup Maven plugin

https://github.com/Swagger2Markup/swagger2markup-maven-plugin

Swagger to AsciiDoctor Maven plugin

Swagger2Markup Maven plugin: Demo

https://github.com/Swagger2Markup/spring-swagger2markup-demo

Swagger2Markup Demo

Dockerfile Maven Plugin

https://github.com/spotify/dockerfile-maven

Dockerfile maven plugin. Uses a Dockerfile to create a new docker image

Note Maintenance

10. Overview

Note Maintenance

10.2. Contact information

Contact : Hafid Haddouti

10.3. License information

License : Apache License Version 2.0
License URL : exmaple.org/LICENSE
Terms of service : http://example.org

10.4. URI scheme

Host : localhost
BasePath : /

10.5. Tags

  • rest-note-maintenance : Rest Note Maintenance

11. Resources

11.1. Rest-note-maintenance

Rest Note Maintenance

11.1.1. getAllNotes

GET /note/v1/note
Responses
HTTP Code Description Schema

200

OK

NoteResponse

401

Unauthorized

No Content

403

Forbidden

No Content

404

Not Found

No Content

Consumes
  • application/json

11.1.2. putNote

PUT /note/v1/note
Parameters
Type Name Description Schema

Body

req
required

req

NoteRequest

Responses
HTTP Code Description Schema

200

OK

NoteResponse

201

Created

No Content

401

Unauthorized

No Content

403

Forbidden

No Content

404

Not Found

No Content

Consumes
  • application/xml

  • application/json

11.1.3. deleteNote

DELETE /note/v1/note
Parameters
Type Name Description Schema

Body

req
required

req

NoteRequest

Responses
HTTP Code Description Schema

200

OK

NoteResponse

204

No Content

No Content

401

Unauthorized

No Content

403

Forbidden

No Content

Consumes
  • application/xml

  • application/json

12. Definitions

12.1. NoteItem

Name Schema

content
optional

string

id
optional

integer (int64)

reminderAt
optional

string (date-time)

title
optional

string

userId
optional

string

12.2. NoteRequest

Name Schema

items
optional

< NoteItem > array

12.3. NoteResponse

Name Schema

items
optional

< NoteItem > array

resultStatus
optional

< StatusCode > array

12.4. StatusCode

Name Schema

code
optional

string

text
optional

string


1. Tbd tomorrow