Skip to content

Commit 66cfe3e

Browse files
committed
ok
1 parent 5584731 commit 66cfe3e

40 files changed

Lines changed: 1369 additions & 1233 deletions

build.gradle

Lines changed: 84 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
buildscript {
22
ext {
3+
groovyallVersion = '3.0.9'
4+
springbootVersion = "2.6.2"
5+
spockCoreVersion = "2.0-groovy-3.0"
6+
spockReportsVersion = '2.1-groovy-3.0'
7+
38
nexus_url = "${project.findProperty('nexus_url') ?: System.getenv('NEXUS_HOST')}"
49
nexus_user = "${project.findProperty('nexus_user') ?: System.getenv('NEXUS_USERNAME')}"
510
nexus_pw = "${project.findProperty('nexus_pw') ?: System.getenv('NEXUS_PASSWORD')}"
@@ -51,32 +56,21 @@ buildscript {
5156
}
5257
}
5358

54-
buildscript {
55-
ext {
56-
joobyVersion = "1.6.6"
57-
}
58-
59-
dependencies {
60-
classpath "org.jooby:jooby-gradle-plugin:$joobyVersion"
61-
}
62-
}
63-
6459
plugins {
65-
id "com.github.johnrengelman.shadow" version "5.1.0"
66-
id "com.google.osdetector" version "1.6.2"
67-
id "io.spring.dependency-management" version "1.0.8.RELEASE"
60+
id "groovy"
61+
id 'application'
62+
id "com.github.johnrengelman.shadow" version "7.1.1"
63+
id "com.google.osdetector" version "1.7.0"
64+
id 'com.adarshr.test-logger' version '3.1.0'
65+
id 'jacoco'
66+
id 'org.springframework.boot' version "${springbootVersion}"
67+
id 'com.bmuschko.docker-spring-boot-application' version '7.1.0'
6868
}
6969

70-
apply plugin: "application"
71-
apply plugin: "distribution"
72-
apply plugin: "groovy"
73-
apply plugin: "jooby"
74-
apply plugin: "jacoco"
75-
7670
repositories {
71+
mavenCentral()
7772
if (no_nexus) {
7873
println("using repositories 'jcenter' and 'mavenCentral', because property no_nexus=$no_nexus")
79-
jcenter()
8074
mavenCentral()
8175
} else {
8276
println("using nexus repositories")
@@ -107,63 +101,97 @@ repositories {
107101
}
108102

109103
group = 'org.ods'
110-
version = '0.1'
111-
mainClassName = "app.App"
112-
sourceCompatibility = 1.8
104+
version = '1.0'
105+
mainClassName = "org.ods.document.generation.svc.App"
113106

114-
dependencyManagement {
115-
imports {
116-
mavenBom "org.jooby:jooby-bom:$joobyVersion"
107+
java {
108+
toolchain {
109+
languageVersion.set(JavaLanguageVersion.of(11))
117110
}
118111
}
119112

113+
compileGroovy {
114+
groovyOptions.javaAnnotationProcessing = true
115+
}
116+
120117
dependencies {
121-
compile "com.github.ben-manes.caffeine:caffeine:2.7.0"
122-
compile "com.github.jknack:handlebars:4.1.2"
123-
compile "commons-io:commons-io:2.6"
124-
compile "io.github.openfeign:feign-core:10.2.3"
125-
compile "io.github.openfeign:feign-gson:10.2.3"
126-
compile "io.github.openfeign:feign-okhttp:10.2.3"
127-
compile "net.lingala.zip4j:zip4j:1.3.3"
128-
compile "org.apache.httpcomponents:httpclient:4.5.8"
129-
compile "org.codehaus.groovy:groovy-all:2.5.7"
130-
compile "org.jooby:jooby-jackson"
131-
compile "org.jooby:jooby-netty"
132-
133-
compile "io.netty:netty-transport-native-epoll:${dependencyManagement.importedProperties['netty.version']}:${osdetector.classifier.contains('linux') ? 'linux-x86_64' : ''}"
134-
compile "io.netty:netty-tcnative-boringssl-static:${dependencyManagement.importedProperties['boringssl.version']}"
135-
136-
testCompile "junit:junit:4.12"
137-
testCompile "com.github.stefanbirkner:system-rules:1.19.0" // for managing environment variables
138-
testCompile "com.github.tomakehurst:wiremock:2.23.2" // for mocking HTTP server reponses
139-
testCompile "io.rest-assured:rest-assured:4.0.0" // for validating REST services
140-
testCompile "org.spockframework:spock-core:1.3-groovy-2.5"
118+
implementation (group: 'org.codehaus.groovy', name: 'groovy-all', version: groovyallVersion){
119+
exclude group: "org.codehaus.groovy", module: "groovy-test-junit5"
120+
}
141121

122+
implementation "org.springframework.boot:spring-boot-starter:${springbootVersion}"
123+
implementation "org.springframework.boot:spring-boot-starter-web:${springbootVersion}"
124+
implementation "org.springframework.boot:spring-boot-starter-cache:${springbootVersion}"
125+
126+
implementation("javax.inject:javax.inject:1")
127+
implementation("javax.cache:cache-api:1.1.1")
128+
129+
implementation 'com.fasterxml.jackson.core:jackson-databind'
130+
implementation 'com.github.ben-manes.caffeine:caffeine:3.0.5'
131+
implementation 'com.github.jknack:handlebars:4.3.0'
132+
implementation 'commons-io:commons-io:2.11.0'
133+
implementation 'io.github.openfeign:feign-core:11.8'
134+
implementation 'io.github.openfeign:feign-gson:11.8'
135+
implementation 'io.github.openfeign:feign-okhttp:11.8'
136+
implementation 'net.lingala.zip4j:zip4j:2.9.1'
137+
implementation 'org.apache.httpcomponents:httpclient:4.5.13'
142138
implementation "org.apache.pdfbox:pdfbox:2.0.24"
143-
}
144139

145-
test {
146-
outputs.dir snippetsDir
140+
testImplementation "org.junit.jupiter:junit-jupiter-api"
141+
testImplementation "org.junit.jupiter:junit-jupiter-engine"
142+
testImplementation("uk.org.webcompere:system-stubs-core:1.2.0")
143+
testImplementation "org.testcontainers:spock:1.16.2"
144+
testImplementation("org.testcontainers:testcontainers:1.16.2")
145+
146+
testImplementation("org.spockframework:spock-core:${spockCoreVersion}")
147+
testImplementation ("com.athaydes:spock-reports:$spockReportsVersion"){ transitive = false }
148+
testImplementation "org.spockframework:spock-spring:${spockCoreVersion}"
149+
testImplementation "org.springframework.boot:spring-boot-starter-test:${springbootVersion}"
147150

148-
// Use overrides in conf/application.test.conf in ConfigFactory.load()
149-
// TODO: setting application.env should be enough, but apparently isn't
150-
systemProperty "application.env", "test"
151-
systemProperty "config.resource", "application.test.conf"
151+
testImplementation "com.github.stefanbirkner:system-rules:1.19.0" // for managing environment variables
152+
testImplementation 'com.github.tomakehurst:wiremock:2.27.2' // for mocking HTTP server reponses
153+
testImplementation 'io.rest-assured:rest-assured:4.4.0' // for validating REST services
154+
}
152155

156+
test {
153157
testLogging {
154158
showStandardStreams = true
159+
exceptionFormat = 'full'
160+
}
161+
filter {
162+
includeTestsMatching "*Spec"
155163
}
164+
useJUnitPlatform()
156165

157166
finalizedBy jacocoTestReport
158167
}
159168

169+
task dockerTest(type: Test) {
170+
group("verification")
171+
filter {
172+
includeTestsMatching "*IT"
173+
}
174+
useJUnitPlatform()
175+
}
176+
160177
jacocoTestReport {
161178
reports {
162179
xml.enabled true
163180
}
164181
}
165182

166-
/** We diverge from the default resources structure to adopt the Jooby standard: */
167-
sourceSets.main.resources {
168-
srcDirs = ["conf", "public"]
183+
import com.bmuschko.gradle.docker.tasks.image.*
184+
task buildImage(type: DockerBuildImage) {
185+
// dependsOn createDockerfile
186+
inputDir = file("src/main/resources")
187+
images.add('docgen-base:latest')
169188
}
189+
190+
docker {
191+
springBootApplication {
192+
baseImage = 'docgen-base:latest'
193+
ports = [9090, 8080]
194+
images = ['docgen:latest']
195+
jvmArgs = ['-Dspring.profiles.active=production', '-Xmx2048m']
196+
}
197+
}

conf/application.conf

Lines changed: 0 additions & 19 deletions
This file was deleted.

conf/application.test.conf

Lines changed: 0 additions & 7 deletions
This file was deleted.

conf/logback.xml

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Use Markdown Architectural Decision Records
2+
3+
## Context and Problem Statement
4+
5+
We want to record architectural decisions made in this project.
6+
Which format and structure should these records follow?
7+
8+
## Considered Options
9+
10+
* [MADR](https://adr.github.io/madr/) 2.1.2 The Markdown Architectural Decision Records
11+
* [Michael Nygard's template](http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions) The first incarnation of the term "ADR"
12+
* [Sustainable Architectural Decisions](https://www.infoq.com/articles/sustainable-architectural-design-decisions) The Y-Statements
13+
* Other templates listed at <https://github.com/joelparkerhenderson/architecture_decision_record>
14+
* Formless No conventions for file format and structure
15+
16+
## Decision Outcome
17+
18+
Chosen option: "MADR 2.1.2", because
19+
20+
* Implicit assumptions should be made explicit.
21+
Design documentation is important to enable people understanding the decisions later on.
22+
See also [A rational design process: How and why to fake it](https://doi.org/10.1109/TSE.1986.6312940).
23+
* The MADR format is lean and fits our development style.
24+
* The MADR structure is comprehensible and facilitates usage & maintenance.
25+
* The MADR project is vivid.
26+
* Version 2.1.2 is the latest one available when starting to document ADRs.
27+
28+
<!-- markdownlint-disable-file MD013 -->
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# {short title of solved problem and solution}
2+
3+
* Status: accepted
4+
* Deciders: Sergio Sacristán
5+
* Date: 2021-12-22
6+
7+
## Context and Problem Statement
8+
9+
In order to evolve DocGen service to migrate here the LevaDoc feature, initially implemented
10+
in the SharedLib, we need to improve LevaDoc architecture to make it more maintainable.
11+
12+
## Decision Drivers
13+
14+
* Maintainability: speed up the development with better modularization of the code
15+
* Testability.
16+
* Extensibility.
17+
* Performance: this is not a big problem. As the API will be executed from a batch, we don't care if the response takes 2 seconds more or less
18+
19+
## Considered Options
20+
21+
* jooby with Dagger and Groovy: poor documentation and examples
22+
* jooby with SpringFramework and Groovy: poor documentation and examples
23+
* SpringFramework and Groovy
24+
25+
## Decision Outcome
26+
27+
Chosen option: "SpringFramework", because:
28+
- There's a lot of documentation and examples. Easy to solve problems
29+
- There's a bigger community of users: easy to involve new developers
30+
- Better integration with more frameworks, means also better extensibility
31+
32+
### Negative Consequences
33+
34+
* We should do a big refactor
35+
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# {short title of solved problem and solution}
2+
3+
* Status: {proposed | rejected | accepted | deprecated | … | superseded by [ADR-0005](0005-example.md)} <!-- optional -->
4+
* Deciders: {list everyone involved in the decision} <!-- optional -->
5+
* Date: {YYYY-MM-DD when the decision was last updated} <!-- optional -->
6+
7+
Technical Story: {description | ticket/issue URL} <!-- optional -->
8+
9+
## Context and Problem Statement
10+
11+
{Describe the context and problem statement, e.g., in free form using two to three sentences. You may want to articulate the problem in form of a question.}
12+
13+
## Decision Drivers <!-- optional -->
14+
15+
* {driver 1, e.g., a force, facing concern, …}
16+
* {driver 2, e.g., a force, facing concern, …}
17+
*<!-- numbers of drivers can vary -->
18+
19+
## Considered Options
20+
21+
* {option 1}
22+
* {option 2}
23+
* {option 3}
24+
*<!-- numbers of options can vary -->
25+
26+
## Decision Outcome
27+
28+
Chosen option: "{option 1}", because {justification. e.g., only option, which meets k.o. criterion decision driver | which resolves force {force} | … | comes out best (see below)}.
29+
30+
### Positive Consequences <!-- optional -->
31+
32+
* {e.g., improvement of quality attribute satisfaction, follow-up decisions required, …}
33+
*
34+
35+
### Negative Consequences <!-- optional -->
36+
37+
* {e.g., compromising quality attribute, follow-up decisions required, …}
38+
*
39+
40+
## Pros and Cons of the Options <!-- optional -->
41+
42+
### {option 1}
43+
44+
{example | description | pointer to more information | …} <!-- optional -->
45+
46+
* Good, because {argument a}
47+
* Good, because {argument b}
48+
* Bad, because {argument c}
49+
*<!-- numbers of pros and cons can vary -->
50+
51+
### {option 2}
52+
53+
{example | description | pointer to more information | …} <!-- optional -->
54+
55+
* Good, because {argument a}
56+
* Good, because {argument b}
57+
* Bad, because {argument c}
58+
*<!-- numbers of pros and cons can vary -->
59+
60+
### {option 3}
61+
62+
{example | description | pointer to more information | …} <!-- optional -->
63+
64+
* Good, because {argument a}
65+
* Good, because {argument b}
66+
* Bad, because {argument c}
67+
*<!-- numbers of pros and cons can vary -->
68+
69+
## Links <!-- optional -->
70+
71+
* {Link type} {Link to ADR} <!-- example: Refined by [ADR-0005](0005-example.md) -->
72+
*<!-- numbers of links can vary -->
73+
74+
<!-- markdownlint-disable-file MD013 -->
75+
https://examples.javacodegeeks.com/spring-boot-mockmvc-tutorial/
76+
77+
When unit testing a service, the standard unit is usually the service class, simple as that. The test will mock out the layer underneath in this case the DAO/DAL layer and verify the interactions on it. Exact same thing for the DAO layer mocking out the interactions with the database (HibernateTemplate in this example) and verifying the interactions with that.
78+
79+
This is a valid approach, but it leads to brittle tests adding or removing a layer almost always means rewriting the tests entirely. This happens because the tests rely on the exact structure of the layers, and a change to that means a change to the tests.
80+
To avoid this kind of inflexibility, we can grow the scope of the unit test by changing the definition of the unit we can look at a persistent operation as a unit, from the Service Layer through the DAO and all the way day to the raw persistence whatever that is. Now, the unit test will consume the API of the Service Layer and will have the raw persistence mocked out in this case, the HibernateTemplate:

0 commit comments

Comments
 (0)