diff --git a/.gitignore b/.gitignore
index f3fa30f3e3..60c38ed8f5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,3 +31,5 @@ spring-openid/src/main/resources/application.properties
.recommenders/
/spring-hibernate4/nbproject/
spring-security-openid/src/main/resources/application.properties
+
+spring-all/*.log
diff --git a/.travis.yml b/.travis.yml
index bcff16f5f1..fdd741154b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,6 @@
language: java
-install: travis_wait 60 mvn -q test
+install: travis_wait 60 mvn -q test -fae
before_script:
- echo "MAVEN_OPTS='-Xmx2048M -Xss128M -XX:MaxPermSize=2048M -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-UseGCOverheadLimit'" > ~/.mavenrc
diff --git a/JGit/pom.xml b/JGit/pom.xml
index 93c49edb92..b902cb87a5 100644
--- a/JGit/pom.xml
+++ b/JGit/pom.xml
@@ -6,6 +6,13 @@
1.0-SNAPSHOTjarhttp://maven.apache.org
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
UTF-81.8
diff --git a/Twitter4J/pom.xml b/Twitter4J/pom.xml
index 7e41d8de76..492db6b43e 100644
--- a/Twitter4J/pom.xml
+++ b/Twitter4J/pom.xml
@@ -8,6 +8,12 @@
Twitter4Jhttp://maven.apache.org
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
UTF-8UTF-8
diff --git a/algorithms/README.md b/algorithms/README.md
index 00e0646f47..f1e12ee243 100644
--- a/algorithms/README.md
+++ b/algorithms/README.md
@@ -5,3 +5,4 @@
- [Ant Colony Optimization](http://www.baeldung.com/java-ant-colony-optimization)
- [Validating Input With Finite Automata in Java](http://www.baeldung.com/finite-automata-java)
- [Introduction to Jenetics Library](http://www.baeldung.com/jenetics)
+- [Check If a Number Is Prime in Java](http://www.baeldung.com/java-prime-numbers)
diff --git a/algorithms/pom.xml b/algorithms/pom.xml
index 884c804d13..6aa347eb20 100644
--- a/algorithms/pom.xml
+++ b/algorithms/pom.xml
@@ -13,6 +13,12 @@
3.6.1
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
org.apache.commons
@@ -39,7 +45,6 @@
- install
@@ -56,6 +61,17 @@
exec-maven-plugin${exec-maven-plugin.version}
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ **/*LongRunningUnitTest.java
+ **/*IntegrationTest.java
+
+
+
diff --git a/algorithms/src/test/java/algorithms/AntColonyOptimizationLongRunningUnitTest.java b/algorithms/src/test/java/algorithms/AntColonyOptimizationLongRunningUnitTest.java
new file mode 100644
index 0000000000..b0218ae23e
--- /dev/null
+++ b/algorithms/src/test/java/algorithms/AntColonyOptimizationLongRunningUnitTest.java
@@ -0,0 +1,22 @@
+package algorithms;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.baeldung.algorithms.ga.ant_colony.AntColonyOptimization;
+
+public class AntColonyOptimizationLongRunningUnitTest {
+
+ @Test
+ public void testGenerateRandomMatrix() {
+ AntColonyOptimization antTSP = new AntColonyOptimization(5);
+ Assert.assertNotNull(antTSP.generateRandomMatrix(5));
+ }
+
+ @Test
+ public void testStartAntOptimization() {
+ AntColonyOptimization antTSP = new AntColonyOptimization(5);
+ Assert.assertNotNull(antTSP.solve());
+ }
+
+}
diff --git a/algorithms/src/test/java/algorithms/AntColonyOptimizationTest.java b/algorithms/src/test/java/algorithms/AntColonyOptimizationTest.java
deleted file mode 100644
index a11f5db698..0000000000
--- a/algorithms/src/test/java/algorithms/AntColonyOptimizationTest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package algorithms;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import com.baeldung.algorithms.ga.ant_colony.AntColonyOptimization;
-
-public class AntColonyOptimizationTest {
-
- @Test
- public void testGenerateRandomMatrix() {
- AntColonyOptimization antTSP = new AntColonyOptimization(5);
- Assert.assertNotNull(antTSP.generateRandomMatrix(5));
- }
-
- @Test
- public void testStartAntOptimization() {
- AntColonyOptimization antTSP = new AntColonyOptimization(5);
- Assert.assertNotNull(antTSP.solve());
- }
-
-}
diff --git a/algorithms/src/test/java/algorithms/BinaryGeneticAlgorithmLongRunningUnitTest.java b/algorithms/src/test/java/algorithms/BinaryGeneticAlgorithmLongRunningUnitTest.java
new file mode 100644
index 0000000000..fa8ecdee77
--- /dev/null
+++ b/algorithms/src/test/java/algorithms/BinaryGeneticAlgorithmLongRunningUnitTest.java
@@ -0,0 +1,16 @@
+package algorithms;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.baeldung.algorithms.ga.binary.SimpleGeneticAlgorithm;
+
+public class BinaryGeneticAlgorithmLongRunningUnitTest {
+
+ @Test
+ public void testGA() {
+ SimpleGeneticAlgorithm ga = new SimpleGeneticAlgorithm();
+ Assert.assertTrue(ga.runAlgorithm(50, "1011000100000100010000100000100111001000000100000100000000001111"));
+ }
+
+}
diff --git a/algorithms/src/test/java/algorithms/BinaryGeneticAlgorithmUnitTest.java b/algorithms/src/test/java/algorithms/BinaryGeneticAlgorithmUnitTest.java
deleted file mode 100644
index 2ba516d310..0000000000
--- a/algorithms/src/test/java/algorithms/BinaryGeneticAlgorithmUnitTest.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package algorithms;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import com.baeldung.algorithms.ga.binary.SimpleGeneticAlgorithm;
-
-public class BinaryGeneticAlgorithmUnitTest {
-
- @Test
- public void testGA() {
- SimpleGeneticAlgorithm ga = new SimpleGeneticAlgorithm();
- Assert.assertTrue(ga.runAlgorithm(50, "1011000100000100010000100000100111001000000100000100000000001111"));
- }
-
-}
diff --git a/algorithms/src/test/java/algorithms/DijkstraAlgorithmTest.java b/algorithms/src/test/java/algorithms/DijkstraAlgorithmLongRunningUnitTest.java
similarity index 74%
rename from algorithms/src/test/java/algorithms/DijkstraAlgorithmTest.java
rename to algorithms/src/test/java/algorithms/DijkstraAlgorithmLongRunningUnitTest.java
index 4d8cebed25..68386278fc 100644
--- a/algorithms/src/test/java/algorithms/DijkstraAlgorithmTest.java
+++ b/algorithms/src/test/java/algorithms/DijkstraAlgorithmLongRunningUnitTest.java
@@ -1,76 +1,86 @@
-package algorithms;
-
-import org.junit.Test;
-
-import com.baeldung.algorithms.ga.dijkstra.Dijkstra;
-import com.baeldung.algorithms.ga.dijkstra.Graph;
-import com.baeldung.algorithms.ga.dijkstra.Node;
-
-import java.util.Arrays;
-import java.util.List;
-
-import static org.junit.Assert.assertTrue;
-
-public class DijkstraAlgorithmTest {
-
- @Test
- public void whenSPPSolved_thenCorrect() {
-
- Node nodeA = new Node("A");
- Node nodeB = new Node("B");
- Node nodeC = new Node("C");
- Node nodeD = new Node("D");
- Node nodeE = new Node("E");
- Node nodeF = new Node("F");
-
- nodeA.addDestination(nodeB, 10);
- nodeA.addDestination(nodeC, 15);
-
- nodeB.addDestination(nodeD, 12);
- nodeB.addDestination(nodeF, 15);
-
- nodeC.addDestination(nodeE, 10);
-
- nodeD.addDestination(nodeE, 2);
- nodeD.addDestination(nodeF, 1);
-
- nodeF.addDestination(nodeE, 5);
-
- Graph graph = new Graph();
-
- graph.addNode(nodeA);
- graph.addNode(nodeB);
- graph.addNode(nodeC);
- graph.addNode(nodeD);
- graph.addNode(nodeE);
- graph.addNode(nodeF);
-
- graph = Dijkstra.calculateShortestPathFromSource(graph, nodeA);
-
- List shortestPathForNodeB = Arrays.asList(nodeA);
- List shortestPathForNodeC = Arrays.asList(nodeA);
- List shortestPathForNodeD = Arrays.asList(nodeA, nodeB);
- List shortestPathForNodeE = Arrays.asList(nodeA, nodeB, nodeD);
- List shortestPathForNodeF = Arrays.asList(nodeA, nodeB, nodeD);
-
- for (Node node : graph.getNodes()) {
- switch (node.getName()) {
- case "B":
- assertTrue(node.getShortestPath().equals(shortestPathForNodeB));
- break;
- case "C":
- assertTrue(node.getShortestPath().equals(shortestPathForNodeC));
- break;
- case "D":
- assertTrue(node.getShortestPath().equals(shortestPathForNodeD));
- break;
- case "E":
- assertTrue(node.getShortestPath().equals(shortestPathForNodeE));
- break;
- case "F":
- assertTrue(node.getShortestPath().equals(shortestPathForNodeF));
- break;
- }
- }
- }
-}
+package algorithms;
+
+import org.junit.Test;
+
+import com.baeldung.algorithms.ga.dijkstra.Dijkstra;
+import com.baeldung.algorithms.ga.dijkstra.Graph;
+import com.baeldung.algorithms.ga.dijkstra.Node;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertTrue;
+
+public class DijkstraAlgorithmLongRunningUnitTest {
+
+ @Test
+ public void whenSPPSolved_thenCorrect() {
+
+ Node nodeA = new Node("A");
+ Node nodeB = new Node("B");
+ Node nodeC = new Node("C");
+ Node nodeD = new Node("D");
+ Node nodeE = new Node("E");
+ Node nodeF = new Node("F");
+
+ nodeA.addDestination(nodeB, 10);
+ nodeA.addDestination(nodeC, 15);
+
+ nodeB.addDestination(nodeD, 12);
+ nodeB.addDestination(nodeF, 15);
+
+ nodeC.addDestination(nodeE, 10);
+
+ nodeD.addDestination(nodeE, 2);
+ nodeD.addDestination(nodeF, 1);
+
+ nodeF.addDestination(nodeE, 5);
+
+ Graph graph = new Graph();
+
+ graph.addNode(nodeA);
+ graph.addNode(nodeB);
+ graph.addNode(nodeC);
+ graph.addNode(nodeD);
+ graph.addNode(nodeE);
+ graph.addNode(nodeF);
+
+ graph = Dijkstra.calculateShortestPathFromSource(graph, nodeA);
+
+ List shortestPathForNodeB = Arrays.asList(nodeA);
+ List shortestPathForNodeC = Arrays.asList(nodeA);
+ List shortestPathForNodeD = Arrays.asList(nodeA, nodeB);
+ List shortestPathForNodeE = Arrays.asList(nodeA, nodeB, nodeD);
+ List shortestPathForNodeF = Arrays.asList(nodeA, nodeB, nodeD);
+
+ for (Node node : graph.getNodes()) {
+ switch (node.getName()) {
+ case "B":
+ assertTrue(node
+ .getShortestPath()
+ .equals(shortestPathForNodeB));
+ break;
+ case "C":
+ assertTrue(node
+ .getShortestPath()
+ .equals(shortestPathForNodeC));
+ break;
+ case "D":
+ assertTrue(node
+ .getShortestPath()
+ .equals(shortestPathForNodeD));
+ break;
+ case "E":
+ assertTrue(node
+ .getShortestPath()
+ .equals(shortestPathForNodeE));
+ break;
+ case "F":
+ assertTrue(node
+ .getShortestPath()
+ .equals(shortestPathForNodeF));
+ break;
+ }
+ }
+ }
+}
diff --git a/algorithms/src/test/java/algorithms/RtFiniteStateMachineTest.java b/algorithms/src/test/java/algorithms/RtFiniteStateMachineLongRunningUnitTest.java
similarity index 72%
rename from algorithms/src/test/java/algorithms/RtFiniteStateMachineTest.java
rename to algorithms/src/test/java/algorithms/RtFiniteStateMachineLongRunningUnitTest.java
index 089b38ec3f..c6800e9a64 100644
--- a/algorithms/src/test/java/algorithms/RtFiniteStateMachineTest.java
+++ b/algorithms/src/test/java/algorithms/RtFiniteStateMachineLongRunningUnitTest.java
@@ -1,38 +1,37 @@
package algorithms;
-import static org.junit.Assert.*;
-import org.junit.Test;
import com.baeldung.automata.*;
+import org.junit.Test;
-/**
- * Tests for {@link RtFiniteStateMachine}
- */
-public final class RtFiniteStateMachineTest {
+import static org.junit.Assert.assertTrue;
+
+public final class RtFiniteStateMachineLongRunningUnitTest {
@Test
public void acceptsSimplePair() {
String json = "{\"key\":\"value\"}";
FiniteStateMachine machine = this.buildJsonStateMachine();
- for (int i=0;iapache-bval
0.0.1-SNAPSHOT
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+ org.apache.bval
diff --git a/apache-cxf/cxf-aegis/src/test/java/com/baeldung/cxf/aegis/BaeldungTest.java b/apache-cxf/cxf-aegis/src/test/java/com/baeldung/cxf/aegis/BaeldungTest.java
index 559de037a9..935b283cb4 100644
--- a/apache-cxf/cxf-aegis/src/test/java/com/baeldung/cxf/aegis/BaeldungTest.java
+++ b/apache-cxf/cxf-aegis/src/test/java/com/baeldung/cxf/aegis/BaeldungTest.java
@@ -3,8 +3,10 @@ package com.baeldung.cxf.aegis;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import org.junit.After;
import org.junit.Test;
+import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.lang.reflect.Type;
@@ -90,4 +92,12 @@ public class BaeldungTest {
xmlReader.close();
return courseRepo;
}
+
+ @After
+ public void cleanup(){
+ File testFile = new File(fileName);
+ if (testFile.exists()) {
+ testFile.delete();
+ }
+ }
}
\ No newline at end of file
diff --git a/apache-cxf/cxf-jaxrs-implementation/pom.xml b/apache-cxf/cxf-jaxrs-implementation/pom.xml
index c3095be5a5..61a5132f19 100644
--- a/apache-cxf/cxf-jaxrs-implementation/pom.xml
+++ b/apache-cxf/cxf-jaxrs-implementation/pom.xml
@@ -54,6 +54,12 @@
org.apache.httpcomponentshttpclient${httpclient.version}
+
+
+ commons-logging
+ commons-logging
+
+
diff --git a/apache-cxf/cxf-spring/pom.xml b/apache-cxf/cxf-spring/pom.xml
index 79a7650ced..dffcc3ee1b 100644
--- a/apache-cxf/cxf-spring/pom.xml
+++ b/apache-cxf/cxf-spring/pom.xml
@@ -24,6 +24,12 @@
org.springframeworkspring-context${spring.version}
+
+
+ commons-logging
+ commons-logging
+
+ org.springframework
diff --git a/apache-cxf/pom.xml b/apache-cxf/pom.xml
index 6849452908..b2ae2dab3e 100644
--- a/apache-cxf/pom.xml
+++ b/apache-cxf/pom.xml
@@ -6,6 +6,12 @@
0.0.1-SNAPSHOTpom
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
cxf-introductioncxf-spring
diff --git a/apache-fop/pom.xml b/apache-fop/pom.xml
index 6075c23d21..2a610d5675 100644
--- a/apache-fop/pom.xml
+++ b/apache-fop/pom.xml
@@ -7,6 +7,12 @@
apache-fop
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
@@ -28,11 +34,6 @@
${org.slf4j.version}
-
- org.slf4j
- log4j-over-slf4j
- ${org.slf4j.version}
-
@@ -78,6 +79,10 @@
org.apache.avalon.frameworkavalon-framework-impl
+
+ commons-logging
+ commons-logging
+
@@ -90,6 +95,12 @@
avalon-frameworkavalon-framework-impl${avalon-framework.version}
+
+
+ commons-logging
+ commons-logging
+
+
diff --git a/apache-poi/pom.xml b/apache-poi/pom.xml
index d8a2cc72e0..127f65bd5f 100644
--- a/apache-poi/pom.xml
+++ b/apache-poi/pom.xml
@@ -5,6 +5,12 @@
apache-poi0.0.1-SNAPSHOT
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
3.6.04.12
@@ -42,6 +48,12 @@
org.jxlsjxls-jexcel${jexcel.version}
+
+
+ commons-logging
+ commons-logging
+
+
diff --git a/apache-poi/src/test/java/com/baeldung/jexcel/JExcelTest.java b/apache-poi/src/test/java/com/baeldung/jexcel/JExcelTest.java
index 8ee465be34..72272913d5 100644
--- a/apache-poi/src/test/java/com/baeldung/jexcel/JExcelTest.java
+++ b/apache-poi/src/test/java/com/baeldung/jexcel/JExcelTest.java
@@ -19,6 +19,7 @@ import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.junit.Before;
+import org.junit.After;
public class JExcelTest {
@@ -53,4 +54,11 @@ public class JExcelTest {
.get(1));
}
+ @After
+ public void cleanup(){
+ File testFile = new File(fileLocation);
+ if (testFile.exists()) {
+ testFile.delete();
+ }
+ }
}
\ No newline at end of file
diff --git a/apache-poi/src/test/java/com/baeldung/poi/excel/ExcelTest.java b/apache-poi/src/test/java/com/baeldung/poi/excel/ExcelTest.java
index 34fa64dd94..ad36f46f02 100644
--- a/apache-poi/src/test/java/com/baeldung/poi/excel/ExcelTest.java
+++ b/apache-poi/src/test/java/com/baeldung/poi/excel/ExcelTest.java
@@ -16,6 +16,7 @@ import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.junit.Before;
+import org.junit.After;
public class ExcelTest {
@@ -50,4 +51,11 @@ public class ExcelTest {
.get(1));
}
+ @After
+ public void cleanup(){
+ File testFile = new File(fileLocation);
+ if (testFile.exists()) {
+ testFile.delete();
+ }
+ }
}
\ No newline at end of file
diff --git a/apache-poi/temp.xls b/apache-poi/temp.xls
deleted file mode 100644
index 1fad76d88d..0000000000
Binary files a/apache-poi/temp.xls and /dev/null differ
diff --git a/apache-poi/temp.xlsx b/apache-poi/temp.xlsx
deleted file mode 100644
index 431a8a662c..0000000000
Binary files a/apache-poi/temp.xlsx and /dev/null differ
diff --git a/apache-solrj/pom.xml b/apache-solrj/pom.xml
index 74daeae55c..8bed42dccc 100644
--- a/apache-solrj/pom.xml
+++ b/apache-solrj/pom.xml
@@ -7,6 +7,12 @@
jarapache-solrj
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
4.122.19.1
diff --git a/apache-thrift/pom.xml b/apache-thrift/pom.xml
index 66cfb2bb41..a1a222887d 100644
--- a/apache-thrift/pom.xml
+++ b/apache-thrift/pom.xml
@@ -6,6 +6,12 @@
0.0.1-SNAPSHOTpom
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
1.84.12
@@ -19,6 +25,12 @@
org.apache.thriftlibthrift${thrift.version}
+
+
+ commons-logging
+ commons-logging
+
+
diff --git a/apache-velocity/pom.xml b/apache-velocity/pom.xml
index 08f0e96a58..d4b773abba 100644
--- a/apache-velocity/pom.xml
+++ b/apache-velocity/pom.xml
@@ -9,6 +9,12 @@
warapache-velocity
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
1.81.2
@@ -38,7 +44,7 @@
org.apache.velocityvelocity-tools
- ${velocity-tools-version}
+ ${velocity-tools-version}org.slf4j
@@ -55,6 +61,12 @@
httpclient${org.apache.httpcomponents.version}test
+
+
+ commons-logging
+ commons-logging
+
+
diff --git a/aspectj/README.md b/aspectj/README.md
deleted file mode 100644
index 71724e76b6..0000000000
--- a/aspectj/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-### Relevant Articles:
-- [Intro to AspectJ](http://www.baeldung.com/aspectj)
-- [Spring Performance Logging](http://www.baeldung.com/spring-performance-logging)
diff --git a/aspectj/pom.xml b/aspectj/pom.xml
deleted file mode 100644
index cbc98dac81..0000000000
--- a/aspectj/pom.xml
+++ /dev/null
@@ -1,138 +0,0 @@
-
- 4.0.0
- com.baeldung
- aspectj
- 0.0.1-SNAPSHOT
- aspectj
-
-
-
- org.aspectj
- aspectjrt
- ${aspectj.version}
-
-
-
- org.aspectj
- aspectjweaver
- ${aspectj.version}
-
-
-
-
- org.slf4j
- slf4j-api
- ${org.slf4j.version}
-
-
-
- ch.qos.logback
- logback-classic
- ${logback.version}
-
-
-
- ch.qos.logback
- logback-core
- ${logback.version}
-
-
-
-
- junit
- junit
- ${junit.version}
-
-
-
- org.springframework
- spring-context
- 4.3.4.RELEASE
-
-
- org.springframework
- spring-beans
- 4.3.4.RELEASE
-
-
- org.springframework
- spring-core
- 4.3.4.RELEASE
-
-
- cglib
- cglib
- 3.2.4
-
-
- org.springframework
- spring-aop
- 4.3.4.RELEASE
-
-
-
-
- aspectj
-
-
- src/main/resources
- true
-
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- ${maven-compiler-plugin.version}
-
- ${source.version}
- ${source.version}
-
-
-
-
-
- org.codehaus.mojo
- aspectj-maven-plugin
- 1.7
-
- ${source.version}
- ${source.version}
- ${source.version}
- true
- true
- ignore
- ${project.build.sourceEncoding}
-
-
-
-
-
-
- compile
- test-compile
-
-
-
-
-
-
-
-
-
-
- 1.8
- UTF-8
- 1.8.9
- 1.7.21
- 1.1.7
- 3.6.0
- 4.12
-
-
-
\ No newline at end of file
diff --git a/assertj/README.md b/assertj/README.md
deleted file mode 100644
index 86eff05057..0000000000
--- a/assertj/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-### Relevant Articles:
-- [AssertJ’s Java 8 Features](http://www.baeldung.com/assertJ-java-8-features)
-- [AssertJ for Guava](http://www.baeldung.com/assertJ-for-guava)
diff --git a/assertj/pom.xml b/assertj/pom.xml
deleted file mode 100644
index 032f33c89d..0000000000
--- a/assertj/pom.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
- 4.0.0
-
- com.baeldung
- assertj
- 1.0.0-SNAPSHOT
-
-
-
-
- com.google.guava
- guava
- ${guava.version}
-
-
- org.assertj
- assertj-guava
- 3.0.0
-
-
-
- junit
- junit
- ${junit.version}
- test
-
-
- org.assertj
- assertj-core
- ${assertj-core.version}
- test
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- ${maven-compiler-plugin.version}
-
- 1.8
- 1.8
-
-
-
-
-
-
- 19.0
- 3.1.0
- 4.12
- 3.6.1
-
- 3.6.0
-
-
-
\ No newline at end of file
diff --git a/autovalue/pom.xml b/autovalue/pom.xml
index 32616dc8bc..4e7c01004c 100644
--- a/autovalue/pom.xml
+++ b/autovalue/pom.xml
@@ -6,6 +6,12 @@
1.0autovalue
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
diff --git a/aws/pom.xml b/aws/pom.xml
index 681b76cfd4..10a2835763 100644
--- a/aws/pom.xml
+++ b/aws/pom.xml
@@ -7,6 +7,12 @@
jaraws
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
2.51.3.0
@@ -19,12 +25,24 @@
com.amazonawsaws-lambda-java-core${aws-lambda-java-core.version}
+
+
+ commons-logging
+ commons-logging
+
+ com.amazonawsaws-lambda-java-events${aws-lambda-java-events.version}
+
+
+ commons-logging
+ commons-logging
+
+
diff --git a/cdi/pom.xml b/cdi/pom.xml
index e5aaeb2c7b..0807d61ce9 100644
--- a/cdi/pom.xml
+++ b/cdi/pom.xml
@@ -7,11 +7,17 @@
cdi1.0-SNAPSHOT
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
org.springframeworkspring-core
- ${spring.version}
+ ${spring.version}org.springframework
diff --git a/core-java-9/README.md b/core-java-9/README.md
index a6cda8e883..3e82ffe14b 100644
--- a/core-java-9/README.md
+++ b/core-java-9/README.md
@@ -12,3 +12,4 @@
- [Spring Security – Redirect to the Previous URL After Login](http://www.baeldung.com/spring-security-redirect-login)
- [Java 9 Process API Improvements](http://www.baeldung.com/java-9-process-api)
- [Introduction to Java 9 StackWalking API](http://www.baeldung.com/java-9-stackwalking-api)
+- [Introduction to Project Jigsaw](http://www.baeldung.com/project-jigsaw-java-modularity)
diff --git a/core-java/README.md b/core-java/README.md
index 45695f13f6..ead65ab166 100644
--- a/core-java/README.md
+++ b/core-java/README.md
@@ -92,3 +92,12 @@
- [Removing all nulls from a List in Java](http://www.baeldung.com/java-remove-nulls-from-list)
- [Removing all duplicates from a List in Java](http://www.baeldung.com/java-remove-duplicates-from-list)
- [An Introduction to ThreadLocal in Java](http://www.baeldung.com/java-threadlocal)
+- [Using Math.pow in Java](http://www.baeldung.com/java-math-pow)
+- [Converting Strings to Enums in Java](http://www.baeldung.com/java-string-to-enum)
+- [Flattening Nested Collections in Java](http://www.baeldung.com/java-flatten-nested-collections)
+- [Quick Guide to the Java StringTokenizer](http://www.baeldung.com/java-stringtokenizer)
+- [JVM Log Forging](http://www.baeldung.com/jvm-log-forging)
+- [Guide to sun.misc.Unsafe](http://www.baeldung.com/java-unsafe)
+- [HashSet and TreeSet Comparison](http://www.baeldung.com/java-hashset-vs-treeset)
+- [How to Perform a Simple HTTP Request in Java](http://www.baeldung.com/java-http-request)
+- [Call Methods at Runtime Using Java Reflection](http://www.baeldung.com/java-method-reflection)
diff --git a/core-java/pom.xml b/core-java/pom.xml
index d2fa1cdd2e..597f448c10 100644
--- a/core-java/pom.xml
+++ b/core-java/pom.xml
@@ -8,6 +8,12 @@
core-java
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
@@ -92,17 +98,19 @@
${org.slf4j.version}
-
- org.slf4j
- log4j-over-slf4j
- ${org.slf4j.version}
- org.projectlomboklombok${lombok.version}provided
+
+
+
+ mysql
+ mysql-connector-java
+ ${mysql.version}
+
@@ -140,13 +148,6 @@
test
-
- org.testng
- testng
- ${testng.version}
- test
-
-
org.mockitomockito-core
@@ -170,13 +171,30 @@
org.javamoneymoneta1.1
-
+
+
+ org.owasp.esapi
+ esapi
+ 2.1.0.1
+
+
+ commons-logging
+ commons-logging
+
+
+
-
- org.owasp.esapi
- esapi
- 2.1.0.1
-
+
+ org.owasp.esapi
+ esapi
+ 2.1.0.1
+
+
+ commons-logging
+ commons-logging
+
+
+
@@ -190,7 +208,6 @@
-
org.apache.maven.pluginsmaven-compiler-plugin
@@ -200,7 +217,6 @@
1.8
-
org.apache.maven.pluginsmaven-surefire-plugin
@@ -209,11 +225,11 @@
**/*IntegrationTest.java**/*LongRunningUnitTest.java**/*ManualTest.java
+ **/JdbcTest.javatrue
-
org.apache.maven.pluginsmaven-dependency-plugin
@@ -244,7 +260,6 @@
-
org.apache.maven.pluginsmaven-assembly-plugin
@@ -268,7 +283,6 @@
-
org.apache.maven.pluginsmaven-shade-plugin
@@ -289,7 +303,6 @@
-
com.joliraonejar-maven-plugin
@@ -306,7 +319,6 @@
-
org.springframework.bootspring-boot-maven-plugin
@@ -322,7 +334,6 @@
-
@@ -369,6 +380,9 @@
1.7.211.1.7
+
+
+ 6.0.621.0
@@ -387,7 +401,6 @@
1.34.121.10.19
- 6.103.6.11.7.0
diff --git a/core-java/src/main/java/com/baeldung/concurrent/phaser/LongRunningAction.java b/core-java/src/main/java/com/baeldung/concurrent/phaser/LongRunningAction.java
new file mode 100644
index 0000000000..dd1487b5cb
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/concurrent/phaser/LongRunningAction.java
@@ -0,0 +1,27 @@
+package com.baeldung.concurrent.phaser;
+
+import java.util.concurrent.Phaser;
+
+class LongRunningAction implements Runnable {
+ private String threadName;
+ private Phaser ph;
+
+ LongRunningAction(String threadName, Phaser ph) {
+ this.threadName = threadName;
+ this.ph = ph;
+ ph.register();
+ }
+
+ @Override
+ public void run() {
+ System.out.println("This is phase " + ph.getPhase());
+ System.out.println("Thread " + threadName + " before long running action");
+ ph.arriveAndAwaitAdvance();
+ try {
+ Thread.sleep(20);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ ph.arriveAndDeregister();
+ }
+}
\ No newline at end of file
diff --git a/core-java/src/main/java/com/baeldung/concurrent/skiplist/Event.java b/core-java/src/main/java/com/baeldung/concurrent/skiplist/Event.java
new file mode 100644
index 0000000000..ce1f57bb93
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/concurrent/skiplist/Event.java
@@ -0,0 +1,21 @@
+package com.baeldung.concurrent.skiplist;
+
+import java.time.ZonedDateTime;
+
+public class Event {
+ private final ZonedDateTime eventTime;
+ private final String content;
+
+ public Event(ZonedDateTime eventTime, String content) {
+ this.eventTime = eventTime;
+ this.content = content;
+ }
+
+ public ZonedDateTime getEventTime() {
+ return eventTime;
+ }
+
+ public String getContent() {
+ return content;
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/concurrent/skiplist/EventWindowSort.java b/core-java/src/main/java/com/baeldung/concurrent/skiplist/EventWindowSort.java
new file mode 100644
index 0000000000..3aca6b0147
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/concurrent/skiplist/EventWindowSort.java
@@ -0,0 +1,29 @@
+package com.baeldung.concurrent.skiplist;
+
+import java.time.ZonedDateTime;
+import java.util.Comparator;
+import java.util.concurrent.ConcurrentNavigableMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+
+public class EventWindowSort {
+ private final ConcurrentSkipListMap events
+ = new ConcurrentSkipListMap<>(Comparator.comparingLong(value -> value.toInstant().toEpochMilli()));
+
+ public void acceptEvent(Event event) {
+ events.put(event.getEventTime(), event.getContent());
+ }
+
+ public ConcurrentNavigableMap getEventsFromLastMinute() {
+ return events.tailMap(ZonedDateTime
+ .now()
+ .minusMinutes(1));
+ }
+
+ public ConcurrentNavigableMap getEventsOlderThatOneMinute() {
+ return events.headMap(ZonedDateTime
+ .now()
+ .minusMinutes(1));
+ }
+
+}
+
diff --git a/core-java/src/main/java/com/baeldung/concurrent/sleepwait/ThreadA.java b/core-java/src/main/java/com/baeldung/concurrent/sleepwait/ThreadA.java
new file mode 100644
index 0000000000..6bb055d360
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/concurrent/sleepwait/ThreadA.java
@@ -0,0 +1,27 @@
+package com.baeldung.concurrent.sleepwait;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/***
+ * Example of waking up a waiting thread
+ */
+public class ThreadA {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ThreadA.class);
+
+ private static final ThreadB b = new ThreadB();
+
+ public static void main(String... args) throws InterruptedException {
+ b.start();
+
+ synchronized (b) {
+ while (b.sum == 0) {
+ LOG.debug("Waiting for ThreadB to complete...");
+ b.wait();
+ }
+
+ LOG.debug("ThreadB has completed. Sum from that thread is: " + b.sum);
+ }
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/concurrent/sleepwait/ThreadB.java b/core-java/src/main/java/com/baeldung/concurrent/sleepwait/ThreadB.java
new file mode 100644
index 0000000000..1fc180a5de
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/concurrent/sleepwait/ThreadB.java
@@ -0,0 +1,20 @@
+package com.baeldung.concurrent.sleepwait;
+
+/***
+ * Example of waking up a waiting thread
+ */
+class ThreadB extends Thread {
+ int sum;
+
+ @Override
+ public void run() {
+ synchronized (this) {
+ int i = 0;
+ while (i < 100000) {
+ sum += i;
+ i++;
+ }
+ notify();
+ }
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/concurrent/sleepwait/WaitSleepExample.java b/core-java/src/main/java/com/baeldung/concurrent/sleepwait/WaitSleepExample.java
new file mode 100644
index 0000000000..0311d9b0b2
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/concurrent/sleepwait/WaitSleepExample.java
@@ -0,0 +1,29 @@
+package com.baeldung.concurrent.sleepwait;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/***
+ * Example of wait() and sleep() methods
+ */
+public class WaitSleepExample {
+
+ private static final Logger LOG = LoggerFactory.getLogger(WaitSleepExample.class);
+
+ private static final Object LOCK = new Object();
+
+ public static void main(String... args) throws InterruptedException {
+ sleepWaitInSyncronizedBlocks();
+ }
+
+ private static void sleepWaitInSyncronizedBlocks() throws InterruptedException {
+ Thread.sleep(1000); // called on the thread
+ LOG.debug("Thread '" + Thread.currentThread().getName() + "' is woken after sleeping for 1 second");
+
+ synchronized (LOCK) {
+ LOCK.wait(1000); // called on the object, synchronization required
+ LOG.debug("Object '" + LOCK + "' is woken after waiting for 1 second");
+ }
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/dirmonitoring/DirectoryMonitoringExample.java b/core-java/src/main/java/com/baeldung/dirmonitoring/DirectoryMonitoringExample.java
index 49030b5352..f9028bd159 100644
--- a/core-java/src/main/java/com/baeldung/dirmonitoring/DirectoryMonitoringExample.java
+++ b/core-java/src/main/java/com/baeldung/dirmonitoring/DirectoryMonitoringExample.java
@@ -1,14 +1,19 @@
package com.baeldung.dirmonitoring;
-import java.io.File;
-
import org.apache.commons.io.monitor.FileAlterationListener;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
public class DirectoryMonitoringExample {
+ private static final Logger LOG = LoggerFactory.getLogger(DirectoryMonitoringExample.class);
+
+
public static final int POLL_INTERVAL = 500;
public static void main(String[] args) throws Exception {
@@ -17,17 +22,17 @@ public class DirectoryMonitoringExample {
FileAlterationListener listener = new FileAlterationListenerAdaptor() {
@Override
public void onFileCreate(File file) {
- System.out.println("File: " + file.getName() + " created");
+ LOG.debug("File: " + file.getName() + " created");
}
@Override
public void onFileDelete(File file) {
- System.out.println("File: " + file.getName() + " deleted");
+ LOG.debug("File: " + file.getName() + " deleted");
}
@Override
public void onFileChange(File file) {
- System.out.println("File: " + file.getName() + " changed");
+ LOG.debug("File: " + file.getName() + " changed");
}
};
observer.addListener(listener);
diff --git a/core-java/src/main/java/com/baeldung/doublecolon/MacbookPro.java b/core-java/src/main/java/com/baeldung/doublecolon/MacbookPro.java
index 3fc459c681..f5c31e9653 100644
--- a/core-java/src/main/java/com/baeldung/doublecolon/MacbookPro.java
+++ b/core-java/src/main/java/com/baeldung/doublecolon/MacbookPro.java
@@ -1,9 +1,14 @@
package com.baeldung.doublecolon;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.util.function.Function;
public class MacbookPro extends Computer {
+ private static final Logger LOG = LoggerFactory.getLogger(MacbookPro.class);
+
public MacbookPro(int age, String color) {
super(age, color);
}
@@ -14,12 +19,12 @@ public class MacbookPro extends Computer {
@Override
public void turnOnPc() {
- System.out.println("MacbookPro turned on");
+ LOG.debug("MacbookPro turned on");
}
@Override
public void turnOffPc() {
- System.out.println("MacbookPro turned off");
+ LOG.debug("MacbookPro turned off");
}
@Override
@@ -27,7 +32,7 @@ public class MacbookPro extends Computer {
Function function = super::calculateValue;
final Double pcValue = function.apply(initialValue);
- System.out.println("First value is:" + pcValue);
+ LOG.debug("First value is:" + pcValue);
return pcValue + (initialValue / 10);
}
diff --git a/core-java/src/main/java/com/baeldung/dynamicproxy/DynamicInvocationHandler.java b/core-java/src/main/java/com/baeldung/dynamicproxy/DynamicInvocationHandler.java
new file mode 100644
index 0000000000..8bde2f703f
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/dynamicproxy/DynamicInvocationHandler.java
@@ -0,0 +1,19 @@
+package com.baeldung.dynamicproxy;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+public class DynamicInvocationHandler implements InvocationHandler {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(DynamicInvocationHandler.class);
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ LOGGER.info("Invoked method: {}", method.getName());
+
+ return 42;
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/dynamicproxy/TimingDynamicInvocationHandler.java b/core-java/src/main/java/com/baeldung/dynamicproxy/TimingDynamicInvocationHandler.java
new file mode 100644
index 0000000000..942efc50cc
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/dynamicproxy/TimingDynamicInvocationHandler.java
@@ -0,0 +1,36 @@
+package com.baeldung.dynamicproxy;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TimingDynamicInvocationHandler implements InvocationHandler {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(TimingDynamicInvocationHandler.class);
+ private final Map methods = new HashMap<>();
+
+ private Object target;
+
+ public TimingDynamicInvocationHandler(Object target) {
+ this.target = target;
+
+ for(Method method: target.getClass().getDeclaredMethods()) {
+ this.methods.put(method.getName(), method);
+ }
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ long start = System.nanoTime();
+ Object result = methods.get(method.getName()).invoke(target, args);
+ long elapsed = System.nanoTime() - start;
+
+ LOGGER.info("Executing {} finished in {} ns", method.getName(), elapsed);
+
+ return result;
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/exceptions/StackTraceToString.java b/core-java/src/main/java/com/baeldung/exceptions/StackTraceToString.java
new file mode 100644
index 0000000000..c6bf915996
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/exceptions/StackTraceToString.java
@@ -0,0 +1,30 @@
+package com.baeldung.exceptions;
+
+import org.apache.commons.lang3.exception.ExceptionUtils;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+public class StackTraceToString {
+
+ public static void main(String[] args) {
+ // Convert a StackTrace to String using core java
+ try {
+ throw new NullPointerException();
+ } catch (Exception e) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ e.printStackTrace(pw);
+
+ System.out.println(sw.toString());
+ }
+
+ // Convert a StackTrace to String using Apache Commons
+ try {
+ throw new IndexOutOfBoundsException();
+ } catch (Exception e) {
+ System.out.println(ExceptionUtils.getStackTrace(e));
+ }
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/http/ParameterStringBuilder.java b/core-java/src/main/java/com/baeldung/http/ParameterStringBuilder.java
new file mode 100644
index 0000000000..bed4195faa
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/http/ParameterStringBuilder.java
@@ -0,0 +1,21 @@
+package com.baeldung.http;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Map;
+
+public class ParameterStringBuilder {
+ public static String getParamsString(Map params) throws UnsupportedEncodingException {
+ StringBuilder result = new StringBuilder();
+
+ for (Map.Entry entry : params.entrySet()) {
+ result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
+ result.append("=");
+ result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
+ result.append("&");
+ }
+
+ String resultString = result.toString();
+ return resultString.length() > 0 ? resultString.substring(0, resultString.length() - 1) : resultString;
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/java/map/MyKey.java b/core-java/src/main/java/com/baeldung/java/map/MyKey.java
index a2587c1dc1..ae3c3edc39 100644
--- a/core-java/src/main/java/com/baeldung/java/map/MyKey.java
+++ b/core-java/src/main/java/com/baeldung/java/map/MyKey.java
@@ -1,6 +1,11 @@
package com.baeldung.java.map;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
public class MyKey {
+ private static final Logger LOG = LoggerFactory.getLogger(MyKey.class);
+
private String name;
private int id;
@@ -27,7 +32,7 @@ public class MyKey {
@Override
public int hashCode() {
- System.out.println("Calling hashCode()");
+ LOG.debug("Calling hashCode()");
return id;
}
@@ -38,7 +43,7 @@ public class MyKey {
@Override
public boolean equals(Object obj) {
- System.out.println("Calling equals() for key: " + obj);
+ LOG.debug("Calling equals() for key: " + obj);
if (this == obj)
return true;
if (obj == null)
diff --git a/core-java/src/main/java/com/baeldung/java/reflection/Operations.java b/core-java/src/main/java/com/baeldung/java/reflection/Operations.java
new file mode 100644
index 0000000000..da4b479b02
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/java/reflection/Operations.java
@@ -0,0 +1,21 @@
+package com.baeldung.java.reflection;
+
+public class Operations {
+
+ public double publicSum(int a, double b) {
+ return a + b;
+ }
+
+ public static double publicStaticMultiply(float a, long b) {
+ return a * b;
+ }
+
+ private boolean privateAnd(boolean a, boolean b) {
+ return a && b;
+ }
+
+ protected int protectedMax(int a, int b) {
+ return a > b ? a : b;
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/jdbc/Employee.java b/core-java/src/main/java/com/baeldung/jdbc/Employee.java
new file mode 100644
index 0000000000..749855ca3b
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/jdbc/Employee.java
@@ -0,0 +1,51 @@
+package com.baeldung.jdbc;
+
+public class Employee {
+ private int id;
+ private String name;
+ private String position;
+ private double salary;
+
+ public Employee() {
+ }
+
+ public Employee(int id, String name, double salary, String position) {
+ this.id = id;
+ this.name = name;
+ this.salary = salary;
+ this.position = position;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public double getSalary() {
+ return salary;
+ }
+
+ public void setSalary(double salary) {
+ this.salary = salary;
+ }
+
+ public String getPosition() {
+ return position;
+ }
+
+ public void setPosition(String position) {
+ this.position = position;
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/jmx/Game.java b/core-java/src/main/java/com/baeldung/jmx/Game.java
index f38db27601..79256c0659 100644
--- a/core-java/src/main/java/com/baeldung/jmx/Game.java
+++ b/core-java/src/main/java/com/baeldung/jmx/Game.java
@@ -1,23 +1,28 @@
package com.baeldung.jmx;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
public class Game implements GameMBean {
+ private static final Logger LOG = LoggerFactory.getLogger(Game.class);
+
private String playerName;
@Override
public void playFootball(String clubName) {
- System.out.println(this.playerName + " playing football for " + clubName);
+ LOG.debug(this.playerName + " playing football for " + clubName);
}
@Override
public String getPlayerName() {
- System.out.println("Return playerName " + this.playerName);
+ LOG.debug("Return playerName " + this.playerName);
return playerName;
}
@Override
public void setPlayerName(String playerName) {
- System.out.println("Set playerName to value " + playerName);
+ LOG.debug("Set playerName to value " + playerName);
this.playerName = playerName;
}
diff --git a/core-java/src/main/java/com/baeldung/jmx/JMXTutorialMainlauncher.java b/core-java/src/main/java/com/baeldung/jmx/JMXTutorialMainlauncher.java
index 6f9c30ab50..220b9a8ec6 100644
--- a/core-java/src/main/java/com/baeldung/jmx/JMXTutorialMainlauncher.java
+++ b/core-java/src/main/java/com/baeldung/jmx/JMXTutorialMainlauncher.java
@@ -1,19 +1,20 @@
package com.baeldung.jmx;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.management.*;
import java.lang.management.ManagementFactory;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.MBeanRegistrationException;
-import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.ObjectName;
public class JMXTutorialMainlauncher {
+ private static final Logger LOG = LoggerFactory.getLogger(JMXTutorialMainlauncher.class);
+
+
public static void main(String[] args) {
// TODO Auto-generated method stub
- System.out.println("This is basic JMX tutorial");
+ LOG.debug("This is basic JMX tutorial");
ObjectName objectName = null;
try {
objectName = new ObjectName("com.baeldung.tutorial:type=basic,name=game");
@@ -27,8 +28,8 @@ public class JMXTutorialMainlauncher {
} catch (InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException e) {
e.printStackTrace();
}
- System.out.println("Registration for Game mbean with the platform server is successfull");
- System.out.println("Please open jconsole to access Game mbean");
+ LOG.debug("Registration for Game mbean with the platform server is successfull");
+ LOG.debug("Please open jconsole to access Game mbean");
while (true) {
// to ensure application does not terminate
}
diff --git a/core-java/src/main/java/com/baeldung/socket/EchoClient.java b/core-java/src/main/java/com/baeldung/socket/EchoClient.java
index 570bd60b2d..cf5c253276 100644
--- a/core-java/src/main/java/com/baeldung/socket/EchoClient.java
+++ b/core-java/src/main/java/com/baeldung/socket/EchoClient.java
@@ -1,9 +1,16 @@
package com.baeldung.socket;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.io.*;
import java.net.*;
public class EchoClient {
+
+
+ private static final Logger LOG = LoggerFactory.getLogger(EchoClient.class);
+
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
@@ -14,7 +21,7 @@ public class EchoClient {
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (IOException e) {
- System.out.print(e);
+ LOG.debug("Error when initializing connection", e);
}
}
@@ -34,7 +41,7 @@ public class EchoClient {
out.close();
clientSocket.close();
} catch (IOException e) {
- e.printStackTrace();
+ LOG.debug("error when closing", e);
}
}
diff --git a/core-java/src/main/java/com/baeldung/socket/EchoMultiServer.java b/core-java/src/main/java/com/baeldung/socket/EchoMultiServer.java
index b920967545..a9f055f8f4 100644
--- a/core-java/src/main/java/com/baeldung/socket/EchoMultiServer.java
+++ b/core-java/src/main/java/com/baeldung/socket/EchoMultiServer.java
@@ -1,9 +1,15 @@
package com.baeldung.socket;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.net.*;
import java.io.*;
public class EchoMultiServer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(EchoMultiServer.class);
+
private ServerSocket serverSocket;
public void start(int port) {
@@ -57,7 +63,7 @@ public class EchoMultiServer {
clientSocket.close();
} catch (IOException e) {
- e.printStackTrace();
+ LOG.debug(e.getMessage());
}
}
}
diff --git a/core-java/src/main/java/com/baeldung/socket/EchoServer.java b/core-java/src/main/java/com/baeldung/socket/EchoServer.java
index dfd281d51c..a869e98966 100644
--- a/core-java/src/main/java/com/baeldung/socket/EchoServer.java
+++ b/core-java/src/main/java/com/baeldung/socket/EchoServer.java
@@ -1,9 +1,15 @@
package com.baeldung.socket;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.net.*;
import java.io.*;
public class EchoServer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(EchoServer.class);
+
private ServerSocket serverSocket;
private Socket clientSocket;
private PrintWriter out;
@@ -24,7 +30,7 @@ public class EchoServer {
out.println(inputLine);
}
} catch (IOException e) {
- e.printStackTrace();
+ LOG.debug(e.getMessage());
}
}
@@ -36,7 +42,7 @@ public class EchoServer {
clientSocket.close();
serverSocket.close();
} catch (IOException e) {
- e.printStackTrace();
+ LOG.debug(e.getMessage());
}
}
diff --git a/core-java/src/main/java/com/baeldung/socket/GreetClient.java b/core-java/src/main/java/com/baeldung/socket/GreetClient.java
index e6f14bb2b6..38ad016919 100644
--- a/core-java/src/main/java/com/baeldung/socket/GreetClient.java
+++ b/core-java/src/main/java/com/baeldung/socket/GreetClient.java
@@ -1,5 +1,8 @@
package com.baeldung.socket;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@@ -7,6 +10,9 @@ import java.io.PrintWriter;
import java.net.Socket;
public class GreetClient {
+
+ private static final Logger LOG = LoggerFactory.getLogger(EchoMultiServer.class);
+
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
@@ -17,7 +23,7 @@ public class GreetClient {
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (IOException e) {
-
+ LOG.debug(e.getMessage());
}
}
@@ -37,7 +43,7 @@ public class GreetClient {
out.close();
clientSocket.close();
} catch (IOException e) {
- e.printStackTrace();
+ LOG.debug(e.getMessage());
}
}
diff --git a/core-java/src/main/java/com/baeldung/socket/GreetServer.java b/core-java/src/main/java/com/baeldung/socket/GreetServer.java
index 05bc65a65e..f46db91959 100644
--- a/core-java/src/main/java/com/baeldung/socket/GreetServer.java
+++ b/core-java/src/main/java/com/baeldung/socket/GreetServer.java
@@ -1,9 +1,15 @@
package com.baeldung.socket;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.net.*;
import java.io.*;
public class GreetServer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(GreetServer.class);
+
private ServerSocket serverSocket;
private Socket clientSocket;
private PrintWriter out;
@@ -21,7 +27,7 @@ public class GreetServer {
else
out.println("unrecognised greeting");
} catch (IOException e) {
- e.printStackTrace();
+ LOG.debug(e.getMessage());
}
}
@@ -33,7 +39,7 @@ public class GreetServer {
clientSocket.close();
serverSocket.close();
} catch (IOException e) {
- e.printStackTrace();
+ LOG.debug(e.getMessage());
}
}
diff --git a/core-java/src/main/java/com/baeldung/stackoverflowerror/AccountHolder.java b/core-java/src/main/java/com/baeldung/stackoverflowerror/AccountHolder.java
new file mode 100644
index 0000000000..9555433792
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/stackoverflowerror/AccountHolder.java
@@ -0,0 +1,8 @@
+package com.baeldung.stackoverflowerror;
+
+public class AccountHolder {
+ private String firstName;
+ private String lastName;
+
+ AccountHolder jointAccountHolder = new AccountHolder();
+}
diff --git a/core-java/src/main/java/com/baeldung/stackoverflowerror/ClassOne.java b/core-java/src/main/java/com/baeldung/stackoverflowerror/ClassOne.java
new file mode 100644
index 0000000000..99ef2b4f92
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/stackoverflowerror/ClassOne.java
@@ -0,0 +1,16 @@
+package com.baeldung.stackoverflowerror;
+
+public class ClassOne {
+ private int oneValue;
+ private ClassTwo clsTwoInstance = null;
+
+ public ClassOne() {
+ oneValue = 0;
+ clsTwoInstance = new ClassTwo();
+ }
+
+ public ClassOne(int oneValue, ClassTwo clsTwoInstance) {
+ this.oneValue = oneValue;
+ this.clsTwoInstance = clsTwoInstance;
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/stackoverflowerror/ClassTwo.java b/core-java/src/main/java/com/baeldung/stackoverflowerror/ClassTwo.java
new file mode 100644
index 0000000000..0d34ac3c32
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/stackoverflowerror/ClassTwo.java
@@ -0,0 +1,16 @@
+package com.baeldung.stackoverflowerror;
+
+public class ClassTwo {
+ private int twoValue;
+ private ClassOne clsOneInstance = null;
+
+ public ClassTwo() {
+ twoValue = 10;
+ clsOneInstance = new ClassOne();
+ }
+
+ public ClassTwo(int twoValue, ClassOne clsOneInstance) {
+ this.twoValue = twoValue;
+ this.clsOneInstance = clsOneInstance;
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/stackoverflowerror/InfiniteRecursionWithTerminationCondition.java b/core-java/src/main/java/com/baeldung/stackoverflowerror/InfiniteRecursionWithTerminationCondition.java
new file mode 100644
index 0000000000..9fb00d4b83
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/stackoverflowerror/InfiniteRecursionWithTerminationCondition.java
@@ -0,0 +1,7 @@
+package com.baeldung.stackoverflowerror;
+
+public class InfiniteRecursionWithTerminationCondition {
+ public int calculateFactorial(final int number) {
+ return number == 1 ? 1 : number * calculateFactorial(number - 1);
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/stackoverflowerror/RecursionWithCorrectTerminationCondition.java b/core-java/src/main/java/com/baeldung/stackoverflowerror/RecursionWithCorrectTerminationCondition.java
new file mode 100644
index 0000000000..0c0c392532
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/stackoverflowerror/RecursionWithCorrectTerminationCondition.java
@@ -0,0 +1,7 @@
+package com.baeldung.stackoverflowerror;
+
+public class RecursionWithCorrectTerminationCondition {
+ public static int calculateFactorial(final int number) {
+ return number <= 1 ? 1 : number * calculateFactorial(number - 1);
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/stackoverflowerror/UnintendedInfiniteRecursion.java b/core-java/src/main/java/com/baeldung/stackoverflowerror/UnintendedInfiniteRecursion.java
new file mode 100644
index 0000000000..f5160c3eb3
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/stackoverflowerror/UnintendedInfiniteRecursion.java
@@ -0,0 +1,7 @@
+package com.baeldung.stackoverflowerror;
+
+public class UnintendedInfiniteRecursion {
+ public int calculateFactorial(int number) {
+ return number * calculateFactorial(number - 1);
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/stream/InfiniteStreams.java b/core-java/src/main/java/com/baeldung/stream/InfiniteStreams.java
index 097b516f8c..ae00fc7cb4 100644
--- a/core-java/src/main/java/com/baeldung/stream/InfiniteStreams.java
+++ b/core-java/src/main/java/com/baeldung/stream/InfiniteStreams.java
@@ -1,9 +1,15 @@
package com.baeldung.stream;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.util.stream.Stream;
public class InfiniteStreams {
+
+ private static final Logger LOG = LoggerFactory.getLogger(InfiniteStreams.class);
+
public static void main(String[] args) {
doWhileOldWay();
@@ -15,7 +21,7 @@ public class InfiniteStreams {
int i = 0;
while (i < 10) {
- System.out.println(i);
+ LOG.debug("{}", i);
i++;
}
}
diff --git a/core-java/src/main/java/com/baeldung/threadlocal/ThreadLocalWithUserContext.java b/core-java/src/main/java/com/baeldung/threadlocal/ThreadLocalWithUserContext.java
index 0d6a7e5572..de7e4a0369 100644
--- a/core-java/src/main/java/com/baeldung/threadlocal/ThreadLocalWithUserContext.java
+++ b/core-java/src/main/java/com/baeldung/threadlocal/ThreadLocalWithUserContext.java
@@ -1,7 +1,11 @@
package com.baeldung.threadlocal;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class ThreadLocalWithUserContext implements Runnable {
+ private static final Logger LOG = LoggerFactory.getLogger(ThreadLocalWithUserContext.class);
+
private static final ThreadLocal userContext = new ThreadLocal<>();
private final Integer userId;
private UserRepository userRepository = new UserRepository();
@@ -15,6 +19,6 @@ public class ThreadLocalWithUserContext implements Runnable {
public void run() {
String userName = userRepository.getUserNameForUserId(userId);
userContext.set(new Context(userName));
- System.out.println("thread context for given userId: " + userId + " is: " + userContext.get());
+ LOG.debug("thread context for given userId: " + userId + " is: " + userContext.get());
}
}
diff --git a/core-java/src/main/java/com/baeldung/transferqueue/Consumer.java b/core-java/src/main/java/com/baeldung/transferqueue/Consumer.java
new file mode 100644
index 0000000000..69d7ff2390
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/transferqueue/Consumer.java
@@ -0,0 +1,42 @@
+package com.baeldung.transferqueue;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.TransferQueue;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class Consumer implements Runnable {
+ private static final Logger LOG = LoggerFactory.getLogger(Consumer.class);
+
+
+ private final TransferQueue transferQueue;
+ private final String name;
+ private final int numberOfMessagesToConsume;
+ public final AtomicInteger numberOfConsumedMessages = new AtomicInteger();
+
+ public Consumer(TransferQueue transferQueue, String name, int numberOfMessagesToConsume) {
+ this.transferQueue = transferQueue;
+ this.name = name;
+ this.numberOfMessagesToConsume = numberOfMessagesToConsume;
+ }
+
+ @Override
+ public void run() {
+ for (int i = 0; i < numberOfMessagesToConsume; i++) {
+ try {
+ LOG.debug("Consumer: " + name + " is waiting to take element...");
+ String element = transferQueue.take();
+ longProcessing(element);
+ LOG.debug("Consumer: " + name + " received element: " + element);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void longProcessing(String element) throws InterruptedException {
+ numberOfConsumedMessages.incrementAndGet();
+ Thread.sleep(500);
+ }
+}
\ No newline at end of file
diff --git a/core-java/src/main/java/com/baeldung/transferqueue/Producer.java b/core-java/src/main/java/com/baeldung/transferqueue/Producer.java
new file mode 100644
index 0000000000..c7df7c410a
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/transferqueue/Producer.java
@@ -0,0 +1,41 @@
+package com.baeldung.transferqueue;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TransferQueue;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class Producer implements Runnable {
+ private static final Logger LOG = LoggerFactory.getLogger(Producer.class);
+
+ private final TransferQueue transferQueue;
+ private final String name;
+ private final Integer numberOfMessagesToProduce;
+ public final AtomicInteger numberOfProducedMessages = new AtomicInteger();
+
+ public Producer(TransferQueue transferQueue, String name, Integer numberOfMessagesToProduce) {
+ this.transferQueue = transferQueue;
+ this.name = name;
+ this.numberOfMessagesToProduce = numberOfMessagesToProduce;
+ }
+
+ @Override
+ public void run() {
+ for (int i = 0; i < numberOfMessagesToProduce; i++) {
+ try {
+ LOG.debug("Producer: " + name + " is waiting to transfer...");
+ boolean added = transferQueue.tryTransfer("A" + i, 4000, TimeUnit.MILLISECONDS);
+ if (added) {
+ numberOfProducedMessages.incrementAndGet();
+ LOG.debug("Producer: " + name + " transferred element: A" + i);
+ } else {
+ LOG.debug("can not add an element due to the timeout");
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/core-java/src/main/resources/META-INF/persistence.xml b/core-java/src/main/resources/META-INF/persistence.xml
new file mode 100644
index 0000000000..3966afdcda
--- /dev/null
+++ b/core-java/src/main/resources/META-INF/persistence.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core-java/src/main/resources/log4j.properties b/core-java/src/main/resources/log4j.properties
new file mode 100644
index 0000000000..621cf01735
--- /dev/null
+++ b/core-java/src/main/resources/log4j.properties
@@ -0,0 +1,6 @@
+log4j.rootLogger=DEBUG, A1
+
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
\ No newline at end of file
diff --git a/core-java/src/test/java/com/baeldung/PrimitiveConversionsJUnitTest.java b/core-java/src/test/java/com/baeldung/PrimitiveConversionsJUnitTest.java
index 10ceaf85a4..69a6c18dfd 100644
--- a/core-java/src/test/java/com/baeldung/PrimitiveConversionsJUnitTest.java
+++ b/core-java/src/test/java/com/baeldung/PrimitiveConversionsJUnitTest.java
@@ -1,13 +1,14 @@
package com.baeldung;
import org.junit.Test;
-import static org.junit.Assert.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.Assert.assertEquals;
-/**
- *
- * @author paulo.motta
- */
public class PrimitiveConversionsJUnitTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PrimitiveConversionsJUnitTest.class);
@Test
public void givenDataWithLessBits_whenAttributingToLargerSizeVariable_thenNoSpecialNotation() {
@@ -60,36 +61,36 @@ public class PrimitiveConversionsJUnitTest {
@Test
public void givenByteValue_whenConvertingToChar_thenWidenAndNarrowTakesPlace(){
byte myLargeValueByte = (byte) 130; //0b10000010
- System.out.println(myLargeValueByte); //0b10000010 -126
+ LOG.debug("{}", myLargeValueByte); //0b10000010 -126
assertEquals( -126, myLargeValueByte);
int myLargeValueInt = myLargeValueByte;
- System.out.println(myLargeValueInt); //0b11111111 11111111 11111111 10000010 -126
+ LOG.debug("{}", myLargeValueInt); //0b11111111 11111111 11111111 10000010 -126
assertEquals( -126, myLargeValueInt);
char myLargeValueChar = (char) myLargeValueByte;
- System.out.println(myLargeValueChar);//0b11111111 10000010 unsigned 0xFF82
+ LOG.debug("{}", myLargeValueChar);//0b11111111 10000010 unsigned 0xFF82
assertEquals(0xFF82, myLargeValueChar);
myLargeValueInt = myLargeValueChar;
- System.out.println(myLargeValueInt); //0b11111111 10000010 65410
+ LOG.debug("{}", myLargeValueInt); //0b11111111 10000010 65410
assertEquals(65410, myLargeValueInt);
byte myOtherByte = (byte) myLargeValueInt;
- System.out.println(myOtherByte); //0b10000010 -126
+ LOG.debug("{}", myOtherByte); //0b10000010 -126
assertEquals( -126, myOtherByte);
char myLargeValueChar2 = 130; //This is an int not a byte!
- System.out.println(myLargeValueChar2);//0b00000000 10000010 unsigned 0x0082
+ LOG.debug("{}", myLargeValueChar2);//0b00000000 10000010 unsigned 0x0082
assertEquals(0x0082, myLargeValueChar2);
int myLargeValueInt2 = myLargeValueChar2;
- System.out.println(myLargeValueInt2); //0b00000000 10000010 130
+ LOG.debug("{}", myLargeValueInt2); //0b00000000 10000010 130
assertEquals(130, myLargeValueInt2);
byte myOtherByte2 = (byte) myLargeValueInt2;
- System.out.println(myOtherByte2); //0b10000010 -126
+ LOG.debug("{}", myOtherByte2); //0b10000010 -126
assertEquals( -126, myOtherByte2);
}
diff --git a/core-java/src/test/java/com/baeldung/completablefuture/CompletableFutureUnitTest.java b/core-java/src/test/java/com/baeldung/completablefuture/CompletableFutureUnitTest.java
index df12c3d79e..501cb1afa0 100644
--- a/core-java/src/test/java/com/baeldung/completablefuture/CompletableFutureUnitTest.java
+++ b/core-java/src/test/java/com/baeldung/completablefuture/CompletableFutureUnitTest.java
@@ -1,20 +1,21 @@
package com.baeldung.completablefuture;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import org.junit.Test;
-
public class CompletableFutureUnitTest {
+ private static final Logger LOG = LoggerFactory.getLogger(CompletableFutureUnitTest.class);
+
+
@Test
public void whenRunningCompletableFutureAsynchronously_thenGetMethodWaitsForResult() throws InterruptedException, ExecutionException {
Future completableFuture = calculateAsync();
@@ -72,7 +73,7 @@ public class CompletableFutureUnitTest {
public void whenAddingThenAcceptToFuture_thenFunctionExecutesAfterComputationIsFinished() throws ExecutionException, InterruptedException {
CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "Hello");
- CompletableFuture future = completableFuture.thenAccept(s -> System.out.println("Computation returned: " + s));
+ CompletableFuture future = completableFuture.thenAccept(s -> LOG.debug("Computation returned: " + s));
future.get();
}
@@ -81,7 +82,7 @@ public class CompletableFutureUnitTest {
public void whenAddingThenRunToFuture_thenFunctionExecutesAfterComputationIsFinished() throws ExecutionException, InterruptedException {
CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "Hello");
- CompletableFuture future = completableFuture.thenRun(() -> System.out.println("Computation finished."));
+ CompletableFuture future = completableFuture.thenRun(() -> LOG.debug("Computation finished."));
future.get();
}
@@ -111,7 +112,7 @@ public class CompletableFutureUnitTest {
@Test
public void whenUsingThenAcceptBoth_thenWaitForExecutionOfBothFutures() throws ExecutionException, InterruptedException {
- CompletableFuture.supplyAsync(() -> "Hello").thenAcceptBoth(CompletableFuture.supplyAsync(() -> " World"), (s1, s2) -> System.out.println(s1 + s2));
+ CompletableFuture.supplyAsync(() -> "Hello").thenAcceptBoth(CompletableFuture.supplyAsync(() -> " World"), (s1, s2) -> LOG.debug(s1 + s2));
}
@Test
diff --git a/core-java/src/test/java/com/baeldung/concurrent/accumulator/LongAccumulatorTest.java b/core-java/src/test/java/com/baeldung/concurrent/accumulator/LongAccumulatorTest.java
new file mode 100644
index 0000000000..3a0092cf24
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/concurrent/accumulator/LongAccumulatorTest.java
@@ -0,0 +1,42 @@
+package com.baeldung.concurrent.accumulator;
+
+import org.junit.Test;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.LongAccumulator;
+import java.util.function.LongBinaryOperator;
+import java.util.stream.IntStream;
+
+import static junit.framework.TestCase.assertEquals;
+
+public class LongAccumulatorTest {
+
+ @Test
+ public void givenLongAccumulator_whenApplyActionOnItFromMultipleThrads_thenShouldProduceProperResult() throws InterruptedException {
+ //given
+ ExecutorService executorService = Executors.newFixedThreadPool(8);
+ LongBinaryOperator sum = Long::sum;
+ LongAccumulator accumulator = new LongAccumulator(sum, 0L);
+ int numberOfThreads = 4;
+ int numberOfIncrements = 100;
+
+ //when
+ Runnable accumulateAction = () -> IntStream
+ .rangeClosed(0, numberOfIncrements)
+ .forEach(accumulator::accumulate);
+
+ for (int i = 0; i < numberOfThreads; i++) {
+ executorService.execute(accumulateAction);
+ }
+
+
+ //then
+ executorService.awaitTermination(500, TimeUnit.MILLISECONDS);
+ executorService.shutdown();
+ assertEquals(accumulator.get(), 20200);
+
+
+ }
+}
diff --git a/core-java/src/test/java/com/baeldung/concurrent/adder/LongAdderTest.java b/core-java/src/test/java/com/baeldung/concurrent/adder/LongAdderTest.java
new file mode 100644
index 0000000000..77d1e9de27
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/concurrent/adder/LongAdderTest.java
@@ -0,0 +1,67 @@
+package com.baeldung.concurrent.adder;
+
+import org.junit.Test;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.LongAdder;
+import java.util.stream.IntStream;
+
+import static com.jayway.awaitility.Awaitility.await;
+import static junit.framework.TestCase.assertEquals;
+
+public class LongAdderTest {
+ @Test
+ public void givenMultipleThread_whenTheyWriteToSharedLongAdder_thenShouldCalculateSumForThem() throws InterruptedException {
+ //given
+ LongAdder counter = new LongAdder();
+ ExecutorService executorService = Executors.newFixedThreadPool(8);
+
+ int numberOfThreads = 4;
+ int numberOfIncrements = 100;
+
+ //when
+ Runnable incrementAction = () -> IntStream
+ .range(0, numberOfIncrements)
+ .forEach((i) -> counter.increment());
+
+ for (int i = 0; i < numberOfThreads; i++) {
+ executorService.execute(incrementAction);
+ }
+
+ //then
+ executorService.awaitTermination(500, TimeUnit.MILLISECONDS);
+ executorService.shutdown();
+
+ assertEquals(counter.sum(), numberOfIncrements * numberOfThreads);
+ assertEquals(counter.sum(), numberOfIncrements * numberOfThreads);
+ }
+
+ @Test
+ public void givenMultipleThread_whenTheyWriteToSharedLongAdder_thenShouldCalculateSumForThemAndResetAdderAfterward() throws InterruptedException {
+ //given
+ LongAdder counter = new LongAdder();
+ ExecutorService executorService = Executors.newFixedThreadPool(8);
+
+ int numberOfThreads = 4;
+ int numberOfIncrements = 100;
+
+ //when
+ Runnable incrementAction = () -> IntStream
+ .range(0, numberOfIncrements)
+ .forEach((i) -> counter.increment());
+
+ for (int i = 0; i < numberOfThreads; i++) {
+ executorService.execute(incrementAction);
+ }
+
+ //then
+ executorService.awaitTermination(500, TimeUnit.MILLISECONDS);
+ executorService.shutdown();
+
+ assertEquals(counter.sumThenReset(), numberOfIncrements * numberOfThreads);
+
+ await().until(() -> assertEquals(counter.sum(), 0));
+ }
+}
diff --git a/core-java/src/test/java/com/baeldung/concurrent/copyonwrite/CopyOnWriteArrayListTest.java b/core-java/src/test/java/com/baeldung/concurrent/copyonwrite/CopyOnWriteArrayListTest.java
new file mode 100644
index 0000000000..c71c193372
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/concurrent/copyonwrite/CopyOnWriteArrayListTest.java
@@ -0,0 +1,53 @@
+package com.baeldung.concurrent.copyonwrite;
+
+
+import org.junit.Test;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+
+public class CopyOnWriteArrayListTest {
+
+ @Test
+ public void givenCopyOnWriteList_whenIterateAndAddElementToUnderneathList_thenShouldNotChangeIterator() {
+ //given
+ final CopyOnWriteArrayList numbers =
+ new CopyOnWriteArrayList<>(new Integer[]{1, 3, 5, 8});
+
+ //when
+ Iterator iterator = numbers.iterator();
+ numbers.add(10);
+
+ //then
+ List result = new LinkedList<>();
+ iterator.forEachRemaining(result::add);
+ assertThat(result).containsOnly(1, 3, 5, 8);
+
+ //and
+ Iterator iterator2 = numbers.iterator();
+ List result2 = new LinkedList<>();
+ iterator2.forEachRemaining(result2::add);
+
+ //then
+ assertThat(result2).containsOnly(1, 3, 5, 8, 10);
+
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void givenCopyOnWriteList_whenIterateOverItAndTryToRemoveElement_thenShouldThrowException() {
+ //given
+ final CopyOnWriteArrayList numbers =
+ new CopyOnWriteArrayList<>(new Integer[]{1, 3, 5, 8});
+
+ //when
+ Iterator iterator = numbers.iterator();
+ while (iterator.hasNext()) {
+ iterator.remove();
+ }
+ }
+}
diff --git a/core-java/src/test/java/com/baeldung/concurrent/future/SquareCalculatorUnitTest.java b/core-java/src/test/java/com/baeldung/concurrent/future/SquareCalculatorIntegrationTest.java
similarity index 77%
rename from core-java/src/test/java/com/baeldung/concurrent/future/SquareCalculatorUnitTest.java
rename to core-java/src/test/java/com/baeldung/concurrent/future/SquareCalculatorIntegrationTest.java
index 69c802feb8..84d7a55504 100644
--- a/core-java/src/test/java/com/baeldung/concurrent/future/SquareCalculatorUnitTest.java
+++ b/core-java/src/test/java/com/baeldung/concurrent/future/SquareCalculatorIntegrationTest.java
@@ -1,22 +1,22 @@
package com.baeldung.concurrent.future;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.*;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class SquareCalculatorIntegrationTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SquareCalculatorIntegrationTest.class);
-public class SquareCalculatorUnitTest {
@Rule
public TestName name = new TestName();
@@ -33,7 +33,7 @@ public class SquareCalculatorUnitTest {
Future result2 = squareCalculator.calculate(1000);
while (!result1.isDone() || !result2.isDone()) {
- System.out.println(String.format("Task 1 is %s and Task 2 is %s.", result1.isDone() ? "done" : "not done", result2.isDone() ? "done" : "not done"));
+ LOG.debug(String.format("Task 1 is %s and Task 2 is %s.", result1.isDone() ? "done" : "not done", result2.isDone() ? "done" : "not done"));
Thread.sleep(300);
}
@@ -59,7 +59,7 @@ public class SquareCalculatorUnitTest {
Future result2 = squareCalculator.calculate(1000);
while (!result1.isDone() || !result2.isDone()) {
- System.out.println(String.format("Task 1 is %s and Task 2 is %s.", result1.isDone() ? "done" : "not done", result2.isDone() ? "done" : "not done"));
+ LOG.debug(String.format("Task 1 is %s and Task 2 is %s.", result1.isDone() ? "done" : "not done", result2.isDone() ? "done" : "not done"));
Thread.sleep(300);
}
@@ -89,6 +89,6 @@ public class SquareCalculatorUnitTest {
@After
public void end() {
- System.out.println(String.format("Test %s took %s ms \n", name.getMethodName(), System.currentTimeMillis() - start));
+ LOG.debug(String.format("Test %s took %s ms \n", name.getMethodName(), System.currentTimeMillis() - start));
}
}
diff --git a/core-java/src/test/java/com/baeldung/concurrent/phaser/PhaserTest.java b/core-java/src/test/java/com/baeldung/concurrent/phaser/PhaserTest.java
new file mode 100644
index 0000000000..7ba1b1ebd9
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/concurrent/phaser/PhaserTest.java
@@ -0,0 +1,41 @@
+package com.baeldung.concurrent.phaser;
+
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Phaser;
+
+import static junit.framework.TestCase.assertEquals;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class PhaserTest {
+
+ @Test
+ public void givenPhaser_whenCoordinateWorksBetweenThreads_thenShouldCoordinateBetweenMultiplePhases() {
+ //given
+ ExecutorService executorService = Executors.newCachedThreadPool();
+ Phaser ph = new Phaser(1);
+ assertEquals(0, ph.getPhase());
+
+ //when
+ executorService.submit(new LongRunningAction("thread-1", ph));
+ executorService.submit(new LongRunningAction("thread-2", ph));
+ executorService.submit(new LongRunningAction("thread-3", ph));
+
+ //then
+ ph.arriveAndAwaitAdvance();
+ assertEquals(1, ph.getPhase());
+
+ //and
+ executorService.submit(new LongRunningAction("thread-4", ph));
+ executorService.submit(new LongRunningAction("thread-5", ph));
+ ph.arriveAndAwaitAdvance();
+ assertEquals(2, ph.getPhase());
+
+
+ ph.arriveAndDeregister();
+ }
+}
diff --git a/core-java/src/test/java/com/baeldung/concurrent/priorityblockingqueue/PriorityBlockingQueueUnitTest.java b/core-java/src/test/java/com/baeldung/concurrent/priorityblockingqueue/PriorityBlockingQueueIntegrationTest.java
similarity index 80%
rename from core-java/src/test/java/com/baeldung/concurrent/priorityblockingqueue/PriorityBlockingQueueUnitTest.java
rename to core-java/src/test/java/com/baeldung/concurrent/priorityblockingqueue/PriorityBlockingQueueIntegrationTest.java
index 0272726465..9f7b828a9c 100644
--- a/core-java/src/test/java/com/baeldung/concurrent/priorityblockingqueue/PriorityBlockingQueueUnitTest.java
+++ b/core-java/src/test/java/com/baeldung/concurrent/priorityblockingqueue/PriorityBlockingQueueIntegrationTest.java
@@ -1,6 +1,8 @@
package com.baeldung.concurrent.priorityblockingqueue;
import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.concurrent.PriorityBlockingQueue;
@@ -9,7 +11,10 @@ import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.util.Lists.newArrayList;
-public class PriorityBlockingQueueUnitTest {
+public class PriorityBlockingQueueIntegrationTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PriorityBlockingQueueIntegrationTest.class);
+
@Test
public void givenUnorderedValues_whenPolling_thenShouldOrderQueue() throws InterruptedException {
@@ -32,11 +37,11 @@ public class PriorityBlockingQueueUnitTest {
PriorityBlockingQueue queue = new PriorityBlockingQueue<>();
final Thread thread = new Thread(() -> {
- System.out.println("Polling...");
+ LOG.debug("Polling...");
while (true) {
try {
Integer poll = queue.take();
- System.out.println("Polled: " + poll);
+ LOG.debug("Polled: " + poll);
} catch (InterruptedException e) {
}
}
@@ -44,7 +49,7 @@ public class PriorityBlockingQueueUnitTest {
thread.start();
Thread.sleep(TimeUnit.SECONDS.toMillis(5));
- System.out.println("Adding to queue");
+ LOG.debug("Adding to queue");
queue.addAll(newArrayList(1, 5, 6, 1, 2, 6, 7));
Thread.sleep(TimeUnit.SECONDS.toMillis(1));
diff --git a/core-java/src/test/java/com/baeldung/concurrent/skiplist/ConcurrentSkipListSetIntegrationTest.java b/core-java/src/test/java/com/baeldung/concurrent/skiplist/ConcurrentSkipListSetIntegrationTest.java
new file mode 100644
index 0000000000..92fff8446b
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/concurrent/skiplist/ConcurrentSkipListSetIntegrationTest.java
@@ -0,0 +1,120 @@
+package com.baeldung.concurrent.skiplist;
+
+import org.junit.Test;
+
+import java.time.ZonedDateTime;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentNavigableMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.IntStream;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ConcurrentSkipListSetIntegrationTest {
+
+ @Test
+ public void givenThreadsProducingEvents_whenGetForEventsFromLastMinute_thenReturnThoseEventsInTheLockFreeWay() throws InterruptedException {
+ //given
+ ExecutorService executorService = Executors.newFixedThreadPool(3);
+ EventWindowSort eventWindowSort = new EventWindowSort();
+ int numberOfThreads = 2;
+ //when
+ Runnable producer = () -> IntStream
+ .rangeClosed(0, 100)
+ .forEach(index -> eventWindowSort.acceptEvent(new Event(ZonedDateTime
+ .now()
+ .minusSeconds(index), UUID
+ .randomUUID()
+ .toString())));
+
+ for (int i = 0; i < numberOfThreads; i++) {
+ executorService.execute(producer);
+ }
+
+ Thread.sleep(500);
+
+ ConcurrentNavigableMap eventsFromLastMinute = eventWindowSort.getEventsFromLastMinute();
+
+ long eventsOlderThanOneMinute = eventsFromLastMinute
+ .entrySet()
+ .stream()
+ .filter(e -> e
+ .getKey()
+ .isBefore(ZonedDateTime
+ .now()
+ .minusMinutes(1)))
+ .count();
+ assertEquals(eventsOlderThanOneMinute, 0);
+
+ long eventYoungerThanOneMinute = eventsFromLastMinute
+ .entrySet()
+ .stream()
+ .filter(e -> e
+ .getKey()
+ .isAfter(ZonedDateTime
+ .now()
+ .minusMinutes(1)))
+ .count();
+
+ //then
+ assertTrue(eventYoungerThanOneMinute > 0);
+
+ executorService.awaitTermination(1, TimeUnit.SECONDS);
+ executorService.shutdown();
+ }
+
+ @Test
+ public void givenThreadsProducingEvents_whenGetForEventsOlderThanOneMinute_thenReturnThoseEventsInTheLockFreeWay() throws InterruptedException {
+ //given
+ ExecutorService executorService = Executors.newFixedThreadPool(3);
+ EventWindowSort eventWindowSort = new EventWindowSort();
+ int numberOfThreads = 2;
+ //when
+ Runnable producer = () -> IntStream
+ .rangeClosed(0, 100)
+ .forEach(index -> eventWindowSort.acceptEvent(new Event(ZonedDateTime
+ .now()
+ .minusSeconds(index), UUID
+ .randomUUID()
+ .toString())));
+
+ for (int i = 0; i < numberOfThreads; i++) {
+ executorService.execute(producer);
+ }
+
+ Thread.sleep(500);
+
+ ConcurrentNavigableMap eventsFromLastMinute = eventWindowSort.getEventsOlderThatOneMinute();
+
+ long eventsOlderThanOneMinute = eventsFromLastMinute
+ .entrySet()
+ .stream()
+ .filter(e -> e
+ .getKey()
+ .isBefore(ZonedDateTime
+ .now()
+ .minusMinutes(1)))
+ .count();
+ assertTrue(eventsOlderThanOneMinute > 0);
+
+ long eventYoungerThanOneMinute = eventsFromLastMinute
+ .entrySet()
+ .stream()
+ .filter(e -> e
+ .getKey()
+ .isAfter(ZonedDateTime
+ .now()
+ .minusMinutes(1)))
+ .count();
+
+ //then
+ assertEquals(eventYoungerThanOneMinute, 0);
+
+ executorService.awaitTermination(1, TimeUnit.SECONDS);
+ executorService.shutdown();
+ }
+
+}
\ No newline at end of file
diff --git a/core-java/src/test/java/com/baeldung/dateapi/JavaDurationTest.java b/core-java/src/test/java/com/baeldung/dateapi/JavaDurationTest.java
new file mode 100644
index 0000000000..f4bfc0f55c
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/dateapi/JavaDurationTest.java
@@ -0,0 +1,42 @@
+package com.baeldung.dateapi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
+import org.junit.Test;
+
+public class JavaDurationTest {
+
+ @Test
+ public void test2() {
+ Instant start = Instant.parse("2017-10-03T10:15:30.00Z");
+ Instant end = Instant.parse("2017-10-03T10:16:30.00Z");
+
+ Duration duration = Duration.between(start, end);
+
+ assertFalse(duration.isNegative());
+
+ assertEquals(60, duration.getSeconds());
+ assertEquals(1, duration.toMinutes());
+
+ Duration fromDays = Duration.ofDays(1);
+ assertEquals(86400, fromDays.getSeconds());
+
+ Duration fromMinutes = Duration.ofMinutes(60);
+ assertEquals(1, fromMinutes.toHours());
+
+ assertEquals(120, duration.plusSeconds(60).getSeconds());
+ assertEquals(30, duration.minusSeconds(30).getSeconds());
+
+ assertEquals(120, duration.plus(60, ChronoUnit.SECONDS).getSeconds());
+ assertEquals(30, duration.minus(30, ChronoUnit.SECONDS).getSeconds());
+
+ Duration fromChar1 = Duration.parse("P1DT1H10M10.5S");
+ Duration fromChar2 = Duration.parse("PT10M");
+ }
+
+}
diff --git a/core-java/src/test/java/com/baeldung/dateapi/JavaPeriodTest.java b/core-java/src/test/java/com/baeldung/dateapi/JavaPeriodTest.java
new file mode 100644
index 0000000000..a0bede49b5
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/dateapi/JavaPeriodTest.java
@@ -0,0 +1,44 @@
+package com.baeldung.dateapi;
+
+import org.apache.log4j.Logger;
+import org.junit.Test;
+
+import java.time.LocalDate;
+import java.time.Period;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+public class JavaPeriodTest {
+
+ private static final Logger LOG = Logger.getLogger(JavaPeriodTest.class);
+
+ @Test
+ public void whenTestPeriod_thenOk() {
+
+ LocalDate startDate = LocalDate.of(2015, 2, 15);
+ LocalDate endDate = LocalDate.of(2017, 1, 21);
+
+ Period period = Period.between(startDate, endDate);
+
+ LOG.info(String.format("Years:%d months:%d days:%d", period.getYears(), period.getMonths(), period.getDays()));
+
+ assertFalse(period.isNegative());
+ assertEquals(56, period.plusDays(50).getDays());
+ assertEquals(9, period.minusMonths(2).getMonths());
+
+ Period fromUnits = Period.of(3, 10, 10);
+ Period fromDays = Period.ofDays(50);
+ Period fromMonths = Period.ofMonths(5);
+ Period fromYears = Period.ofYears(10);
+ Period fromWeeks = Period.ofWeeks(40);
+
+ assertEquals(280, fromWeeks.getDays());
+
+ Period fromCharYears = Period.parse("P2Y");
+ assertEquals(2, fromCharYears.getYears());
+ Period fromCharUnits = Period.parse("P2Y3M5D");
+ assertEquals(5, fromCharUnits.getDays());
+ }
+
+}
diff --git a/core-java/src/test/java/com/baeldung/dynamicproxy/DynamicProxyTest.java b/core-java/src/test/java/com/baeldung/dynamicproxy/DynamicProxyTest.java
new file mode 100644
index 0000000000..dc7f9366ba
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/dynamicproxy/DynamicProxyTest.java
@@ -0,0 +1,57 @@
+package com.baeldung.dynamicproxy;
+
+import org.junit.Test;
+
+import java.lang.reflect.Proxy;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class DynamicProxyTest {
+
+ @Test
+ public void givenDynamicProxy_thenPutWorks() {
+ Map proxyInstance = (Map) Proxy.newProxyInstance(DynamicProxyTest.class.getClassLoader(), new Class[] { Map.class }, new DynamicInvocationHandler());
+
+ proxyInstance.put("hello", "world");
+ }
+
+ @Test
+ public void givenInlineDynamicProxy_thenGetWorksOtherMethodsDoNot() {
+ Map proxyInstance = (Map) Proxy.newProxyInstance(DynamicProxyTest.class.getClassLoader(), new Class[] { Map.class }, (proxy, method, methodArgs) -> {
+
+ if (method.getName().equals("get")) {
+ return 42;
+ } else {
+ throw new UnsupportedOperationException("Unsupported method: " + method.getName());
+ }
+ });
+
+ int result = (int) proxyInstance.get("hello");
+
+ assertEquals(42, result);
+
+ try {
+ proxyInstance.put("hello", "world");
+ fail();
+ } catch(UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void givenTimingDynamicProxy_thenMethodInvokationsProduceTiming() {
+ Map mapProxyInstance = (Map) Proxy.newProxyInstance(DynamicProxyTest.class.getClassLoader(), new Class[] { Map.class }, new TimingDynamicInvocationHandler(new HashMap<>()));
+
+ mapProxyInstance.put("hello", "world");
+ assertEquals("world", mapProxyInstance.get("hello"));
+
+ CharSequence csProxyInstance = (CharSequence) Proxy.newProxyInstance(DynamicProxyTest.class.getClassLoader(), new Class[] { CharSequence.class }, new TimingDynamicInvocationHandler("Hello World"));
+
+ assertEquals('l', csProxyInstance.charAt(2));
+ assertEquals(11, csProxyInstance.length());
+ }
+
+}
diff --git a/core-java/src/test/java/com/baeldung/functionalinterface/FunctionalInterfaceUnitTest.java b/core-java/src/test/java/com/baeldung/functionalinterface/FunctionalInterfaceUnitTest.java
index 6f3384c8eb..1036df0bb8 100644
--- a/core-java/src/test/java/com/baeldung/functionalinterface/FunctionalInterfaceUnitTest.java
+++ b/core-java/src/test/java/com/baeldung/functionalinterface/FunctionalInterfaceUnitTest.java
@@ -1,8 +1,9 @@
package com.baeldung.functionalinterface;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import com.google.common.util.concurrent.Uninterruptibles;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.HashMap;
@@ -14,12 +15,13 @@ import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import org.junit.Test;
-
-import com.google.common.util.concurrent.Uninterruptibles;
+import static org.junit.Assert.*;
public class FunctionalInterfaceUnitTest {
+ private static final Logger LOG = LoggerFactory.getLogger(FunctionalInterfaceUnitTest.class);
+
+
@Test
public void whenPassingLambdaToComputeIfAbsent_thenTheValueGetsComputedAndPutIntoMap() {
Map nameMap = new HashMap<>();
@@ -65,7 +67,7 @@ public class FunctionalInterfaceUnitTest {
@Test
public void whenPassingLambdaToThreadConstructor_thenLambdaInferredToRunnable() {
- Thread thread = new Thread(() -> System.out.println("Hello From Another Thread"));
+ Thread thread = new Thread(() -> LOG.debug("Hello From Another Thread"));
thread.start();
}
@@ -93,7 +95,7 @@ public class FunctionalInterfaceUnitTest {
@Test
public void whenUsingConsumerInForEach_thenConsumerExecutesForEachListElement() {
List names = Arrays.asList("John", "Freddy", "Samuel");
- names.forEach(name -> System.out.println("Hello, " + name));
+ names.forEach(name -> LOG.debug("Hello, " + name));
}
@Test
@@ -103,7 +105,7 @@ public class FunctionalInterfaceUnitTest {
ages.put("Freddy", 24);
ages.put("Samuel", 30);
- ages.forEach((name, age) -> System.out.println(name + " is " + age + " years old"));
+ ages.forEach((name, age) -> LOG.debug(name + " is " + age + " years old"));
}
@Test
diff --git a/core-java/src/test/java/com/baeldung/http/HttpRequestTest.java b/core-java/src/test/java/com/baeldung/http/HttpRequestTest.java
new file mode 100644
index 0000000000..f238f7df7c
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/http/HttpRequestTest.java
@@ -0,0 +1,126 @@
+package com.baeldung.http;
+
+import org.apache.commons.lang.StringUtils;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.CookieManager;
+import java.net.HttpCookie;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+public class HttpRequestTest {
+
+ @Test
+ public void whenGetRequest_thenOk() throws IOException {
+ URL url = new URL("http://example.com");
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+
+ Map parameters = new HashMap<>();
+ parameters.put("param1", "val");
+ con.setDoOutput(true);
+ DataOutputStream out = new DataOutputStream(con.getOutputStream());
+ out.writeBytes(ParameterStringBuilder.getParamsString(parameters));
+ out.flush();
+ out.close();
+
+ con.setConnectTimeout(5000);
+ con.setReadTimeout(5000);
+
+ int status = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputLine;
+ StringBuffer content = new StringBuffer();
+ while ((inputLine = in.readLine()) != null) {
+ content.append(inputLine);
+ }
+ in.close();
+
+ assertEquals("status code incorrect", status, 200);
+ assertTrue("content incorrect", content.toString().contains("Example Domain"));
+ }
+
+ @Test
+ public void whenPostRequest_thenOk() throws IOException {
+ URL url = new URL("http://example.com");
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("POST");
+ con.setRequestProperty("Content-Type", "application/json");
+
+ Map parameters = new HashMap<>();
+ parameters.put("param1", "val");
+ con.setDoOutput(true);
+ DataOutputStream out = new DataOutputStream(con.getOutputStream());
+ out.writeBytes(ParameterStringBuilder.getParamsString(parameters));
+ out.flush();
+ out.close();
+
+ int status = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputLine;
+ StringBuffer content = new StringBuffer();
+ while ((inputLine = in.readLine()) != null) {
+ content.append(inputLine);
+ }
+ in.close();
+
+ assertEquals("status code incorrect", status, 200);
+ }
+
+ @Test
+ public void whenGetCookies_thenOk() throws IOException {
+ URL url = new URL("http://example.com");
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+
+ CookieManager cookieManager = new CookieManager();
+ String cookiesHeader = con.getHeaderField("Set-Cookie");
+ Optional usernameCookie = null;
+ if (cookiesHeader != null) {
+ List cookies = HttpCookie.parse(cookiesHeader);
+ cookies.forEach(cookie -> cookieManager.getCookieStore().add(null, cookie));
+ usernameCookie = cookies.stream().findAny().filter(cookie -> cookie.getName().equals("username"));
+ }
+
+ if (usernameCookie == null) {
+ cookieManager.getCookieStore().add(null, new HttpCookie("username", "john"));
+ }
+
+ con.disconnect();
+
+ con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("Cookie", StringUtils.join(cookieManager.getCookieStore().getCookies(), ";"));
+
+ int status = con.getResponseCode();
+
+ assertEquals("status code incorrect", status, 200);
+ }
+
+ @Test
+ public void whenRedirect_thenOk() throws IOException {
+ URL url = new URL("http://example.com");
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+
+ con.setInstanceFollowRedirects(true);
+ int status = con.getResponseCode();
+
+ if (status == HttpURLConnection.HTTP_MOVED_TEMP || status == HttpURLConnection.HTTP_MOVED_PERM) {
+ String location = con.getHeaderField("Location");
+ URL newUrl = new URL(location);
+ con = (HttpURLConnection) newUrl.openConnection();
+ }
+
+ assertEquals("status code incorrect", con.getResponseCode(), 200);
+ }
+
+}
diff --git a/core-java/src/test/java/com/baeldung/java/collections/ConcurrentModificationExceptionTest.java b/core-java/src/test/java/com/baeldung/java/collections/ConcurrentModificationExceptionTest.java
index 100d25ab8d..d12f07286b 100644
--- a/core-java/src/test/java/com/baeldung/java/collections/ConcurrentModificationExceptionTest.java
+++ b/core-java/src/test/java/com/baeldung/java/collections/ConcurrentModificationExceptionTest.java
@@ -6,9 +6,10 @@ import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import static java.util.Arrays.asList;
-import static org.testng.Assert.assertEquals;
+import static org.junit.Assert.assertEquals;
public class ConcurrentModificationExceptionTest {
+
@Test
public void changingContentWithSetDoesNotThrowConcurrentModificationException() throws Exception {
ArrayList
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
diff --git a/gson/pom.xml b/gson/pom.xml
index f2a2f4f930..285039f8f6 100644
--- a/gson/pom.xml
+++ b/gson/pom.xml
@@ -6,6 +6,12 @@
gson
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
diff --git a/guava/pom.xml b/guava/pom.xml
index 0edbb90efd..a21b432e98 100644
--- a/guava/pom.xml
+++ b/guava/pom.xml
@@ -6,6 +6,12 @@
guava
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
@@ -76,11 +82,6 @@
${org.slf4j.version}
-
- org.slf4j
- log4j-over-slf4j
- ${org.slf4j.version}
-
diff --git a/guava/src/test/java/org/baeldung/guava/ClassToInstanceMapTests.java b/guava/src/test/java/org/baeldung/guava/ClassToInstanceMapTests.java
new file mode 100644
index 0000000000..aef70aa72e
--- /dev/null
+++ b/guava/src/test/java/org/baeldung/guava/ClassToInstanceMapTests.java
@@ -0,0 +1,70 @@
+package org.baeldung.guava;
+import com.google.common.collect.ClassToInstanceMap;
+import com.google.common.collect.ImmutableClassToInstanceMap;
+import com.google.common.collect.MutableClassToInstanceMap;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class ClassToInstanceMapTests {
+ @Test
+ public void whenOfCalled_thenCreateEmptyImmutableMap() {
+ ClassToInstanceMap map = ImmutableClassToInstanceMap.of();
+ assertTrue(map.isEmpty());
+ }
+
+ @Test
+ public void whenCreateCalled_thenCreateEmptyMutableMap() {
+ ClassToInstanceMap map = MutableClassToInstanceMap.create();
+ assertTrue(map.isEmpty());
+ }
+
+ @Test
+ public void whenOfWithParameterCalled_thenCreateSingleEntryMap() {
+ ClassToInstanceMap map = ImmutableClassToInstanceMap.of(Save.class, new Save());
+ assertEquals(1, map.size());
+ }
+
+ @Test
+ public void whenBuilderUser_thenCreateMap() {
+ ClassToInstanceMap map = ImmutableClassToInstanceMap.builder()
+ .put(Save.class, new Save())
+ .put(Open.class, new Open())
+ .build();
+ assertEquals(2, map.size());
+ }
+
+ @Test
+ public void givenClassToInstanceMap_whenGetCalled_returnUpperBoundElement() {
+ ClassToInstanceMap map = ImmutableClassToInstanceMap.of(Save.class, new Save());
+ Action action = map.get(Save.class);
+ assertTrue(action instanceof Save);
+
+ // Use getInstance to avoid casting
+ Save save = map.getInstance(Save.class);
+ }
+
+ @Test
+ public void givenClassToInstanceMap_whenPutCalled_returnPreviousElementUpperBound() {
+ ClassToInstanceMap map = MutableClassToInstanceMap.create();
+ map.put(Save.class, new Save());
+ // Put again to get previous value returned
+ Action action = map.put(Save.class, new Save());
+ assertTrue(action instanceof Save);
+
+ // Use putInstance to avoid casting
+ Save save = map.putInstance(Save.class, new Save());
+ }
+}
+
+abstract class Action {
+}
+
+class Save extends Action {
+}
+
+class Open extends Action {
+}
+
+class Delete extends Action {
+}
diff --git a/guava/src/test/java/org/baeldung/guava/GuavaBigIntegerMathTest.java b/guava/src/test/java/org/baeldung/guava/GuavaBigIntegerMathTest.java
new file mode 100644
index 0000000000..4dd36fa58d
--- /dev/null
+++ b/guava/src/test/java/org/baeldung/guava/GuavaBigIntegerMathTest.java
@@ -0,0 +1,112 @@
+package org.baeldung.guava;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.math.BigInteger;
+import java.math.RoundingMode;
+
+import org.junit.Test;
+
+import com.google.common.math.BigIntegerMath;
+
+public class GuavaBigIntegerMathTest {
+
+ @Test
+ public void whenPerformBinomialOnTwoIntValues_shouldReturnResult() {
+ BigInteger result = BigIntegerMath.binomial(6, 3);
+ assertEquals(new BigInteger("20"), result);
+ }
+
+ @Test
+ public void whenProformCeilPowOfTwoBigIntegerValues_shouldReturnResult() {
+ BigInteger result = BigIntegerMath.ceilingPowerOfTwo(new BigInteger("20"));
+ assertEquals(new BigInteger("32"), result);
+ }
+
+ @Test
+ public void whenDivideTwoBigIntegerValues_shouldDivideThemAndReturnTheResultForCeilingRounding() {
+ BigInteger result = BigIntegerMath.divide(new BigInteger("10"), new BigInteger("3"), RoundingMode.CEILING);
+ assertEquals(new BigInteger("4"), result);
+ }
+
+ @Test
+ public void whenDivideTwoBigIntegerValues_shouldDivideThemAndReturnTheResultForFloorRounding() {
+ BigInteger result = BigIntegerMath.divide(new BigInteger("10"), new BigInteger("3"), RoundingMode.FLOOR);
+ assertEquals(new BigInteger("3"), result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void whenDivideTwoBigIntegerValues_shouldThrowArithmeticExceptionIfRoundingNotDefinedButNecessary() {
+ BigIntegerMath.divide(new BigInteger("10"), new BigInteger("3"), RoundingMode.UNNECESSARY);
+ }
+
+ @Test
+ public void whenFactorailInteger_shouldFactorialThemAndReturnTheResultIfInIntRange() {
+ BigInteger result = BigIntegerMath.factorial(5);
+ assertEquals(new BigInteger("120"), result);
+ }
+
+ @Test
+ public void whenFloorPowerOfInteger_shouldReturnValue() {
+ BigInteger result = BigIntegerMath.floorPowerOfTwo(new BigInteger("30"));
+ assertEquals(new BigInteger("16"), result);
+ }
+
+ @Test
+ public void whenIsPowOfInteger_shouldReturnTrueIfPowerOfTwo() {
+ boolean result = BigIntegerMath.isPowerOfTwo(new BigInteger("16"));
+ assertTrue(result);
+ }
+
+ @Test
+ public void whenLog10BigIntegerValues_shouldLog10ThemAndReturnTheResultForCeilingRounding() {
+ int result = BigIntegerMath.log10(new BigInteger("30"), RoundingMode.CEILING);
+ assertEquals(2, result);
+ }
+
+ @Test
+ public void whenLog10BigIntegerValues_shouldog10ThemAndReturnTheResultForFloorRounding() {
+ int result = BigIntegerMath.log10(new BigInteger("30"), RoundingMode.FLOOR);
+ assertEquals(1, result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void whenLog10BigIntegerValues_shouldThrowArithmeticExceptionIfRoundingNotDefinedButNecessary() {
+ BigIntegerMath.log10(new BigInteger("30"), RoundingMode.UNNECESSARY);
+ }
+
+ @Test
+ public void whenLog2BigIntegerValues_shouldLog2ThemAndReturnTheResultForCeilingRounding() {
+ int result = BigIntegerMath.log2(new BigInteger("30"), RoundingMode.CEILING);
+ assertEquals(5, result);
+ }
+
+ @Test
+ public void whenLog2BigIntegerValues_shouldog2ThemAndReturnTheResultForFloorRounding() {
+ int result = BigIntegerMath.log2(new BigInteger("30"), RoundingMode.FLOOR);
+ assertEquals(4, result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void whenLog2BigIntegerValues_shouldThrowArithmeticExceptionIfRoundingNotDefinedButNecessary() {
+ BigIntegerMath.log2(new BigInteger("30"), RoundingMode.UNNECESSARY);
+ }
+
+ @Test
+ public void whenSqrtBigIntegerValues_shouldSqrtThemAndReturnTheResultForCeilingRounding() {
+ BigInteger result = BigIntegerMath.sqrt(new BigInteger("30"), RoundingMode.CEILING);
+ assertEquals(new BigInteger("6"), result);
+ }
+
+ @Test
+ public void whenSqrtBigIntegerValues_shouldSqrtThemAndReturnTheResultForFloorRounding() {
+ BigInteger result = BigIntegerMath.sqrt(new BigInteger("30"), RoundingMode.FLOOR);
+ assertEquals(new BigInteger("5"), result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void whenSqrtBigIntegerValues_shouldThrowArithmeticExceptionIfRoundingNotDefinedButNecessary() {
+ BigIntegerMath.sqrt(new BigInteger("30"), RoundingMode.UNNECESSARY);
+ }
+}
diff --git a/guava/src/test/java/org/baeldung/guava/GuavaDoubleMathTest.java b/guava/src/test/java/org/baeldung/guava/GuavaDoubleMathTest.java
new file mode 100644
index 0000000000..ad06b37e36
--- /dev/null
+++ b/guava/src/test/java/org/baeldung/guava/GuavaDoubleMathTest.java
@@ -0,0 +1,98 @@
+package org.baeldung.guava;
+
+import static org.junit.Assert.*;
+
+import java.math.RoundingMode;
+
+import org.junit.Test;
+
+import com.google.common.math.DoubleMath;
+import com.google.common.math.IntMath;
+
+public class GuavaDoubleMathTest {
+
+ @Test
+ public void whenFactorailDouble_shouldFactorialThemAndReturnTheResultIfInDoubleRange() {
+ double result = DoubleMath.factorial(5);
+ assertEquals(120, result, 0);
+ }
+
+ @Test
+ public void whenFactorailDouble_shouldFactorialThemAndReturnDoubkeInfIfNotInDoubletRange() {
+ double result = DoubleMath.factorial(Integer.MAX_VALUE);
+ assertEquals(Double.POSITIVE_INFINITY, result, 0);
+ }
+
+ @Test
+ public void whenFuzzyCompareDouble_shouldReturnZeroIfInRange() {
+ int result = DoubleMath.fuzzyCompare(4, 4.05, 0.6);
+ assertEquals(0, result);
+ }
+
+ @Test
+ public void whenFuzzyCompareDouble_shouldReturnNonZeroIfNotInRange() {
+ int result = DoubleMath.fuzzyCompare(4, 5, 0.1);
+ assertEquals(-1, result);
+ }
+
+ @Test
+ public void whenFuzzyEqualDouble_shouldReturnZeroIfInRange() {
+ boolean result = DoubleMath.fuzzyEquals(4, 4.05, 0.6);
+ assertTrue(result);
+ }
+
+ @Test
+ public void whenFuzzyEqualDouble_shouldReturnNonZeroIfNotInRange() {
+ boolean result = DoubleMath.fuzzyEquals(4, 5, 0.1);
+ assertFalse(result);
+ }
+
+ @Test
+ public void whenMathematicalIntDouble_shouldReturnTrueIfInRange() {
+ boolean result = DoubleMath.isMathematicalInteger(5);
+ assertTrue(result);
+ }
+
+ @Test
+ public void whenMathematicalIntDouble_shouldReturnFalseIfNotInRange() {
+ boolean result = DoubleMath.isMathematicalInteger(5.2);
+ assertFalse(result);
+ }
+
+ @Test
+ public void whenIsPowerOfTwoDouble_shouldReturnTrueIfIsPowerOfTwo() {
+ boolean result = DoubleMath.isMathematicalInteger(4);
+ assertTrue(result);
+ }
+
+ @Test
+ public void whenIsPowerOfTwoDouble_shouldReturnFalseIsNotPowerOfTwoe() {
+ boolean result = DoubleMath.isMathematicalInteger(5.2);
+ assertFalse(result);
+ }
+
+ @Test
+ public void whenLog2Double_shouldReturnResult() {
+ double result = DoubleMath.log2(4);
+ assertEquals(2, result, 0);
+ }
+
+
+ @Test
+ public void whenLog2DoubleValues_shouldLog2ThemAndReturnTheResultForCeilingRounding() {
+ int result = DoubleMath.log2(30, RoundingMode.CEILING);
+ assertEquals(5, result);
+ }
+
+ @Test
+ public void whenLog2DoubleValues_shouldog2ThemAndReturnTheResultForFloorRounding() {
+ int result = DoubleMath.log2(30, RoundingMode.FLOOR);
+ assertEquals(4, result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void whenLog2DoubleValues_shouldThrowArithmeticExceptionIfRoundingNotDefinedButNecessary() {
+ DoubleMath.log2(30, RoundingMode.UNNECESSARY);
+ }
+
+}
diff --git a/guava/src/test/java/org/baeldung/guava/GuavaEventBusTest.java b/guava/src/test/java/org/baeldung/guava/GuavaEventBusTest.java
index 1390eb05aa..0ff25c6df2 100644
--- a/guava/src/test/java/org/baeldung/guava/GuavaEventBusTest.java
+++ b/guava/src/test/java/org/baeldung/guava/GuavaEventBusTest.java
@@ -44,11 +44,10 @@ public class GuavaEventBusTest {
}
@Test
- public void givenUnSubscribedEvent_whenEventHandledByDeadEvent_thenSuccess() throws InterruptedException {
+ public void givenUnSubscribedEvent_whenEventHandledByDeadEvent_thenSuccess() {
listener.resetEventsHandled();
eventBus.post(12345);
-
assertEquals(1, listener.getEventsHandled());
}
diff --git a/guava/src/test/java/org/baeldung/guava/GuavaIntMathTest.java b/guava/src/test/java/org/baeldung/guava/GuavaIntMathTest.java
new file mode 100644
index 0000000000..9c8f3923d3
--- /dev/null
+++ b/guava/src/test/java/org/baeldung/guava/GuavaIntMathTest.java
@@ -0,0 +1,274 @@
+package org.baeldung.guava;
+
+import static org.junit.Assert.*;
+
+import java.math.RoundingMode;
+
+import com.google.common.math.IntMath;
+import org.junit.Test;
+
+public class GuavaIntMathTest {
+
+ @Test
+ public void whenPerformBinomialOnTwoIntegerValues_shouldReturnResultIfUnderInt() {
+ int result = IntMath.binomial(6, 3);
+ assertEquals(20, result);
+ }
+
+ @Test
+ public void whenPerformBinomialOnTwoIntegerValues_shouldReturnIntMaxIfUnderInt() {
+ int result = IntMath.binomial(Integer.MAX_VALUE, 3);
+ assertEquals(Integer.MAX_VALUE, result);
+ }
+
+ @Test
+ public void whenProformCeilPowOfTwoIntegerValues_shouldReturnResult() {
+ int result = IntMath.ceilingPowerOfTwo(20);
+ assertEquals(32, result);
+ }
+
+ @Test
+ public void whenCheckedAddTwoIntegerValues_shouldAddThemAndReturnTheSumIfNotOverflow() {
+ int result = IntMath.checkedAdd(1, 2);
+ assertEquals(3, result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void gwhenCheckedAddTwoIntegerValues_shouldThrowArithmeticExceptionIfOverflow() {
+ IntMath.checkedAdd(Integer.MAX_VALUE, 100);
+ }
+
+ @Test
+ public void whenCheckedMultiplyTwoIntegerValues_shouldMultiplyThemAndReturnTheResultIfNotOverflow() {
+ int result = IntMath.checkedMultiply(1, 2);
+ assertEquals(2, result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void gwhenCheckedMultiplyTwoIntegerValues_shouldThrowArithmeticExceptionIfOverflow() {
+ IntMath.checkedMultiply(Integer.MAX_VALUE, 100);
+ }
+
+ @Test
+ public void whenCheckedPowTwoIntegerValues_shouldPowThemAndReturnTheResultIfNotOverflow() {
+ int result = IntMath.checkedPow(2, 3);
+ assertEquals(8, result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void gwhenCheckedPowTwoIntegerValues_shouldThrowArithmeticExceptionIfOverflow() {
+ IntMath.checkedPow(Integer.MAX_VALUE, 100);
+ }
+
+ @Test
+ public void whenCheckedSubstractTwoIntegerValues_shouldSubstractThemAndReturnTheResultIfNotOverflow() {
+ int result = IntMath.checkedSubtract(4, 1);
+ assertEquals(3, result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void gwhenCheckedSubstractTwoIntegerValues_shouldThrowArithmeticExceptionIfOverflow() {
+ IntMath.checkedSubtract(Integer.MAX_VALUE, -100);
+ }
+
+ @Test
+ public void whenDivideTwoIntegerValues_shouldDivideThemAndReturnTheResultForCeilingRounding() {
+ int result = IntMath.divide(10, 3, RoundingMode.CEILING);
+ assertEquals(4, result);
+ }
+
+ @Test
+ public void whenDivideTwoIntegerValues_shouldDivideThemAndReturnTheResultForFloorRounding() {
+ int result = IntMath.divide(10, 3, RoundingMode.FLOOR);
+ assertEquals(3, result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void whenDivideTwoIntegerValues_shouldThrowArithmeticExceptionIfRoundingNotDefinedButNecessary() {
+ IntMath.divide(10, 3, RoundingMode.UNNECESSARY);
+ }
+
+ @Test
+ public void whenFactorailInteger_shouldFactorialThemAndReturnTheResultIfInIntRange() {
+ int result = IntMath.factorial(5);
+ assertEquals(120, result);
+ }
+
+ @Test
+ public void whenFactorailInteger_shouldFactorialThemAndReturnIntMaxIfNotInIntRange() {
+ int result = IntMath.factorial(Integer.MAX_VALUE);
+ assertEquals(Integer.MAX_VALUE, result);
+ }
+
+ @Test
+ public void whenFloorPowerOfInteger_shouldReturnValue() {
+ int result = IntMath.floorPowerOfTwo(30);
+ assertEquals(16, result);
+ }
+
+ @Test
+ public void whenGcdOfTwoIntegers_shouldReturnValue() {
+ int result = IntMath.gcd(30, 40);
+ assertEquals(10, result);
+ }
+
+ @Test
+ public void whenIsPowOfInteger_shouldReturnTrueIfPowerOfTwo() {
+ boolean result = IntMath.isPowerOfTwo(16);
+ assertTrue(result);
+ }
+
+ @Test
+ public void whenIsPowOfInteger_shouldReturnFalseeIfNotPowerOfTwo() {
+ boolean result = IntMath.isPowerOfTwo(20);
+ assertFalse(result);
+ }
+
+ @Test
+ public void whenIsPrineOfInteger_shouldReturnFalseeIfNotPrime() {
+ boolean result = IntMath.isPrime(20);
+ assertFalse(result);
+ }
+
+ @Test
+ public void whenLog10IntegerValues_shouldLog10ThemAndReturnTheResultForCeilingRounding() {
+ int result = IntMath.log10(30, RoundingMode.CEILING);
+ assertEquals(2, result);
+ }
+
+ @Test
+ public void whenLog10IntegerValues_shouldog10ThemAndReturnTheResultForFloorRounding() {
+ int result = IntMath.log10(30, RoundingMode.FLOOR);
+ assertEquals(1, result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void whenLog10IntegerValues_shouldThrowArithmeticExceptionIfRoundingNotDefinedButNecessary() {
+ IntMath.log10(30, RoundingMode.UNNECESSARY);
+ }
+
+ @Test
+ public void whenLog2IntegerValues_shouldLog2ThemAndReturnTheResultForCeilingRounding() {
+ int result = IntMath.log2(30, RoundingMode.CEILING);
+ assertEquals(5, result);
+ }
+
+ @Test
+ public void whenLog2IntegerValues_shouldog2ThemAndReturnTheResultForFloorRounding() {
+ int result = IntMath.log2(30, RoundingMode.FLOOR);
+ assertEquals(4, result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void whenLog2IntegerValues_shouldThrowArithmeticExceptionIfRoundingNotDefinedButNecessary() {
+ IntMath.log2(30, RoundingMode.UNNECESSARY);
+ }
+
+ @Test
+ public void whenMeanTwoIntegerValues_shouldMeanThemAndReturnTheResult() {
+ int result = IntMath.mean(30, 20);
+ assertEquals(25, result);
+ }
+
+ @Test
+ public void whenModTwoIntegerValues_shouldModThemAndReturnTheResult() {
+ int result = IntMath.mod(30, 4);
+ assertEquals(2, result);
+ }
+
+ @Test
+ public void whenPowTwoIntegerValues_shouldPowThemAndReturnTheResult() {
+ int result = IntMath.pow(6, 4);
+ assertEquals(1296, result);
+ }
+
+ @Test
+ public void whenSaturatedAddTwoIntegerValues_shouldAddThemAndReturnTheResult() {
+ int result = IntMath.saturatedAdd(6, 4);
+ assertEquals(10, result);
+ }
+
+ @Test
+ public void whenSaturatedAddTwoIntegerValues_shouldAddThemAndReturnIntMaxIfOverflow() {
+ int result = IntMath.saturatedAdd(Integer.MAX_VALUE, 1000);
+ assertEquals(Integer.MAX_VALUE, result);
+ }
+
+ @Test
+ public void whenSaturatedAddTwoIntegerValues_shouldAddThemAndReturnIntMinIfUnderflow() {
+ int result = IntMath.saturatedAdd(Integer.MIN_VALUE, -1000);
+ assertEquals(Integer.MIN_VALUE, result);
+ }
+
+ @Test
+ public void whenSaturatedMultiplyTwoIntegerValues_shouldMultiplyThemAndReturnTheResult() {
+ int result = IntMath.saturatedMultiply(6, 4);
+ assertEquals(24, result);
+ }
+
+ @Test
+ public void whenSaturatedMultiplyTwoIntegerValues_shouldMultiplyThemAndReturnIntMaxIfOverflow() {
+ int result = IntMath.saturatedMultiply(Integer.MAX_VALUE, 1000);
+ assertEquals(Integer.MAX_VALUE, result);
+ }
+
+ @Test
+ public void whenSaturatedMultiplyTwoIntegerValues_shouldMultiplyThemAndReturnIntMinIfUnderflow() {
+ int result = IntMath.saturatedMultiply(Integer.MIN_VALUE, 1000);
+ assertEquals(Integer.MIN_VALUE, result);
+ }
+
+ @Test
+ public void whenSaturatedPowTwoIntegerValues_shouldPowThemAndReturnTheResult() {
+ int result = IntMath.saturatedPow(6, 2);
+ assertEquals(36, result);
+ }
+
+ @Test
+ public void whenSaturatedPowTwoIntegerValues_shouldPowThemAndReturnIntMaxIfOverflow() {
+ int result = IntMath.saturatedPow(Integer.MAX_VALUE, 2);
+ assertEquals(Integer.MAX_VALUE, result);
+ }
+
+ @Test
+ public void whenSaturatedPowTwoIntegerValues_shouldPowThemAndReturnIntMinIfUnderflow() {
+ int result = IntMath.saturatedPow(Integer.MIN_VALUE, 3);
+ assertEquals(Integer.MIN_VALUE, result);
+ }
+
+ @Test
+ public void whenSaturatedSubstractTwoIntegerValues_shouldSubstractThemAndReturnTheResult() {
+ int result = IntMath.saturatedSubtract(6, 2);
+ assertEquals(4, result);
+ }
+
+ @Test
+ public void whenSaturatedSubstractTwoIntegerValues_shouldSubstractwThemAndReturnIntMaxIfOverflow() {
+ int result = IntMath.saturatedSubtract(Integer.MAX_VALUE, -2);
+ assertEquals(Integer.MAX_VALUE, result);
+ }
+
+ @Test
+ public void whenSaturatedSubstractTwoIntegerValues_shouldSubstractThemAndReturnIntMinIfUnderflow() {
+ int result = IntMath.saturatedSubtract(Integer.MIN_VALUE, 3);
+ assertEquals(Integer.MIN_VALUE, result);
+ }
+
+ @Test
+ public void whenSqrtIntegerValues_shouldSqrtThemAndReturnTheResultForCeilingRounding() {
+ int result = IntMath.sqrt(30, RoundingMode.CEILING);
+ assertEquals(6, result);
+ }
+
+ @Test
+ public void whenSqrtIntegerValues_shouldSqrtThemAndReturnTheResultForFloorRounding() {
+ int result = IntMath.sqrt(30, RoundingMode.FLOOR);
+ assertEquals(5, result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void whenSqrtIntegerValues_shouldThrowArithmeticExceptionIfRoundingNotDefinedButNecessary() {
+ IntMath.sqrt(30, RoundingMode.UNNECESSARY);
+ }
+
+}
diff --git a/guava/src/test/java/org/baeldung/guava/GuavaLongMathTest.java b/guava/src/test/java/org/baeldung/guava/GuavaLongMathTest.java
new file mode 100644
index 0000000000..5d6d06c571
--- /dev/null
+++ b/guava/src/test/java/org/baeldung/guava/GuavaLongMathTest.java
@@ -0,0 +1,268 @@
+package org.baeldung.guava;
+
+import static org.junit.Assert.*;
+
+import java.math.RoundingMode;
+
+import com.google.common.math.LongMath;
+import org.junit.Test;
+
+public class GuavaLongMathTest {
+
+ @Test
+ public void whenPerformBinomialOnTwoLongValues_shouldReturnResultIfUnderLong() {
+ long result = LongMath.binomial(6, 3);
+ assertEquals(20L, result);
+ }
+
+ @Test
+ public void whenProformCeilPowOfTwoLongValues_shouldReturnResult() {
+ long result = LongMath.ceilingPowerOfTwo(20L);
+ assertEquals(32L, result);
+ }
+
+ @Test
+ public void whenCheckedAddTwoLongValues_shouldAddThemAndReturnTheSumIfNotOverflow() {
+ long result = LongMath.checkedAdd(1L, 2L);
+ assertEquals(3L, result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void whenCheckedAddTwoLongValues_shouldThrowArithmeticExceptionIfOverflow() {
+ LongMath.checkedAdd(Long.MAX_VALUE, 100L);
+ }
+
+ @Test
+ public void whenCheckedMultiplyTwoLongValues_shouldMultiplyThemAndReturnTheResultIfNotOverflow() {
+ long result = LongMath.checkedMultiply(3L, 2L);
+ assertEquals(6L, result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void whenCheckedMultiplyTwoLongValues_shouldThrowArithmeticExceptionIfOverflow() {
+ LongMath.checkedMultiply(Long.MAX_VALUE, 100L);
+ }
+
+ @Test
+ public void whenCheckedPowTwoLongValues_shouldPowThemAndReturnTheResultIfNotOverflow() {
+ long result = LongMath.checkedPow(2L, 3);
+ assertEquals(8L, result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void gwhenCheckedPowTwoLongValues_shouldThrowArithmeticExceptionIfOverflow() {
+ LongMath.checkedPow(Long.MAX_VALUE, 100);
+ }
+
+ @Test
+ public void whenCheckedSubstractTwoLongValues_shouldSubstractThemAndReturnTheResultIfNotOverflow() {
+ long result = LongMath.checkedSubtract(4L, 1L);
+ assertEquals(3L, result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void gwhenCheckedSubstractTwoLongValues_shouldThrowArithmeticExceptionIfOverflow() {
+ LongMath.checkedSubtract(Long.MAX_VALUE, -100);
+ }
+
+ @Test
+ public void whenDivideTwoLongValues_shouldDivideThemAndReturnTheResultForCeilingRounding() {
+ long result = LongMath.divide(10L, 3L, RoundingMode.CEILING);
+ assertEquals(4L, result);
+ }
+
+ @Test
+ public void whenDivideTwoLongValues_shouldDivideThemAndReturnTheResultForFloorRounding() {
+ long result = LongMath.divide(10L, 3L, RoundingMode.FLOOR);
+ assertEquals(3L, result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void whenDivideTwoLongValues_shouldThrowArithmeticExceptionIfRoundingNotDefinedButNecessary() {
+ LongMath.divide(10L, 3L, RoundingMode.UNNECESSARY);
+ }
+
+ @Test
+ public void whenFactorailLong_shouldFactorialThemAndReturnTheResultIfInIntRange() {
+ long result = LongMath.factorial(5);
+ assertEquals(120L, result);
+ }
+
+ @Test
+ public void whenFactorailLong_shouldFactorialThemAndReturnIntMaxIfNotInIntRange() {
+ long result = LongMath.factorial(Integer.MAX_VALUE);
+ assertEquals(Long.MAX_VALUE, result);
+ }
+
+ @Test
+ public void whenFloorPowerOfLong_shouldReturnValue() {
+ long result = LongMath.floorPowerOfTwo(30L);
+ assertEquals(16L, result);
+ }
+
+ @Test
+ public void whenGcdOfTwoLongs_shouldReturnValue() {
+ long result = LongMath.gcd(30L, 40L);
+ assertEquals(10L, result);
+ }
+
+ @Test
+ public void whenIsPowOfLong_shouldReturnTrueIfPowerOfTwo() {
+ boolean result = LongMath.isPowerOfTwo(16L);
+ assertTrue(result);
+ }
+
+ @Test
+ public void whenIsPowOfLong_shouldReturnFalseeIfNotPowerOfTwo() {
+ boolean result = LongMath.isPowerOfTwo(20L);
+ assertFalse(result);
+ }
+
+ @Test
+ public void whenIsPrineOfLong_shouldReturnFalseeIfNotPrime() {
+ boolean result = LongMath.isPrime(20L);
+ assertFalse(result);
+ }
+
+ @Test
+ public void whenLog10LongValues_shouldLog10ThemAndReturnTheResultForCeilingRounding() {
+ int result = LongMath.log10(30L, RoundingMode.CEILING);
+ assertEquals(2, result);
+ }
+
+ @Test
+ public void whenLog10LongValues_shouldog10ThemAndReturnTheResultForFloorRounding() {
+ int result = LongMath.log10(30L, RoundingMode.FLOOR);
+ assertEquals(1, result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void whenLog10LongValues_shouldThrowArithmeticExceptionIfRoundingNotDefinedButNecessary() {
+ LongMath.log10(30L, RoundingMode.UNNECESSARY);
+ }
+
+ @Test
+ public void whenLog2LongValues_shouldLog2ThemAndReturnTheResultForCeilingRounding() {
+ int result = LongMath.log2(30L, RoundingMode.CEILING);
+ assertEquals(5, result);
+ }
+
+ @Test
+ public void whenLog2LongValues_shouldog2ThemAndReturnTheResultForFloorRounding() {
+ int result = LongMath.log2(30L, RoundingMode.FLOOR);
+ assertEquals(4, result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void whenLog2LongValues_shouldThrowArithmeticExceptionIfRoundingNotDefinedButNecessary() {
+ LongMath.log2(30L, RoundingMode.UNNECESSARY);
+ }
+
+ @Test
+ public void whenMeanTwoLongValues_shouldMeanThemAndReturnTheResult() {
+ long result = LongMath.mean(30L, 20L);
+ assertEquals(25L, result);
+ }
+
+ @Test
+ public void whenModLongAndIntegerValues_shouldModThemAndReturnTheResult() {
+ int result = LongMath.mod(30L, 4);
+ assertEquals(2, result);
+ }
+
+ @Test
+ public void whenModTwoLongValues_shouldModThemAndReturnTheResult() {
+ long result = LongMath.mod(30L, 4L);
+ assertEquals(2L, result);
+ }
+
+ @Test
+ public void whenPowTwoLongValues_shouldPowThemAndReturnTheResult() {
+ long result = LongMath.pow(6L, 4);
+ assertEquals(1296L, result);
+ }
+
+ @Test
+ public void whenSaturatedAddTwoLongValues_shouldAddThemAndReturnTheResult() {
+ long result = LongMath.saturatedAdd(6L, 4L);
+ assertEquals(10L, result);
+ }
+
+ @Test
+ public void whenSaturatedAddTwoLongValues_shouldAddThemAndReturnIntMaxIfOverflow() {
+ long result = LongMath.saturatedAdd(Long.MAX_VALUE, 1000L);
+ assertEquals(Long.MAX_VALUE, result);
+ }
+
+ @Test
+ public void whenSaturatedAddTwoLongValues_shouldAddThemAndReturnIntMinIfUnderflow() {
+ long result = LongMath.saturatedAdd(Long.MIN_VALUE, -1000);
+ assertEquals(Long.MIN_VALUE, result);
+ }
+
+ @Test
+ public void whenSaturatedMultiplyTwoLongValues_shouldMultiplyThemAndReturnTheResult() {
+ long result = LongMath.saturatedMultiply(6L, 4L);
+ assertEquals(24L, result);
+ }
+
+ @Test
+ public void whenSaturatedMultiplyTwoLongValues_shouldMultiplyThemAndReturnIntMaxIfOverflow() {
+ long result = LongMath.saturatedMultiply(Long.MAX_VALUE, 1000L);
+ assertEquals(Long.MAX_VALUE, result);
+ }
+
+ @Test
+ public void whenSaturatedPowTwoLongValues_shouldPowThemAndReturnTheResult() {
+ long result = LongMath.saturatedPow(6L, 2);
+ assertEquals(36L, result);
+ }
+
+ @Test
+ public void whenSaturatedPowTwoLongValues_shouldPowThemAndReturnIntMaxIfOverflow() {
+ long result = LongMath.saturatedPow(Long.MAX_VALUE, 2);
+ assertEquals(Long.MAX_VALUE, result);
+ }
+
+ @Test
+ public void whenSaturatedPowTwoLongValues_shouldPowThemAndReturnIntMinIfUnderflow() {
+ long result = LongMath.saturatedPow(Long.MIN_VALUE, 3);
+ assertEquals(Long.MIN_VALUE, result);
+ }
+
+ @Test
+ public void whenSaturatedSubstractTwoLongValues_shouldSubstractThemAndReturnTheResult() {
+ long result = LongMath.saturatedSubtract(6L, 2L);
+ assertEquals(4L, result);
+ }
+
+ @Test
+ public void whenSaturatedSubstractTwoLongValues_shouldSubstractwThemAndReturnIntMaxIfOverflow() {
+ long result = LongMath.saturatedSubtract(Long.MAX_VALUE, -2L);
+ assertEquals(Long.MAX_VALUE, result);
+ }
+
+ @Test
+ public void whenSaturatedSubstractTwoLongValues_shouldSubstractThemAndReturnIntMinIfUnderflow() {
+ long result = LongMath.saturatedSubtract(Long.MIN_VALUE, 3L);
+ assertEquals(Long.MIN_VALUE, result);
+ }
+
+ @Test
+ public void whenSqrtLongValues_shouldSqrtThemAndReturnTheResultForCeilingRounding() {
+ long result = LongMath.sqrt(30L, RoundingMode.CEILING);
+ assertEquals(6L, result);
+ }
+
+ @Test
+ public void whenSqrtLongValues_shouldSqrtThemAndReturnTheResultForFloorRounding() {
+ long result = LongMath.sqrt(30L, RoundingMode.FLOOR);
+ assertEquals(5L, result);
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void whenSqrtLongValues_shouldThrowArithmeticExceptionIfRoundingNotDefinedButNecessary() {
+ LongMath.sqrt(30L, RoundingMode.UNNECESSARY);
+ }
+
+}
diff --git a/guava18/pom.xml b/guava18/pom.xml
index 1118a13e07..34e1677642 100644
--- a/guava18/pom.xml
+++ b/guava18/pom.xml
@@ -7,6 +7,12 @@
guava180.1.0-SNAPSHOT
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
com.google.guava
diff --git a/guava19/pom.xml b/guava19/pom.xml
index 75f87ccf4f..536f809e3b 100644
--- a/guava19/pom.xml
+++ b/guava19/pom.xml
@@ -7,6 +7,12 @@
guava190.1.0-SNAPSHOT
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
com.google.guava
diff --git a/guava21/README.md b/guava21/README.md
index ff12555376..8725352d69 100644
--- a/guava21/README.md
+++ b/guava21/README.md
@@ -1 +1,2 @@
-## Relevant articles:
+### Relevant articles:
+- [New Stream, Comparator and Collector Functionality in Guava 21](http://www.baeldung.com/guava-21-new)
diff --git a/guava21/pom.xml b/guava21/pom.xml
index f393c65aec..b327bd7890 100644
--- a/guava21/pom.xml
+++ b/guava21/pom.xml
@@ -7,6 +7,13 @@
com.baeldung.guavatutorial1.0-SNAPSHOT
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
diff --git a/guava21/src/test/java/GauavaStreamsTests.java b/guava21/src/test/java/GuavaStreamsTests.java
similarity index 99%
rename from guava21/src/test/java/GauavaStreamsTests.java
rename to guava21/src/test/java/GuavaStreamsTests.java
index 1482d685cf..cc5fcff229 100644
--- a/guava21/src/test/java/GauavaStreamsTests.java
+++ b/guava21/src/test/java/GuavaStreamsTests.java
@@ -9,7 +9,7 @@ import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
-public class GauavaStreamsTests {
+public class GuavaStreamsTests {
List numbers;
diff --git a/guice/pom.xml b/guice/pom.xml
index df87021794..942ec33af6 100644
--- a/guice/pom.xml
+++ b/guice/pom.xml
@@ -5,6 +5,13 @@
guice1.0-SNAPSHOTjar
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
com.google.inject
diff --git a/handling-spring-static-resources/pom.xml b/handling-spring-static-resources/pom.xml
index 9a14ce9372..7cb79252ad 100644
--- a/handling-spring-static-resources/pom.xml
+++ b/handling-spring-static-resources/pom.xml
@@ -9,6 +9,12 @@
spring-static-resources
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
@@ -155,11 +161,6 @@
${org.slf4j.version}
-
- org.slf4j
- log4j-over-slf4j
- ${org.slf4j.version}
-
diff --git a/hazelcast/pom.xml b/hazelcast/pom.xml
index 91e2cd2c61..a73cc834e6 100644
--- a/hazelcast/pom.xml
+++ b/hazelcast/pom.xml
@@ -6,6 +6,12 @@
0.0.1-SNAPSHOThazelcast
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
com.hazelcast
diff --git a/hbase/pom.xml b/hbase/pom.xml
index 9d523abf1a..c692054f0f 100644
--- a/hbase/pom.xml
+++ b/hbase/pom.xml
@@ -28,6 +28,12 @@
org.apache.hbasehbase-client${hbase.version}
+
+
+ commons-logging
+ commons-logging
+
+ org.apache.hbase
diff --git a/hibernate5/pom.xml b/hibernate5/pom.xml
new file mode 100644
index 0000000000..32712fba2a
--- /dev/null
+++ b/hibernate5/pom.xml
@@ -0,0 +1,75 @@
+
+
+ 4.0.0
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+ com.baeldung
+ hibernate5
+ 0.0.1-SNAPSHOT
+ hibernate5
+ http://maven.apache.org
+
+ UTF-8
+
+ 3.6.0
+
+
+
+ org.hibernate
+ hibernate-core
+ 5.2.9.Final
+
+
+ junit
+ junit
+ 4.12
+
+
+ com.h2database
+ h2
+ 1.4.194
+
+
+
+ hibernate5
+
+
+ src/main/resources
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+ 1.8
+ 1.8
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ 3
+ true
+
+ **/*IntegrationTest.java
+ **/*LiveTest.java
+
+
+
+
+
+
+
+
+
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/App.java b/hibernate5/src/main/java/com/baeldung/hibernate/App.java
new file mode 100644
index 0000000000..26a40bb782
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/App.java
@@ -0,0 +1,30 @@
+package com.baeldung.hibernate;
+
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+
+import com.baeldung.hibernate.pojo.Supplier;
+
+/**
+ * Hello world!
+ *
+ */
+public class App {
+ public static void main(String[] args) {
+ try {
+ // NOTE: this is just for boostrap testing for multitenancy.
+ System.out.println("Checking the system.");
+ SessionFactory sessionFactory = HibernateMultiTenantUtil.getSessionFactory();
+ Session currentSession = sessionFactory.withOptions().tenantIdentifier("h2db1").openSession();
+ Transaction transaction = currentSession.getTransaction();
+ transaction.begin();
+ currentSession.createCriteria(Supplier.class).list().stream().forEach(System.out::println);
+ transaction.commit();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+}
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/ConfigurableMultiTenantConnectionProvider.java b/hibernate5/src/main/java/com/baeldung/hibernate/ConfigurableMultiTenantConnectionProvider.java
new file mode 100644
index 0000000000..b9ed2bd139
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/ConfigurableMultiTenantConnectionProvider.java
@@ -0,0 +1,41 @@
+package com.baeldung.hibernate;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.hibernate.engine.jdbc.connections.spi.AbstractMultiTenantConnectionProvider;
+import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
+
+public class ConfigurableMultiTenantConnectionProvider extends AbstractMultiTenantConnectionProvider {
+
+ private final Map connectionProviderMap =
+ new HashMap<>();
+
+
+ public ConfigurableMultiTenantConnectionProvider(
+ Map connectionProviderMap) {
+ this.connectionProviderMap.putAll( connectionProviderMap );
+ }
+ @Override
+ protected ConnectionProvider getAnyConnectionProvider() {
+ System.out.println("Any");
+ return connectionProviderMap.values().iterator().next();
+ }
+
+ @Override
+ protected ConnectionProvider selectConnectionProvider(String tenantIdentifier) {
+ System.out.println("Specific");
+ return connectionProviderMap.get( tenantIdentifier );
+ }
+
+ @Override
+ public Connection getConnection(String tenantIdentifier) throws SQLException {
+ Connection connection = super.getConnection(tenantIdentifier);
+ // uncomment to see option 2 for SCHEMA strategy.
+ //connection.createStatement().execute("SET SCHEMA '" + tenantIdentifier + "'");
+ return connection;
+ }
+
+}
\ No newline at end of file
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/HibernateMultiTenantUtil.java b/hibernate5/src/main/java/com/baeldung/hibernate/HibernateMultiTenantUtil.java
new file mode 100644
index 0000000000..c3e7b621d0
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/HibernateMultiTenantUtil.java
@@ -0,0 +1,95 @@
+package com.baeldung.hibernate;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.hibernate.SessionFactory;
+import org.hibernate.boot.Metadata;
+import org.hibernate.boot.MetadataSources;
+import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
+import org.hibernate.cfg.AvailableSettings;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
+import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
+import org.hibernate.service.ServiceRegistry;
+
+import com.baeldung.hibernate.pojo.Supplier;
+
+public class HibernateMultiTenantUtil {
+ private static SessionFactory sessionFactory;
+ private static Map connectionProviderMap = new HashMap<>();
+ private static final String[] tenantDBNames = { "mydb1","mydb2"};
+
+ public static SessionFactory getSessionFactory() throws UnsupportedTenancyException {
+ if (sessionFactory == null) {
+ Configuration configuration = new Configuration().configure();
+ ServiceRegistry serviceRegistry = configureServiceRegistry(configuration);
+ sessionFactory = makeSessionFactory (serviceRegistry);
+// sessionFactory = configuration.buildSessionFactory(serviceRegistry);
+
+
+ }
+ return sessionFactory;
+ }
+
+ private static SessionFactory makeSessionFactory(ServiceRegistry serviceRegistry) {
+ MetadataSources metadataSources = new MetadataSources( serviceRegistry );
+ for(Class annotatedClasses : getAnnotatedClasses()) {
+ metadataSources.addAnnotatedClass( annotatedClasses );
+ }
+
+ Metadata metadata = metadataSources.buildMetadata();
+ return metadata.getSessionFactoryBuilder().build();
+
+ }
+
+ private static Class>[] getAnnotatedClasses() {
+ return new Class>[] {
+ Supplier.class
+ };
+ }
+
+ private static ServiceRegistry configureServiceRegistry(Configuration configuration) throws UnsupportedTenancyException {
+ Properties properties = configuration.getProperties();
+
+ connectionProviderMap = setUpConnectionProviders(properties, tenantDBNames);
+ properties.put(AvailableSettings.MULTI_TENANT_CONNECTION_PROVIDER, new ConfigurableMultiTenantConnectionProvider(connectionProviderMap));
+
+ return new StandardServiceRegistryBuilder().applySettings(properties).build();
+ }
+
+ private static Map setUpConnectionProviders(Properties properties, String[] tenantNames) throws UnsupportedTenancyException {
+ Map providerMap = new HashMap<>();
+ for (String tenant : tenantNames) {
+ DriverManagerConnectionProviderImpl connectionProvider = new DriverManagerConnectionProviderImpl();
+
+ String tenantStrategy = properties.getProperty("hibernate.multiTenancy");
+ System.out.println("Strategy:"+tenantStrategy);
+ properties.put(Environment.URL, tenantUrl(properties.getProperty(Environment.URL), tenant, tenantStrategy));
+ System.out.println("URL:"+properties.getProperty(Environment.URL));
+ connectionProvider.configure(properties);
+ System.out.println("Tenant:"+tenant);
+ providerMap.put(tenant, connectionProvider);
+
+ }
+ System.out.println("Added connections for:");
+ providerMap.keySet().stream().forEach(System.out::println);
+ return providerMap;
+ }
+
+ private static Object tenantUrl(String originalUrl, String tenant, String tenantStrategy) throws UnsupportedTenancyException {
+ if (tenantStrategy.toUpperCase().equals("DATABASE")) {
+ return originalUrl.replace(DEFAULT_DB_NAME, tenant);
+ } else if (tenantStrategy.toUpperCase().equals("SCHEMA")) {
+ return originalUrl + String.format(SCHEMA_TOKEN, tenant);
+ } else {
+ throw new UnsupportedTenancyException("Not yet supported");
+ }
+ }
+
+ public static final String SCHEMA_TOKEN = ";INIT=CREATE SCHEMA IF NOT EXISTS %1$s\\;SET SCHEMA %1$s";
+ public static final String DEFAULT_DB_NAME = "mydb1";
+
+}
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/HibernateUtil.java b/hibernate5/src/main/java/com/baeldung/hibernate/HibernateUtil.java
new file mode 100644
index 0000000000..c1f7301d46
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/HibernateUtil.java
@@ -0,0 +1,24 @@
+package com.baeldung.hibernate;
+
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.Configuration;
+
+public class HibernateUtil {
+
+ private static final SessionFactory sessionFactory;
+
+ static {
+ try {
+ Configuration configuration = new Configuration().configure();
+ sessionFactory = configuration.buildSessionFactory();
+
+ } catch (Throwable ex) {
+ System.err.println("Initial SessionFactory creation failed." + ex);
+ throw new ExceptionInInitializerError(ex);
+ }
+ }
+
+ public static SessionFactory getSessionFactory() {
+ return sessionFactory;
+ }
+}
\ No newline at end of file
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/UnsupportedTenancyException.java b/hibernate5/src/main/java/com/baeldung/hibernate/UnsupportedTenancyException.java
new file mode 100644
index 0000000000..99d9505ea3
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/UnsupportedTenancyException.java
@@ -0,0 +1,8 @@
+package com.baeldung.hibernate;
+
+public class UnsupportedTenancyException extends Exception {
+ public UnsupportedTenancyException (String message) {
+ super(message);
+ }
+
+}
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Supplier.java b/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Supplier.java
new file mode 100644
index 0000000000..d0187bba47
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Supplier.java
@@ -0,0 +1,67 @@
+package com.baeldung.hibernate.pojo;
+// Generated Feb 9, 2017 11:31:36 AM by Hibernate Tools 5.1.0.Final
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.junit.runners.Suite.SuiteClasses;
+
+
+/**
+ * Suppliers generated by hbm2java
+ */
+@Entity(name = "Supplier")
+@Table(name ="Supplier")
+public class Supplier implements java.io.Serializable {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Integer id;
+ private String name;
+ private String country;
+
+ public Supplier() {
+ }
+
+ public Supplier(String name, String country) {
+ this.name = name;
+ this.country = country;
+ }
+
+ public Integer getId() {
+ return this.id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getCountry() {
+ return this.country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuffer().append("[").append(id).append(",").append(name).append(",").append(country).append("]").toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return name.equals(((Supplier) obj).getName());
+ }
+}
diff --git a/hibernate5/src/main/resources/hibernate.cfg.xml b/hibernate5/src/main/resources/hibernate.cfg.xml
new file mode 100644
index 0000000000..26be05f931
--- /dev/null
+++ b/hibernate5/src/main/resources/hibernate.cfg.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ org.h2.Driver
+ jdbc:h2:mem:mydb1;DB_CLOSE_DELAY=-1
+ sa
+
+ org.hibernate.dialect.H2Dialect
+ DATABASE
+
+
diff --git a/hibernate5/src/test/java/com/baeldung/hibernate/MultiTenantHibernateIntegrationTest.java b/hibernate5/src/test/java/com/baeldung/hibernate/MultiTenantHibernateIntegrationTest.java
new file mode 100644
index 0000000000..8f2e88ac3d
--- /dev/null
+++ b/hibernate5/src/test/java/com/baeldung/hibernate/MultiTenantHibernateIntegrationTest.java
@@ -0,0 +1,66 @@
+package com.baeldung.hibernate;
+import com.baeldung.hibernate.pojo.Supplier;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotEquals;
+
+
+public class MultiTenantHibernateIntegrationTest {
+ @Test
+ public void givenDBMode_whenFetchingSuppliers_thenComparingFromDbs () {
+ SessionFactory sessionFactory;
+ try {
+ sessionFactory = HibernateMultiTenantUtil.getSessionFactory();
+
+ Session db1Session = sessionFactory
+ .withOptions().tenantIdentifier("mydb1").openSession();
+
+ initDb1(db1Session);
+
+ Transaction transaction = db1Session.getTransaction();
+ transaction.begin();
+ Supplier supplierFromDB1 = (Supplier)db1Session.createCriteria(Supplier.class).list().get(0);
+ transaction.commit();
+
+ Session db2Session = sessionFactory
+ .withOptions().tenantIdentifier("mydb2").openSession();
+
+ initDb2(db2Session);
+ db2Session.getTransaction().begin();
+ Supplier supplierFromDB2 = (Supplier) db2Session.createCriteria(Supplier.class).list().get(0);
+ db2Session.getTransaction().commit();
+
+ System.out.println(supplierFromDB1);
+ System.out.println(supplierFromDB2);
+
+ assertNotEquals(supplierFromDB1, supplierFromDB2);
+ } catch (UnsupportedTenancyException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+
+ private void initDb1(Session db1Session) {
+ System.out.println("Init DB1");
+ Transaction transaction = db1Session.getTransaction();
+ transaction.begin();
+ db1Session.createSQLQuery("DROP ALL OBJECTS").executeUpdate();
+ db1Session.createSQLQuery("create table Supplier (id integer generated by default as identity, country varchar(255), name varchar(255), primary key (id))").executeUpdate();
+ db1Session.createSQLQuery("insert into Supplier (id, country, name) values (null, 'John', 'USA')").executeUpdate();
+ transaction.commit();
+ }
+
+ private void initDb2(Session db2Session) {
+ System.out.println("Init DB2");
+ Transaction transaction = db2Session.getTransaction();
+ transaction.begin();
+ db2Session.createSQLQuery("DROP ALL OBJECTS").executeUpdate();
+ db2Session.createSQLQuery("create table Supplier (id integer generated by default as identity, country varchar(255), name varchar(255), primary key (id))").executeUpdate();
+ db2Session.createSQLQuery("insert into Supplier (id, country, name) values (null, 'Miller', 'UK')").executeUpdate();
+ transaction.commit();
+ }
+}
diff --git a/httpclient/pom.xml b/httpclient/pom.xml
index eec705b224..9d1c0dc7c1 100644
--- a/httpclient/pom.xml
+++ b/httpclient/pom.xml
@@ -7,6 +7,12 @@
httpclient
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
@@ -41,6 +47,12 @@
org.apache.httpcomponentsfluent-hc${httpclient.version}
+
+
+ commons-logging
+ commons-logging
+
+
@@ -59,6 +71,12 @@
org.apache.httpcomponentshttpasyncclient${httpasyncclient.version}
+
+
+ commons-logging
+ commons-logging
+
+
@@ -80,11 +98,6 @@
${org.slf4j.version}
-
- org.slf4j
- log4j-over-slf4j
- ${org.slf4j.version}
-
diff --git a/hystrix/pom.xml b/hystrix/pom.xml
index ba1a596631..5ccc66709f 100644
--- a/hystrix/pom.xml
+++ b/hystrix/pom.xml
@@ -56,6 +56,12 @@
com.netflix.hystrixhystrix-core${hystrix-core.version}
+
+
+ commons-logging
+ commons-logging
+
+ com.netflix.hystrix
diff --git a/image-processing/pom.xml b/image-processing/pom.xml
index 8766da571e..8abb7dc6b9 100644
--- a/image-processing/pom.xml
+++ b/image-processing/pom.xml
@@ -12,16 +12,34 @@
1.51h
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
net.imagejij${ij.version}
+
+
+ commons-logging
+ commons-logging
+
+ org.openimajcore-image${core-image.version}
+
+
+ commons-logging
+ commons-logging
+
+
diff --git a/immutables/pom.xml b/immutables/pom.xml
index 054763b3d4..6a3ee0335a 100644
--- a/immutables/pom.xml
+++ b/immutables/pom.xml
@@ -8,6 +8,12 @@
immutables1.0.0-SNAPSHOT
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
org.immutables
diff --git a/jackson/README.md b/jackson/README.md
index 5bc16e66b7..51919f6769 100644
--- a/jackson/README.md
+++ b/jackson/README.md
@@ -27,3 +27,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Guide to @JsonFormat in Jackson](http://www.baeldung.com/jackson-jsonformat)
- [A Guide to Optional with Jackson](http://www.baeldung.com/jackson-optional)
- [Map Serialization and Deserialization with Jackson](http://www.baeldung.com/jackson-map)
+- [Jackson Streaming API](http://www.baeldung.com/jackson-streaming-api)
diff --git a/jackson/pom.xml b/jackson/pom.xml
index 8e627c146b..77b3a00bee 100644
--- a/jackson/pom.xml
+++ b/jackson/pom.xml
@@ -7,6 +7,12 @@
jackson
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
@@ -154,11 +160,6 @@
${org.slf4j.version}
-
- org.slf4j
- log4j-over-slf4j
- ${org.slf4j.version}
-
diff --git a/jackson/src/main/java/com/baeldung/jackson/serialization/DistanceSerializer.java b/jackson/src/main/java/com/baeldung/jackson/serialization/DistanceSerializer.java
index ca013ff921..f5951dfd8e 100644
--- a/jackson/src/main/java/com/baeldung/jackson/serialization/DistanceSerializer.java
+++ b/jackson/src/main/java/com/baeldung/jackson/serialization/DistanceSerializer.java
@@ -23,7 +23,7 @@ public class DistanceSerializer extends StdSerializer {
public void serialize(Distance distance, JsonGenerator generator, SerializerProvider provider) throws IOException, JsonProcessingException {
generator.writeStartObject();
generator.writeFieldName("name");
- generator.writeNumber(distance.name());
+ generator.writeString(distance.name());
generator.writeFieldName("unit");
generator.writeString(distance.getUnit());
generator.writeFieldName("meters");
diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonDateTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonDateTest.java
index d8357f8500..b6472d889e 100644
--- a/jackson/src/test/java/com/baeldung/jackson/test/JacksonDateTest.java
+++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonDateTest.java
@@ -11,6 +11,7 @@ import java.time.LocalDateTime;
import java.util.Date;
import java.util.TimeZone;
+import com.fasterxml.jackson.databind.util.ISO8601DateFormat;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.junit.Test;
@@ -53,9 +54,10 @@ public class JacksonDateTest {
final ObjectMapper mapper = new ObjectMapper();
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+ mapper.setDateFormat(new ISO8601DateFormat());
final String result = mapper.writeValueAsString(event);
- assertThat(result, containsString("1970-01-01T02:30:00.000+0000"));
+ assertThat(result, containsString("1970-01-01T02:30:00Z"));
}
@Test
diff --git a/java-cassandra/pom.xml b/java-cassandra/pom.xml
index 5796043b95..4fbe5f1baf 100644
--- a/java-cassandra/pom.xml
+++ b/java-cassandra/pom.xml
@@ -7,6 +7,12 @@
cassandra-java-client
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
@@ -49,11 +55,6 @@
${org.slf4j.version}
-
- org.slf4j
- log4j-over-slf4j
- ${org.slf4j.version}
- junit
diff --git a/java-mongodb/pom.xml b/java-mongodb/pom.xml
index 4e5b847a01..3ec662996b 100644
--- a/java-mongodb/pom.xml
+++ b/java-mongodb/pom.xml
@@ -7,6 +7,12 @@
java-mongodb1.0-SNAPSHOT
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
diff --git a/java-websocket/pom.xml b/java-websocket/pom.xml
index e19706b4d9..a7510d8ae0 100644
--- a/java-websocket/pom.xml
+++ b/java-websocket/pom.xml
@@ -11,6 +11,12 @@
UTF-8
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
diff --git a/javaslang/README.md b/javaslang/README.md
index e451883516..fe413fc275 100644
--- a/javaslang/README.md
+++ b/javaslang/README.md
@@ -2,3 +2,4 @@
- [Introduction to Javaslang](http://www.baeldung.com/javaslang)
- [Guide to Try in Javaslang](http://www.baeldung.com/javaslang-try)
- [Guide to Pattern Matching in Javaslang](http://www.baeldung.com/javaslang-pattern-matching)
+- [Property Testing Example With Javaslang](http://www.baeldung.com/javaslang-property-testing)
diff --git a/javaslang/pom.xml b/javaslang/pom.xml
index 3770cce548..d32f1e8abf 100644
--- a/javaslang/pom.xml
+++ b/javaslang/pom.xml
@@ -5,6 +5,13 @@
javaslang1.0javaslang
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
junit
diff --git a/javax-servlets/pom.xml b/javax-servlets/pom.xml
index 68a1b9c441..71d64b2d43 100644
--- a/javax-servlets/pom.xml
+++ b/javax-servlets/pom.xml
@@ -7,6 +7,12 @@
com.baeldungjavax-servlets1.0-SNAPSHOT
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
@@ -49,6 +55,12 @@
httpclient${org.apache.httpcomponents.version}test
+
+
+ commons-logging
+ commons-logging
+
+
diff --git a/javaxval/pom.xml b/javaxval/pom.xml
index 1503ca49a6..f551fbb56d 100644
--- a/javaxval/pom.xml
+++ b/javaxval/pom.xml
@@ -12,6 +12,13 @@
2.2.6
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
diff --git a/jaxb/pom.xml b/jaxb/pom.xml
index b636a4dc82..f052b2f616 100644
--- a/jaxb/pom.xml
+++ b/jaxb/pom.xml
@@ -6,6 +6,13 @@
0.0.1-SNAPSHOTjaxb
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
org.glassfish.jaxb
@@ -135,6 +142,9 @@
${basedir}/src/main/javafalse
+ true
+ true
+ false
diff --git a/jaxb/src/main/java/com/baeldung/jaxb/gen/ObjectFactory.java b/jaxb/src/main/java/com/baeldung/jaxb/gen/ObjectFactory.java
new file mode 100644
index 0000000000..0a3da677ce
--- /dev/null
+++ b/jaxb/src/main/java/com/baeldung/jaxb/gen/ObjectFactory.java
@@ -0,0 +1,48 @@
+
+package com.baeldung.jaxb.gen;
+
+import javax.xml.bind.annotation.XmlRegistry;
+
+
+/**
+ * This object contains factory methods for each
+ * Java content interface and Java element interface
+ * generated in the com.baeldung.jaxb.gen package.
+ *
An ObjectFactory allows you to programatically
+ * construct new instances of the Java representation
+ * for XML content. The Java representation of XML
+ * content can consist of schema derived interfaces
+ * and classes representing the binding of schema
+ * type definitions, element declarations and model
+ * groups. Factory methods for each of these are
+ * provided in this class.
+ *
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+
+ /**
+ * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.baeldung.jaxb.gen
+ *
+ */
+ public ObjectFactory() {
+ }
+
+ /**
+ * Create an instance of {@link UserRequest }
+ *
+ */
+ public UserRequest createUserRequest() {
+ return new UserRequest();
+ }
+
+ /**
+ * Create an instance of {@link UserResponse }
+ *
+ */
+ public UserResponse createUserResponse() {
+ return new UserResponse();
+ }
+
+}
diff --git a/jaxb/src/main/java/com/baeldung/jaxb/gen/UserRequest.java b/jaxb/src/main/java/com/baeldung/jaxb/gen/UserRequest.java
new file mode 100644
index 0000000000..1c1abc61a6
--- /dev/null
+++ b/jaxb/src/main/java/com/baeldung/jaxb/gen/UserRequest.java
@@ -0,0 +1,87 @@
+
+package com.baeldung.jaxb.gen;
+
+import java.io.Serializable;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ *
Java class for UserRequest complex type.
+ *
+ *
The following schema fragment specifies the expected content contained within this class.
+ *
+ *
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "getAllEmployeesResponse", propOrder = {
+ "_return"
+})
+public class GetAllEmployeesResponse {
+
+ @XmlElement(name = "return")
+ protected List _return;
+
+ /**
+ * Gets the value of the return property.
+ *
+ *
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a set method for the return property.
+ *
+ *
+ * For example, to add a new item, do as follows:
+ *
+ * getReturn().add(newItem);
+ *
+ *
+ *
+ *
+ * Objects of the following type(s) are allowed in the list
+ * {@link Employee }
+ *
+ *
+ */
+ public List getReturn() {
+ if (_return == null) {
+ _return = new ArrayList();
+ }
+ return this._return;
+ }
+
+}
diff --git a/jee7/src/main/java/com/baeldung/jaxws/client/GetEmployee.java b/jee7/src/main/java/com/baeldung/jaxws/client/GetEmployee.java
new file mode 100644
index 0000000000..333073be69
--- /dev/null
+++ b/jee7/src/main/java/com/baeldung/jaxws/client/GetEmployee.java
@@ -0,0 +1,52 @@
+
+package com.baeldung.jaxws.client;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ *
Java class for getEmployee complex type.
+ *
+ *
The following schema fragment specifies the expected content contained within this class.
+ *
+ *
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "updateEmployeeResponse", propOrder = {
+ "_return"
+})
+public class UpdateEmployeeResponse {
+
+ @XmlElement(name = "return")
+ protected Employee _return;
+
+ /**
+ * Gets the value of the return property.
+ *
+ * @return
+ * possible object is
+ * {@link Employee }
+ *
+ */
+ public Employee getReturn() {
+ return _return;
+ }
+
+ /**
+ * Sets the value of the return property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Employee }
+ *
+ */
+ public void setReturn(Employee value) {
+ this._return = value;
+ }
+
+}
diff --git a/jee7/src/main/java/com/baeldung/jaxws/client/package-info.java b/jee7/src/main/java/com/baeldung/jaxws/client/package-info.java
new file mode 100644
index 0000000000..c264b876f9
--- /dev/null
+++ b/jee7/src/main/java/com/baeldung/jaxws/client/package-info.java
@@ -0,0 +1,2 @@
+@javax.xml.bind.annotation.XmlSchema(namespace = "http://bottomup.server.jaxws.baeldung.com/")
+package com.baeldung.jaxws.client;
diff --git a/jee7/src/main/java/com/baeldung/jaxws/config/EmployeeServicePublisher.java b/jee7/src/main/java/com/baeldung/jaxws/config/EmployeeServicePublisher.java
deleted file mode 100644
index ac3b049320..0000000000
--- a/jee7/src/main/java/com/baeldung/jaxws/config/EmployeeServicePublisher.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.baeldung.jaxws.config;
-
-import javax.xml.ws.Endpoint;
-
-import com.baeldung.jaxws.EmployeeServiceImpl;
-
-public class EmployeeServicePublisher {
-
- public static void main(String[] args) {
- Endpoint.publish("http://localhost:8080/employeeservice", new EmployeeServiceImpl());
- }
-}
diff --git a/jee7/src/main/java/com/baeldung/jaxws/EmployeeService.java b/jee7/src/main/java/com/baeldung/jaxws/server/bottomup/EmployeeService.java
similarity index 69%
rename from jee7/src/main/java/com/baeldung/jaxws/EmployeeService.java
rename to jee7/src/main/java/com/baeldung/jaxws/server/bottomup/EmployeeService.java
index 9735607da6..7381e58dad 100644
--- a/jee7/src/main/java/com/baeldung/jaxws/EmployeeService.java
+++ b/jee7/src/main/java/com/baeldung/jaxws/server/bottomup/EmployeeService.java
@@ -1,13 +1,13 @@
-package com.baeldung.jaxws;
+package com.baeldung.jaxws.server.bottomup;
import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebService;
-import com.baeldung.jaxws.exception.EmployeeAlreadyExists;
-import com.baeldung.jaxws.exception.EmployeeNotFound;
-import com.baeldung.jaxws.model.Employee;
+import com.baeldung.jaxws.server.bottomup.exception.EmployeeAlreadyExists;
+import com.baeldung.jaxws.server.bottomup.exception.EmployeeNotFound;
+import com.baeldung.jaxws.server.bottomup.model.Employee;
@WebService
public interface EmployeeService {
diff --git a/jee7/src/main/java/com/baeldung/jaxws/EmployeeServiceImpl.java b/jee7/src/main/java/com/baeldung/jaxws/server/bottomup/EmployeeServiceImpl.java
similarity index 76%
rename from jee7/src/main/java/com/baeldung/jaxws/EmployeeServiceImpl.java
rename to jee7/src/main/java/com/baeldung/jaxws/server/bottomup/EmployeeServiceImpl.java
index c1c9cd4385..602a2f7336 100644
--- a/jee7/src/main/java/com/baeldung/jaxws/EmployeeServiceImpl.java
+++ b/jee7/src/main/java/com/baeldung/jaxws/server/bottomup/EmployeeServiceImpl.java
@@ -1,4 +1,4 @@
-package com.baeldung.jaxws;
+package com.baeldung.jaxws.server.bottomup;
import java.util.List;
@@ -6,12 +6,12 @@ import javax.inject.Inject;
import javax.jws.WebMethod;
import javax.jws.WebService;
-import com.baeldung.jaxws.exception.EmployeeAlreadyExists;
-import com.baeldung.jaxws.exception.EmployeeNotFound;
-import com.baeldung.jaxws.model.Employee;
-import com.baeldung.jaxws.repository.EmployeeRepository;
+import com.baeldung.jaxws.server.bottomup.exception.EmployeeAlreadyExists;
+import com.baeldung.jaxws.server.bottomup.exception.EmployeeNotFound;
+import com.baeldung.jaxws.server.bottomup.model.Employee;
+import com.baeldung.jaxws.server.repository.EmployeeRepository;
-@WebService(serviceName = "EmployeeService", endpointInterface = "com.baeldung.jaxws.EmployeeService")
+@WebService(serviceName = "EmployeeService", endpointInterface = "com.baeldung.jaxws.server.bottomup.EmployeeService")
public class EmployeeServiceImpl implements EmployeeService {
@Inject
diff --git a/jee7/src/main/java/com/baeldung/jaxws/exception/EmployeeAlreadyExists.java b/jee7/src/main/java/com/baeldung/jaxws/server/bottomup/exception/EmployeeAlreadyExists.java
similarity index 83%
rename from jee7/src/main/java/com/baeldung/jaxws/exception/EmployeeAlreadyExists.java
rename to jee7/src/main/java/com/baeldung/jaxws/server/bottomup/exception/EmployeeAlreadyExists.java
index 8a96f8aec0..26fd80f1e5 100644
--- a/jee7/src/main/java/com/baeldung/jaxws/exception/EmployeeAlreadyExists.java
+++ b/jee7/src/main/java/com/baeldung/jaxws/server/bottomup/exception/EmployeeAlreadyExists.java
@@ -1,4 +1,4 @@
-package com.baeldung.jaxws.exception;
+package com.baeldung.jaxws.server.bottomup.exception;
import javax.xml.ws.WebFault;
diff --git a/jee7/src/main/java/com/baeldung/jaxws/exception/EmployeeNotFound.java b/jee7/src/main/java/com/baeldung/jaxws/server/bottomup/exception/EmployeeNotFound.java
similarity index 82%
rename from jee7/src/main/java/com/baeldung/jaxws/exception/EmployeeNotFound.java
rename to jee7/src/main/java/com/baeldung/jaxws/server/bottomup/exception/EmployeeNotFound.java
index 3de2ca8db6..52397d55a3 100644
--- a/jee7/src/main/java/com/baeldung/jaxws/exception/EmployeeNotFound.java
+++ b/jee7/src/main/java/com/baeldung/jaxws/server/bottomup/exception/EmployeeNotFound.java
@@ -1,4 +1,4 @@
-package com.baeldung.jaxws.exception;
+package com.baeldung.jaxws.server.bottomup.exception;
import javax.xml.ws.WebFault;
diff --git a/jee7/src/main/java/com/baeldung/jaxws/model/Employee.java b/jee7/src/main/java/com/baeldung/jaxws/server/bottomup/model/Employee.java
similarity index 90%
rename from jee7/src/main/java/com/baeldung/jaxws/model/Employee.java
rename to jee7/src/main/java/com/baeldung/jaxws/server/bottomup/model/Employee.java
index dbbdc234cf..089ff88aa2 100644
--- a/jee7/src/main/java/com/baeldung/jaxws/model/Employee.java
+++ b/jee7/src/main/java/com/baeldung/jaxws/server/bottomup/model/Employee.java
@@ -1,4 +1,4 @@
-package com.baeldung.jaxws.model;
+package com.baeldung.jaxws.server.bottomup.model;
public class Employee {
private int id;
diff --git a/jee7/src/main/java/com/baeldung/jaxws/server/config/EmployeeServicePublisher.java b/jee7/src/main/java/com/baeldung/jaxws/server/config/EmployeeServicePublisher.java
new file mode 100644
index 0000000000..8659833f99
--- /dev/null
+++ b/jee7/src/main/java/com/baeldung/jaxws/server/config/EmployeeServicePublisher.java
@@ -0,0 +1,14 @@
+package com.baeldung.jaxws.server.config;
+
+import javax.xml.ws.Endpoint;
+
+import com.baeldung.jaxws.server.bottomup.EmployeeServiceImpl;
+import com.baeldung.jaxws.server.topdown.EmployeeServiceTopDownImpl;
+
+public class EmployeeServicePublisher {
+
+ public static void main(String[] args) {
+ Endpoint.publish("http://localhost:8080/employeeservicetopdown", new EmployeeServiceTopDownImpl());
+ Endpoint.publish("http://localhost:8080/employeeservice", new EmployeeServiceImpl());
+ }
+}
diff --git a/jee7/src/main/java/com/baeldung/jaxws/repository/EmployeeRepository.java b/jee7/src/main/java/com/baeldung/jaxws/server/repository/EmployeeRepository.java
similarity index 61%
rename from jee7/src/main/java/com/baeldung/jaxws/repository/EmployeeRepository.java
rename to jee7/src/main/java/com/baeldung/jaxws/server/repository/EmployeeRepository.java
index 0d5dec0462..c9d8b4d33c 100644
--- a/jee7/src/main/java/com/baeldung/jaxws/repository/EmployeeRepository.java
+++ b/jee7/src/main/java/com/baeldung/jaxws/server/repository/EmployeeRepository.java
@@ -1,10 +1,10 @@
-package com.baeldung.jaxws.repository;
+package com.baeldung.jaxws.server.repository;
import java.util.List;
-import com.baeldung.jaxws.exception.EmployeeAlreadyExists;
-import com.baeldung.jaxws.exception.EmployeeNotFound;
-import com.baeldung.jaxws.model.Employee;
+import com.baeldung.jaxws.server.bottomup.exception.EmployeeAlreadyExists;
+import com.baeldung.jaxws.server.bottomup.exception.EmployeeNotFound;
+import com.baeldung.jaxws.server.bottomup.model.Employee;
public interface EmployeeRepository {
diff --git a/jee7/src/main/java/com/baeldung/jaxws/repository/EmployeeRepositoryImpl.java b/jee7/src/main/java/com/baeldung/jaxws/server/repository/EmployeeRepositoryImpl.java
similarity index 87%
rename from jee7/src/main/java/com/baeldung/jaxws/repository/EmployeeRepositoryImpl.java
rename to jee7/src/main/java/com/baeldung/jaxws/server/repository/EmployeeRepositoryImpl.java
index f67509fff5..f211c4f25b 100644
--- a/jee7/src/main/java/com/baeldung/jaxws/repository/EmployeeRepositoryImpl.java
+++ b/jee7/src/main/java/com/baeldung/jaxws/server/repository/EmployeeRepositoryImpl.java
@@ -1,11 +1,11 @@
-package com.baeldung.jaxws.repository;
+package com.baeldung.jaxws.server.repository;
import java.util.ArrayList;
import java.util.List;
-import com.baeldung.jaxws.exception.EmployeeAlreadyExists;
-import com.baeldung.jaxws.exception.EmployeeNotFound;
-import com.baeldung.jaxws.model.Employee;
+import com.baeldung.jaxws.server.bottomup.exception.EmployeeAlreadyExists;
+import com.baeldung.jaxws.server.bottomup.exception.EmployeeNotFound;
+import com.baeldung.jaxws.server.bottomup.model.Employee;
public class EmployeeRepositoryImpl implements EmployeeRepository {
private List employeeList;
diff --git a/jee7/src/main/java/com/baeldung/jaxws/server/topdown/EmployeeServiceTopDown.java b/jee7/src/main/java/com/baeldung/jaxws/server/topdown/EmployeeServiceTopDown.java
new file mode 100644
index 0000000000..ec4103438b
--- /dev/null
+++ b/jee7/src/main/java/com/baeldung/jaxws/server/topdown/EmployeeServiceTopDown.java
@@ -0,0 +1,34 @@
+
+package com.baeldung.jaxws.server.topdown;
+
+import javax.jws.WebMethod;
+import javax.jws.WebResult;
+import javax.jws.WebService;
+import javax.jws.soap.SOAPBinding;
+import javax.xml.bind.annotation.XmlSeeAlso;
+
+
+/**
+ * This class was generated by the JAX-WS RI.
+ * JAX-WS RI 2.2.4-b01
+ * Generated source version: 2.2
+ *
+ */
+@WebService(name = "EmployeeServiceTopDown", targetNamespace = "http://topdown.server.jaxws.baeldung.com/")
+@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
+@XmlSeeAlso({
+ ObjectFactory.class
+})
+public interface EmployeeServiceTopDown {
+
+
+ /**
+ *
+ * @return
+ * returns int
+ */
+ @WebMethod(action = "http://topdown.server.jaxws.baeldung.com/EmployeeServiceTopDown/countEmployees")
+ @WebResult(name = "countEmployeesResponse", targetNamespace = "http://topdown.server.jaxws.baeldung.com/", partName = "parameters")
+ public int countEmployees();
+
+}
diff --git a/jee7/src/main/java/com/baeldung/jaxws/server/topdown/EmployeeServiceTopDownImpl.java b/jee7/src/main/java/com/baeldung/jaxws/server/topdown/EmployeeServiceTopDownImpl.java
new file mode 100644
index 0000000000..bd46c025b7
--- /dev/null
+++ b/jee7/src/main/java/com/baeldung/jaxws/server/topdown/EmployeeServiceTopDownImpl.java
@@ -0,0 +1,19 @@
+package com.baeldung.jaxws.server.topdown;
+
+import com.baeldung.jaxws.server.repository.EmployeeRepository;
+
+import javax.inject.Inject;
+import javax.jws.WebMethod;
+import javax.jws.WebService;
+
+
+@WebService(name = "EmployeeServiceTopDown", targetNamespace = "http://topdown.server.jaxws.baeldung.com/", endpointInterface = "com.baeldung.jaxws.server.topdown.EmployeeServiceTopDown")
+public class EmployeeServiceTopDownImpl implements EmployeeServiceTopDown {
+
+ @Inject private EmployeeRepository employeeRepositoryImpl;
+
+ @WebMethod
+ public int countEmployees() {
+ return employeeRepositoryImpl.count();
+ }
+}
diff --git a/jee7/src/main/java/com/baeldung/jaxws/server/topdown/EmployeeServiceTopDown_Service.java b/jee7/src/main/java/com/baeldung/jaxws/server/topdown/EmployeeServiceTopDown_Service.java
new file mode 100644
index 0000000000..ee3382adb6
--- /dev/null
+++ b/jee7/src/main/java/com/baeldung/jaxws/server/topdown/EmployeeServiceTopDown_Service.java
@@ -0,0 +1,94 @@
+
+package com.baeldung.jaxws.server.topdown;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import javax.xml.namespace.QName;
+import javax.xml.ws.Service;
+import javax.xml.ws.WebEndpoint;
+import javax.xml.ws.WebServiceClient;
+import javax.xml.ws.WebServiceException;
+import javax.xml.ws.WebServiceFeature;
+
+
+/**
+ * This class was generated by the JAX-WS RI.
+ * JAX-WS RI 2.2.4-b01
+ * Generated source version: 2.2
+ *
+ */
+@WebServiceClient(name = "EmployeeServiceTopDown", targetNamespace = "http://topdown.server.jaxws.baeldung.com/", wsdlLocation = "file:/Users/do-enr-lap-4/Developer/baeldung/source/tutorials/jee7/src/main/java/com/baeldung/jaxws/server/topdown/wsdl/employeeservicetopdown.wsdl")
+public class EmployeeServiceTopDown_Service
+ extends Service
+{
+
+ private final static URL EMPLOYEESERVICETOPDOWN_WSDL_LOCATION;
+ private final static WebServiceException EMPLOYEESERVICETOPDOWN_EXCEPTION;
+ private final static QName EMPLOYEESERVICETOPDOWN_QNAME = new QName("http://topdown.server.jaxws.baeldung.com/", "EmployeeServiceTopDown");
+
+ static {
+ URL url = null;
+ WebServiceException e = null;
+ try {
+ url = new URL("file:/Users/do-enr-lap-4/Developer/baeldung/source/tutorials/jee7/src/main/java/com/baeldung/jaxws/server/topdown/wsdl/employeeservicetopdown.wsdl");
+ } catch (MalformedURLException ex) {
+ e = new WebServiceException(ex);
+ }
+ EMPLOYEESERVICETOPDOWN_WSDL_LOCATION = url;
+ EMPLOYEESERVICETOPDOWN_EXCEPTION = e;
+ }
+
+ public EmployeeServiceTopDown_Service() {
+ super(__getWsdlLocation(), EMPLOYEESERVICETOPDOWN_QNAME);
+ }
+
+ public EmployeeServiceTopDown_Service(WebServiceFeature... features) {
+ super(__getWsdlLocation(), EMPLOYEESERVICETOPDOWN_QNAME, features);
+ }
+
+ public EmployeeServiceTopDown_Service(URL wsdlLocation) {
+ super(wsdlLocation, EMPLOYEESERVICETOPDOWN_QNAME);
+ }
+
+ public EmployeeServiceTopDown_Service(URL wsdlLocation, WebServiceFeature... features) {
+ super(wsdlLocation, EMPLOYEESERVICETOPDOWN_QNAME, features);
+ }
+
+ public EmployeeServiceTopDown_Service(URL wsdlLocation, QName serviceName) {
+ super(wsdlLocation, serviceName);
+ }
+
+ public EmployeeServiceTopDown_Service(URL wsdlLocation, QName serviceName, WebServiceFeature... features) {
+ super(wsdlLocation, serviceName, features);
+ }
+
+ /**
+ *
+ * @return
+ * returns EmployeeServiceTopDown
+ */
+ @WebEndpoint(name = "EmployeeServiceTopDownSOAP")
+ public EmployeeServiceTopDown getEmployeeServiceTopDownSOAP() {
+ return super.getPort(new QName("http://topdown.server.jaxws.baeldung.com/", "EmployeeServiceTopDownSOAP"), EmployeeServiceTopDown.class);
+ }
+
+ /**
+ *
+ * @param features
+ * A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the features parameter will have their default values.
+ * @return
+ * returns EmployeeServiceTopDown
+ */
+ @WebEndpoint(name = "EmployeeServiceTopDownSOAP")
+ public EmployeeServiceTopDown getEmployeeServiceTopDownSOAP(WebServiceFeature... features) {
+ return super.getPort(new QName("http://topdown.server.jaxws.baeldung.com/", "EmployeeServiceTopDownSOAP"), EmployeeServiceTopDown.class, features);
+ }
+
+ private static URL __getWsdlLocation() {
+ if (EMPLOYEESERVICETOPDOWN_EXCEPTION!= null) {
+ throw EMPLOYEESERVICETOPDOWN_EXCEPTION;
+ }
+ return EMPLOYEESERVICETOPDOWN_WSDL_LOCATION;
+ }
+
+}
diff --git a/jee7/src/main/java/com/baeldung/jaxws/server/topdown/ObjectFactory.java b/jee7/src/main/java/com/baeldung/jaxws/server/topdown/ObjectFactory.java
new file mode 100644
index 0000000000..53e23eee5d
--- /dev/null
+++ b/jee7/src/main/java/com/baeldung/jaxws/server/topdown/ObjectFactory.java
@@ -0,0 +1,45 @@
+
+package com.baeldung.jaxws.server.topdown;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlElementDecl;
+import javax.xml.bind.annotation.XmlRegistry;
+import javax.xml.namespace.QName;
+
+
+/**
+ * This object contains factory methods for each
+ * Java content interface and Java element interface
+ * generated in the com.baeldung.jaxws.server.topdown package.
+ *
An ObjectFactory allows you to programatically
+ * construct new instances of the Java representation
+ * for XML content. The Java representation of XML
+ * content can consist of schema derived interfaces
+ * and classes representing the binding of schema
+ * type definitions, element declarations and model
+ * groups. Factory methods for each of these are
+ * provided in this class.
+ *
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+ private final static QName _CountEmployeesResponse_QNAME = new QName("http://topdown.server.jaxws.baeldung.com/", "countEmployeesResponse");
+
+ /**
+ * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.baeldung.jaxws.server.topdown
+ *
+ */
+ public ObjectFactory() {
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Integer }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://topdown.server.jaxws.baeldung.com/", name = "countEmployeesResponse")
+ public JAXBElement createCountEmployeesResponse(Integer value) {
+ return new JAXBElement(_CountEmployeesResponse_QNAME, Integer.class, null, value);
+ }
+
+}
diff --git a/jee7/src/main/java/com/baeldung/jaxws/wsdl/employeeservicetopdown.wsdl b/jee7/src/main/java/com/baeldung/jaxws/wsdl/employeeservicetopdown.wsdl
new file mode 100644
index 0000000000..426717f90e
--- /dev/null
+++ b/jee7/src/main/java/com/baeldung/jaxws/wsdl/employeeservicetopdown.wsdl
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jee7/src/test/java/com/baeldung/jaxws/EmployeeServiceLiveTest.java b/jee7/src/test/java/com/baeldung/jaxws/EmployeeServiceLiveTest.java
index 4429703468..5663db712e 100644
--- a/jee7/src/test/java/com/baeldung/jaxws/EmployeeServiceLiveTest.java
+++ b/jee7/src/test/java/com/baeldung/jaxws/EmployeeServiceLiveTest.java
@@ -1,4 +1,4 @@
-/*package com.baeldung.jaxws;
+package com.baeldung.jaxws;
import static org.junit.Assert.assertEquals;
@@ -7,7 +7,6 @@ import java.net.URL;
import java.util.List;
import javax.xml.namespace.QName;
-import javax.xml.ws.Service;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
@@ -19,17 +18,18 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.baeldung.jaxws.exception.EmployeeAlreadyExists;
-import com.baeldung.jaxws.exception.EmployeeNotFound;
-import com.baeldung.jaxws.model.Employee;
-import com.baeldung.jaxws.repository.EmployeeRepository;
+import com.baeldung.jaxws.client.Employee;
+import com.baeldung.jaxws.client.EmployeeAlreadyExists_Exception;
+import com.baeldung.jaxws.client.EmployeeNotFound_Exception;
+import com.baeldung.jaxws.client.EmployeeService;
+import com.baeldung.jaxws.client.EmployeeService_Service;
@RunWith(Arquillian.class)
public class EmployeeServiceLiveTest {
private static final String APP_NAME = "jee7";
private static final String WSDL_PATH = "EmployeeService?wsdl";
- private static QName SERVICE_NAME = new QName("http://jaxws.baeldung.com/", "EmployeeService");
+ private static QName SERVICE_NAME = new QName("http://bottomup.server.jaxws.baeldung.com/", "EmployeeService");
private static URL wsdlUrl;
@ArquillianResource
@@ -39,8 +39,12 @@ public class EmployeeServiceLiveTest {
@Deployment(testable = false)
public static WebArchive createDeployment() {
- return ShrinkWrap.create(WebArchive.class, APP_NAME + ".war").addPackage(EmployeeService.class.getPackage()).addPackage(Employee.class.getPackage()).addPackage(EmployeeNotFound.class.getPackage()).addPackage(EmployeeRepository.class.getPackage())
- .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
+ return ShrinkWrap.create(WebArchive.class, APP_NAME + ".war")
+ .addPackage(com.baeldung.jaxws.server.bottomup.EmployeeService.class.getPackage())
+ .addPackage(com.baeldung.jaxws.server.bottomup.model.Employee.class.getPackage())
+ .addPackage(com.baeldung.jaxws.server.bottomup.exception.EmployeeNotFound.class.getPackage())
+ .addPackage(com.baeldung.jaxws.server.repository.EmployeeRepository.class.getPackage())
+ .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
}
@Before
@@ -51,8 +55,8 @@ public class EmployeeServiceLiveTest {
e.printStackTrace();
}
- Service service = Service.create(wsdlUrl, SERVICE_NAME);
- employeeServiceProxy = service.getPort(EmployeeService.class);
+ EmployeeService_Service employeeService_Service = new EmployeeService_Service(wsdlUrl);
+ employeeServiceProxy = employeeService_Service.getEmployeeServiceImplPort();
}
@Test
@@ -63,49 +67,48 @@ public class EmployeeServiceLiveTest {
}
@Test
- public void givenEmployees_whenGetAvailableEmployee_thenCorrectEmployeeReturned() throws EmployeeNotFound {
+ public void givenEmployees_whenGetAvailableEmployee_thenCorrectEmployeeReturned() throws EmployeeNotFound_Exception {
Employee employee = employeeServiceProxy.getEmployee(2);
assertEquals(employee.getFirstName(), "Jack");
}
- @Test(expected = EmployeeNotFound.class)
- public void givenEmployees_whenGetNonAvailableEmployee_thenEmployeeNotFoundException() throws EmployeeNotFound {
+ @Test(expected = EmployeeNotFound_Exception.class)
+ public void givenEmployees_whenGetNonAvailableEmployee_thenEmployeeNotFoundException() throws EmployeeNotFound_Exception {
employeeServiceProxy.getEmployee(20);
}
@Test
- public void givenEmployees_whenAddNewEmployee_thenEmployeeCountIncreased() throws EmployeeAlreadyExists {
+ public void givenEmployees_whenAddNewEmployee_thenEmployeeCountIncreased() throws EmployeeAlreadyExists_Exception {
int employeeCount = employeeServiceProxy.countEmployees();
employeeServiceProxy.addEmployee(4, "Anna");
assertEquals(employeeServiceProxy.countEmployees(), employeeCount + 1);
}
- @Test(expected = EmployeeAlreadyExists.class)
- public void givenEmployees_whenAddAlreadyExistingEmployee_thenEmployeeAlreadyExistsException() throws EmployeeAlreadyExists {
+ @Test(expected = EmployeeAlreadyExists_Exception.class)
+ public void givenEmployees_whenAddAlreadyExistingEmployee_thenEmployeeAlreadyExistsException() throws EmployeeAlreadyExists_Exception {
employeeServiceProxy.addEmployee(1, "Anna");
}
@Test
- public void givenEmployees_whenUpdateExistingEmployee_thenUpdatedEmployeeReturned() throws EmployeeNotFound {
+ public void givenEmployees_whenUpdateExistingEmployee_thenUpdatedEmployeeReturned() throws EmployeeNotFound_Exception {
Employee updated = employeeServiceProxy.updateEmployee(1, "Joan");
assertEquals(updated.getFirstName(), "Joan");
}
- @Test(expected = EmployeeNotFound.class)
- public void givenEmployees_whenUpdateNonExistingEmployee_thenEmployeeNotFoundException() throws EmployeeNotFound {
+ @Test(expected = EmployeeNotFound_Exception.class)
+ public void givenEmployees_whenUpdateNonExistingEmployee_thenEmployeeNotFoundException() throws EmployeeNotFound_Exception {
employeeServiceProxy.updateEmployee(20, "Joan");
}
@Test
- public void givenEmployees_whenDeleteExistingEmployee_thenSuccessReturned() throws EmployeeNotFound {
+ public void givenEmployees_whenDeleteExistingEmployee_thenSuccessReturned() throws EmployeeNotFound_Exception {
boolean deleteEmployee = employeeServiceProxy.deleteEmployee(3);
assertEquals(deleteEmployee, true);
}
- @Test(expected = EmployeeNotFound.class)
- public void givenEmployee_whenDeleteNonExistingEmployee_thenEmployeeNotFoundException() throws EmployeeNotFound {
+ @Test(expected = EmployeeNotFound_Exception.class)
+ public void givenEmployee_whenDeleteNonExistingEmployee_thenEmployeeNotFoundException() throws EmployeeNotFound_Exception {
employeeServiceProxy.deleteEmployee(20);
}
}
-*/
\ No newline at end of file
diff --git a/jhipster/.editorconfig b/jhipster/jhipster-microservice/car-app/.editorconfig
similarity index 100%
rename from jhipster/.editorconfig
rename to jhipster/jhipster-microservice/car-app/.editorconfig
diff --git a/jhipster/.gitattributes b/jhipster/jhipster-microservice/car-app/.gitattributes
similarity index 100%
rename from jhipster/.gitattributes
rename to jhipster/jhipster-microservice/car-app/.gitattributes
diff --git a/jhipster/jhipster-microservice/car-app/.gitignore b/jhipster/jhipster-microservice/car-app/.gitignore
new file mode 100644
index 0000000000..74b29e2042
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/.gitignore
@@ -0,0 +1,141 @@
+######################
+# Project Specific
+######################
+/target/www/**
+/src/test/javascript/coverage/
+/src/test/javascript/PhantomJS*/
+
+######################
+# Node
+######################
+/node/
+node_tmp/
+node_modules/
+npm-debug.log.*
+
+######################
+# SASS
+######################
+.sass-cache/
+
+######################
+# Eclipse
+######################
+*.pydevproject
+.project
+.metadata
+tmp/
+tmp/**/*
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.classpath
+.settings/
+.loadpath
+.factorypath
+/src/main/resources/rebel.xml
+
+# External tool builders
+.externalToolBuilders/**
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# CDT-specific
+.cproject
+
+# PDT-specific
+.buildpath
+
+######################
+# Intellij
+######################
+.idea/
+*.iml
+*.iws
+*.ipr
+*.ids
+*.orig
+
+######################
+# Visual Studio Code
+######################
+.vscode/
+
+######################
+# Maven
+######################
+/log/
+/target/
+
+######################
+# Gradle
+######################
+.gradle/
+/build/
+
+######################
+# Package Files
+######################
+*.jar
+*.war
+*.ear
+*.db
+
+######################
+# Windows
+######################
+# Windows image file caches
+Thumbs.db
+
+# Folder config file
+Desktop.ini
+
+######################
+# Mac OSX
+######################
+.DS_Store
+.svn
+
+# Thumbnails
+._*
+
+# Files that might appear on external disk
+.Spotlight-V100
+.Trashes
+
+######################
+# Directories
+######################
+/bin/
+/deploy/
+
+######################
+# Logs
+######################
+*.log
+
+######################
+# Others
+######################
+*.class
+*.*~
+*~
+.merge_file*
+
+######################
+# Gradle Wrapper
+######################
+!gradle/wrapper/gradle-wrapper.jar
+
+######################
+# Maven Wrapper
+######################
+!.mvn/wrapper/maven-wrapper.jar
+
+######################
+# ESLint
+######################
+.eslintcache
diff --git a/jhipster/jhipster-microservice/car-app/.jhipster/Car.json b/jhipster/jhipster-microservice/car-app/.jhipster/Car.json
new file mode 100644
index 0000000000..ceaef3cd63
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/.jhipster/Car.json
@@ -0,0 +1,25 @@
+{
+ "fluentMethods": true,
+ "relationships": [],
+ "fields": [
+ {
+ "fieldName": "make",
+ "fieldType": "String"
+ },
+ {
+ "fieldName": "brand",
+ "fieldType": "String"
+ },
+ {
+ "fieldName": "price",
+ "fieldType": "Double"
+ }
+ ],
+ "changelogDate": "20170503041524",
+ "dto": "no",
+ "service": "no",
+ "entityTableName": "car",
+ "pagination": "infinite-scroll",
+ "microserviceName": "carapp",
+ "searchEngine": false
+}
diff --git a/jhipster/.mvn/wrapper/maven-wrapper.jar b/jhipster/jhipster-microservice/car-app/.mvn/wrapper/maven-wrapper.jar
similarity index 100%
rename from jhipster/.mvn/wrapper/maven-wrapper.jar
rename to jhipster/jhipster-microservice/car-app/.mvn/wrapper/maven-wrapper.jar
diff --git a/jhipster/.mvn/wrapper/maven-wrapper.properties b/jhipster/jhipster-microservice/car-app/.mvn/wrapper/maven-wrapper.properties
similarity index 100%
rename from jhipster/.mvn/wrapper/maven-wrapper.properties
rename to jhipster/jhipster-microservice/car-app/.mvn/wrapper/maven-wrapper.properties
diff --git a/jhipster/jhipster-microservice/car-app/.yo-rc.json b/jhipster/jhipster-microservice/car-app/.yo-rc.json
new file mode 100644
index 0000000000..896ab47839
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/.yo-rc.json
@@ -0,0 +1,29 @@
+{
+ "generator-jhipster": {
+ "jhipsterVersion": "4.0.8",
+ "baseName": "carapp",
+ "packageName": "com.car.app",
+ "packageFolder": "com/car/app",
+ "serverPort": "8081",
+ "authenticationType": "jwt",
+ "hibernateCache": "hazelcast",
+ "clusteredHttpSession": false,
+ "websocket": false,
+ "databaseType": "sql",
+ "devDatabaseType": "h2Disk",
+ "prodDatabaseType": "mysql",
+ "searchEngine": false,
+ "messageBroker": false,
+ "serviceDiscoveryType": "eureka",
+ "buildTool": "maven",
+ "enableSocialSignIn": false,
+ "jwtSecretKey": "0ebd193e0552c4ac548217d353abbde0761a1997",
+ "enableTranslation": false,
+ "applicationType": "microservice",
+ "testFrameworks": [],
+ "jhiPrefix": "jhi",
+ "skipClient": true,
+ "skipUserManagement": true,
+ "clientPackageManager": "yarn"
+ }
+}
\ No newline at end of file
diff --git a/jhipster/jhipster-microservice/car-app/README.md b/jhipster/jhipster-microservice/car-app/README.md
new file mode 100644
index 0000000000..7dcbb23bb1
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/README.md
@@ -0,0 +1,75 @@
+# carapp
+This application was generated using JHipster 4.0.8, you can find documentation and help at [https://jhipster.github.io/documentation-archive/v4.0.8](https://jhipster.github.io/documentation-archive/v4.0.8).
+
+This is a "microservice" application intended to be part of a microservice architecture, please refer to the [Doing microservices with JHipster][] page of the documentation for more information.
+
+This application is configured for Service Discovery and Configuration with the JHipster-Registry. On launch, it will refuse to start if it is not able to connect to the JHipster-Registry at [http://localhost:8761](http://localhost:8761). For more information, read our documentation on [Service Discovery and Configuration with the JHipster-Registry][].
+
+## Development
+
+To start your application in the dev profile, simply run:
+
+ ./mvnw
+
+
+For further instructions on how to develop with JHipster, have a look at [Using JHipster in development][].
+
+
+## Building for production
+
+To optimize the carapp application for production, run:
+
+ ./mvnw -Pprod clean package
+
+To ensure everything worked, run:
+
+ java -jar target/*.war
+
+
+Refer to [Using JHipster in production][] for more details.
+
+## Testing
+
+To launch your application's tests, run:
+
+ ./mvnw clean test
+
+For more information, refer to the [Running tests page][].
+
+## Using Docker to simplify development (optional)
+
+You can use Docker to improve your JHipster development experience. A number of docker-compose configuration are available in the [src/main/docker](src/main/docker) folder to launch required third party services.
+For example, to start a mysql database in a docker container, run:
+
+ docker-compose -f src/main/docker/mysql.yml up -d
+
+To stop it and remove the container, run:
+
+ docker-compose -f src/main/docker/mysql.yml down
+
+You can also fully dockerize your application and all the services that it depends on.
+To achieve this, first build a docker image of your app by running:
+
+ ./mvnw package -Pprod docker:build
+
+Then run:
+
+ docker-compose -f src/main/docker/app.yml up -d
+
+For more information refer to [Using Docker and Docker-Compose][], this page also contains information on the docker-compose sub-generator (`yo jhipster:docker-compose`), which is able to generate docker configurations for one or several JHipster applications.
+
+## Continuous Integration (optional)
+
+To configure CI for your project, run the ci-cd sub-generator (`yo jhipster:ci-cd`), this will let you generate configuration files for a number of Continuous Integration systems. Consult the [Setting up Continuous Integration][] page for more information.
+
+[JHipster Homepage and latest documentation]: https://jhipster.github.io
+[JHipster 4.0.8 archive]: https://jhipster.github.io/documentation-archive/v4.0.8
+[Doing microservices with JHipster]: https://jhipster.github.io/documentation-archive/v4.0.8/microservices-architecture/
+[Using JHipster in development]: https://jhipster.github.io/documentation-archive/v4.0.8/development/
+[Service Discovery and Configuration with the JHipster-Registry]: https://jhipster.github.io/documentation-archive/v4.0.8/microservices-architecture/#jhipster-registry
+[Using Docker and Docker-Compose]: https://jhipster.github.io/documentation-archive/v4.0.8/docker-compose
+[Using JHipster in production]: https://jhipster.github.io/documentation-archive/v4.0.8/production/
+[Running tests page]: https://jhipster.github.io/documentation-archive/v4.0.8/running-tests/
+[Setting up Continuous Integration]: https://jhipster.github.io/documentation-archive/v4.0.8/setting-up-ci/
+
+
diff --git a/jhipster/mvnw b/jhipster/jhipster-microservice/car-app/mvnw
similarity index 100%
rename from jhipster/mvnw
rename to jhipster/jhipster-microservice/car-app/mvnw
diff --git a/jhipster/mvnw.cmd b/jhipster/jhipster-microservice/car-app/mvnw.cmd
similarity index 100%
rename from jhipster/mvnw.cmd
rename to jhipster/jhipster-microservice/car-app/mvnw.cmd
diff --git a/jhipster/jhipster-microservice/car-app/package.json b/jhipster/jhipster-microservice/car-app/package.json
new file mode 100644
index 0000000000..ac56dd89a7
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/package.json
@@ -0,0 +1,5 @@
+{
+ "devDependencies": {
+ "generator-jhipster": "4.0.8"
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/pom.xml b/jhipster/jhipster-microservice/car-app/pom.xml
new file mode 100644
index 0000000000..bf26818f66
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/pom.xml
@@ -0,0 +1,928 @@
+
+
+ 4.0.0
+
+
+ spring-boot-starter-parent
+ org.springframework.boot
+ 1.5.2.RELEASE
+
+
+
+ com.car.app
+ carapp
+ 0.0.1-SNAPSHOT
+ war
+ Carapp
+
+
+ ${maven.version}
+
+
+
+ -Djava.security.egd=file:/dev/./urandom -Xmx256m
+ 3.6.2
+ 2.0.0
+ 2.5
+ 3.5
+ 0.4.13
+ 1.2
+ 5.2.8.Final
+ 2.6.0
+ 0.7.9
+ 1.8
+ 3.21.0-GA
+ 1.0.0
+ 1.1.0
+ 0.7.0
+ 3.6
+ 2.0.0
+ 4.8
+ jdt_apt
+ 1.1.0.Final
+ 3.6.0
+ 1.4.1
+ 3.0.1
+ yyyyMMddHHmmss
+ ${java.version}
+ ${java.version}
+ 3.0.0
+ 3.1.3
+ v6.10.0
+
+
+
+
+ ${project.build.directory}/test-results
+ 0.0.20
+ false
+ 3.2.2
+ 2.12.1
+ 3.2
+
+ src/main/webapp/content/**/*.*, src/main/webapp/bower_components/**/*.*, src/main/webapp/i18n/*.js, target/www/**/*.*
+
+ S3437,UndocumentedApi,BoldAndItalicTagsCheck
+
+
+ src/main/webapp/app/**/*.*
+ Web:BoldAndItalicTagsCheck
+
+ src/main/java/**/*
+ squid:S3437
+
+ src/main/java/**/*
+ squid:UndocumentedApi
+
+ ${project.testresult.directory}/coverage/jacoco/jacoco-it.exec
+ ${project.testresult.directory}/coverage/jacoco/jacoco.exec
+ jacoco
+
+ ${project.testresult.directory}/karma
+
+ ${project.testresult.directory}/coverage/report-lcov/lcov.info
+
+ ${project.testresult.directory}/coverage/report-lcov/lcov.info
+
+ ${project.basedir}/src/main/
+ ${project.testresult.directory}/surefire-reports
+ ${project.basedir}/src/test/
+
+ 2.5.0
+
+ Camden.SR5
+ 2.6.1
+ 1.4.10.Final
+ 1.1.0.Final
+ v0.21.3
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-hibernate5
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-hppc
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-json-org
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+
+
+ com.h2database
+ h2
+
+
+ com.hazelcast
+ hazelcast
+
+
+ com.hazelcast
+ hazelcast-hibernate52
+ ${hazelcast-hibernate52.version}
+
+
+ com.hazelcast
+ hazelcast-spring
+
+
+ com.jayway.jsonpath
+ json-path
+ test
+
+
+
+ com.mattbertolini
+ liquibase-slf4j
+ ${liquibase-slf4j.version}
+
+
+ com.ryantenney.metrics
+ metrics-spring
+ ${metrics-spring.version}
+
+
+ metrics-annotation
+ com.codahale.metrics
+
+
+ metrics-core
+ com.codahale.metrics
+
+
+ metrics-healthchecks
+ com.codahale.metrics
+
+
+
+
+ com.zaxxer
+ HikariCP
+
+
+ tools
+ com.sun
+
+
+
+
+
+ commons-io
+ commons-io
+ ${commons-io.version}
+
+
+ io.dropwizard.metrics
+ metrics-annotation
+ ${dropwizard-metrics.version}
+
+
+ io.dropwizard.metrics
+ metrics-core
+
+
+ io.dropwizard.metrics
+ metrics-json
+ ${dropwizard-metrics.version}
+
+
+ io.dropwizard.metrics
+ metrics-jvm
+ ${dropwizard-metrics.version}
+
+
+ io.dropwizard.metrics
+ metrics-servlet
+ ${dropwizard-metrics.version}
+
+
+ io.dropwizard.metrics
+ metrics-servlets
+
+
+ io.github.jhipster
+ jhipster
+ ${jhipster.server.version}
+
+
+ io.jsonwebtoken
+ jjwt
+ ${jjwt.version}
+
+
+ io.springfox
+ springfox-bean-validators
+ ${springfox.version}
+
+
+ io.springfox
+ springfox-swagger2
+ ${springfox.version}
+
+
+ mapstruct
+ org.mapstruct
+
+
+
+
+ javax.cache
+ cache-api
+
+
+ mysql
+ mysql-connector-java
+
+
+ net.logstash.logback
+ logstash-logback-encoder
+ ${logstash-logback-encoder.version}
+
+
+ logback-core
+ ch.qos.logback
+
+
+ logback-classic
+ ch.qos.logback
+
+
+ logback-access
+ ch.qos.logback
+
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang.version}
+
+
+ org.assertj
+ assertj-core
+ test
+
+
+ org.awaitility
+ awaitility
+ ${awaitility.version}
+ test
+
+
+ org.hibernate
+ hibernate-envers
+
+
+ org.hibernate
+ hibernate-validator
+
+
+ org.liquibase
+ liquibase-core
+
+
+ jetty-servlet
+ org.eclipse.jetty
+
+
+
+
+ org.mapstruct
+ mapstruct-jdk8
+ ${mapstruct.version}
+
+
+ org.springframework
+ spring-context-support
+
+
+ org.springframework.boot
+ spring-boot-actuator
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ org.springframework.boot
+ spring-boot-loader-tools
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+ org.springframework.boot
+ spring-boot-starter-cloud-connectors
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+ org.springframework.boot
+ spring-boot-starter-mail
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ spring-boot-starter-tomcat
+ org.springframework.boot
+
+
+
+
+ org.springframework.boot
+ spring-boot-test
+ test
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+ org.springframework.cloud
+ spring-cloud-starter-feign
+
+
+ org.springframework.cloud
+ spring-cloud-starter-hystrix
+
+
+ org.springframework.cloud
+ spring-cloud-starter-ribbon
+
+
+
+ netty-transport-native-epoll
+ io.netty
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-spectator
+
+
+ org.springframework.retry
+ spring-retry
+
+
+
+ org.springframework.security
+ spring-security-data
+
+
+ org.springframework.security
+ spring-security-test
+ test
+
+
+
+
+ spring-boot:run
+
+
+
+
+ org.eclipse.m2e
+ lifecycle-mapping
+ 1.0.0
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ ${jacoco-maven-plugin.version}
+
+ prepare-agent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ com.github.ekryd.sortpom
+ sortpom-maven-plugin
+ ${sortpom-maven-plugin.version}
+
+
+ verify
+
+ sort
+
+
+
+
+ true
+ 4
+ groupId,artifactId
+ groupId,artifactId
+ true
+ false
+
+
+
+ com.spotify
+ docker-maven-plugin
+ ${docker-maven-plugin.version}
+
+ carapp
+ src/main/docker
+
+
+ /
+ ${project.build.directory}
+ ${project.build.finalName}.war
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+
+
+ org.mapstruct
+ mapstruct-processor
+ ${mapstruct.version}
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-eclipse-plugin
+
+ true
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ ${maven-enforcer-plugin.version}
+
+
+ enforce-versions
+
+ enforce
+
+
+
+
+
+
+ You are running an older version of Maven. JHipster requires at least Maven ${maven.version}
+ [${maven.version},)
+
+
+ You are running an older version of Java. JHipster requires at least JDK ${java.version}
+ [${java.version}.0,)
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ ${maven-resources-plugin.version}
+
+
+ default-resources
+ validate
+
+ copy-resources
+
+
+ target/classes
+ false
+
+ #
+
+
+
+ src/main/resources/
+ true
+
+ **/*.xml
+ **/*.yml
+
+
+
+ src/main/resources/
+ false
+
+ **/*.xml
+ **/*.yml
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ alphabetical
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ ${jacoco-maven-plugin.version}
+
+
+ pre-unit-tests
+
+ prepare-agent
+
+
+
+ ${project.testresult.directory}/coverage/jacoco/jacoco.exec
+
+
+
+
+ post-unit-test
+ test
+
+ report
+
+
+ ${project.testresult.directory}/coverage/jacoco/jacoco.exec
+ ${project.testresult.directory}/coverage/jacoco
+
+
+
+
+
+ org.liquibase
+ liquibase-maven-plugin
+ ${liquibase.version}
+
+
+ javax.validation
+ validation-api
+ ${validation-api.version}
+
+
+ org.javassist
+ javassist
+ ${javassist.version}
+
+
+ org.liquibase.ext
+ liquibase-hibernate5
+ ${liquibase-hibernate5.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+ ${project.parent.version}
+
+
+
+ src/main/resources/config/liquibase/master.xml
+ src/main/resources/config/liquibase/changelog/${maven.build.timestamp}_changelog.xml
+ org.h2.Driver
+ jdbc:h2:file:./target/h2db/db/carapp
+
+ carapp
+
+ hibernate:spring:com.car.app.domain?dialect=org.hibernate.dialect.H2Dialect&hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy&hibernate.implicit_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
+ true
+ debug
+
+
+
+ org.sonarsource.scanner.maven
+ sonar-maven-plugin
+ ${sonar-maven-plugin.version}
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+ true
+
+
+
+
+
+
+
+
+ no-liquibase
+
+ ,no-liquibase
+
+
+
+ swagger
+
+ ,swagger
+
+
+
+ dev
+
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
+
+
+
+
+
+ DEBUG
+
+ dev${profile.no-liquibase}
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-undertow
+
+
+
+
+ prod
+
+
+
+ maven-clean-plugin
+
+
+
+ target/www/
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ build-info
+
+
+
+
+ true
+
+
+
+
+
+
+ INFO
+
+ prod${profile.swagger}${profile.no-liquibase}
+
+
+
+ org.springframework.boot
+ spring-boot-starter-undertow
+
+
+
+
+
+ cc
+
+
+
+ net.alchim31.maven
+ scala-maven-plugin
+ ${scala-maven-plugin.version}
+
+
+ compile
+ compile
+
+ add-source
+ compile
+
+
+
+ test-compile
+ test-compile
+
+ add-source
+ testCompile
+
+
+
+
+ incremental
+ true
+ ${scala.version}
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ default-compile
+ none
+
+
+ default-testCompile
+ none
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
+ src/main/webapp/
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+ true
+ true
+
+
+
+
+
+
+
+ DEBUG
+
+ dev,swagger
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-undertow
+
+
+
+
+
+ graphite
+
+
+ io.dropwizard.metrics
+ metrics-graphite
+
+
+
+
+
+ prometheus
+
+
+ io.prometheus
+ simpleclient
+ ${prometheus-simpleclient.version}
+
+
+ io.prometheus
+ simpleclient_dropwizard
+ ${prometheus-simpleclient.version}
+
+
+ io.prometheus
+ simpleclient_servlet
+ ${prometheus-simpleclient.version}
+
+
+
+
+
+ IDE
+
+
+ org.mapstruct
+ mapstruct-processor
+ ${mapstruct.version}
+
+
+
+
+
diff --git a/jhipster/jhipster-microservice/car-app/src/main/docker/Dockerfile b/jhipster/jhipster-microservice/car-app/src/main/docker/Dockerfile
new file mode 100644
index 0000000000..037e197be6
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/docker/Dockerfile
@@ -0,0 +1,13 @@
+FROM openjdk:8-jre-alpine
+
+ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \
+ JHIPSTER_SLEEP=0
+
+# add directly the war
+ADD *.war /app.war
+
+VOLUME /tmp
+EXPOSE 8081 5701/udp
+CMD echo "The application will start in ${JHIPSTER_SLEEP}s..." && \
+ sleep ${JHIPSTER_SLEEP} && \
+ java -Djava.security.egd=file:/dev/./urandom -jar /app.war
diff --git a/jhipster/jhipster-microservice/car-app/src/main/docker/app.yml b/jhipster/jhipster-microservice/car-app/src/main/docker/app.yml
new file mode 100644
index 0000000000..0904a7335d
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/docker/app.yml
@@ -0,0 +1,19 @@
+version: '2'
+services:
+ carapp-app:
+ image: carapp
+ environment:
+ - SPRING_PROFILES_ACTIVE=prod,swagger
+ - SPRING_CLOUD_CONFIG_URI=http://admin:$${jhipster.registry.password}@jhipster-registry:8761/config
+ - SPRING_DATASOURCE_URL=jdbc:mysql://carapp-mysql:3306/carapp?useUnicode=true&characterEncoding=utf8&useSSL=false
+ - JHIPSTER_SLEEP=10 # gives time for the database to boot before the application
+ carapp-mysql:
+ extends:
+ file: mysql.yml
+ service: carapp-mysql
+ jhipster-registry:
+ extends:
+ file: jhipster-registry.yml
+ service: jhipster-registry
+ environment:
+ - SPRING_CLOUD_CONFIG_SERVER_NATIVE_SEARCH_LOCATIONS=file:./central-config/docker-config/
diff --git a/jhipster/jhipster-microservice/car-app/src/main/docker/central-server-config/README.md b/jhipster/jhipster-microservice/car-app/src/main/docker/central-server-config/README.md
new file mode 100644
index 0000000000..022a152863
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/docker/central-server-config/README.md
@@ -0,0 +1,7 @@
+# Central configuration sources details
+
+The JHipster-Registry will use the following directories as its configuration source :
+- localhost-config : when running the registry in docker with the jhipster-registry.yml docker-compose file
+- docker-config : when running the registry and the app both in docker with the app.yml docker-compose file
+
+For more info, refer to http://jhipster.github.io/microservices-architecture/#registry_app_configuration
diff --git a/jhipster/jhipster-microservice/car-app/src/main/docker/central-server-config/docker-config/application.yml b/jhipster/jhipster-microservice/car-app/src/main/docker/central-server-config/docker-config/application.yml
new file mode 100644
index 0000000000..f11d367241
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/docker/central-server-config/docker-config/application.yml
@@ -0,0 +1,15 @@
+# Common configuration shared between all applications
+configserver:
+ name: Docker JHipster Registry
+ status: Connected to the JHipster Registry running in Docker
+
+jhipster:
+ security:
+ authentication:
+ jwt:
+ secret: my-secret-token-to-change-in-production
+
+eureka:
+ client:
+ serviceUrl:
+ defaultZone: http://admin:${jhipster.registry.password}@jhipster-registry:8761/eureka/
diff --git a/jhipster/jhipster-microservice/car-app/src/main/docker/central-server-config/localhost-config/application.yml b/jhipster/jhipster-microservice/car-app/src/main/docker/central-server-config/localhost-config/application.yml
new file mode 100644
index 0000000000..052a6d0535
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/docker/central-server-config/localhost-config/application.yml
@@ -0,0 +1,15 @@
+# Common configuration shared between all applications
+configserver:
+ name: Docker JHipster Registry
+ status: Connected to the JHipster Registry running in Docker
+
+jhipster:
+ security:
+ authentication:
+ jwt:
+ secret: my-secret-token-to-change-in-production
+
+eureka:
+ client:
+ serviceUrl:
+ defaultZone: http://admin:${jhipster.registry.password}@localhost:8761/eureka/
diff --git a/jhipster/jhipster-microservice/car-app/src/main/docker/jhipster-registry.yml b/jhipster/jhipster-microservice/car-app/src/main/docker/jhipster-registry.yml
new file mode 100644
index 0000000000..58feb685d4
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/docker/jhipster-registry.yml
@@ -0,0 +1,18 @@
+version: '2'
+services:
+ jhipster-registry:
+ image: jhipster/jhipster-registry:v2.5.8
+ volumes:
+ - ./central-server-config:/central-config
+ # When run with the "dev" Spring profile, the JHipster Registry will
+ # read the config from the local filesystem (central-server-config directory)
+ # When run with the "prod" Spring profile, it will read the config from a git repository
+ # See http://jhipster.github.io/microservices-architecture/#registry_app_configuration
+ environment:
+ - SPRING_PROFILES_ACTIVE=dev
+ - SECURITY_USER_PASSWORD=admin
+ - SPRING_CLOUD_CONFIG_SERVER_NATIVE_SEARCH_LOCATIONS=file:./central-config/localhost-config/
+ # - GIT_URI=https://github.com/jhipster/jhipster-registry/
+ # - GIT_SEARCH_PATHS=central-config
+ ports:
+ - 8761:8761
diff --git a/jhipster/jhipster-microservice/car-app/src/main/docker/mysql.yml b/jhipster/jhipster-microservice/car-app/src/main/docker/mysql.yml
new file mode 100644
index 0000000000..151facca36
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/docker/mysql.yml
@@ -0,0 +1,13 @@
+version: '2'
+services:
+ carapp-mysql:
+ image: mysql:5.7.13
+ # volumes:
+ # - ~/volumes/jhipster/carapp/mysql/:/var/lib/mysql/
+ environment:
+ - MYSQL_USER=root
+ - MYSQL_ALLOW_EMPTY_PASSWORD=yes
+ - MYSQL_DATABASE=carapp
+ ports:
+ - 3306:3306
+ command: mysqld --lower_case_table_names=1 --skip-ssl --character_set_server=utf8
diff --git a/jhipster/jhipster-microservice/car-app/src/main/docker/sonar.yml b/jhipster/jhipster-microservice/car-app/src/main/docker/sonar.yml
new file mode 100644
index 0000000000..353e034f40
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/docker/sonar.yml
@@ -0,0 +1,7 @@
+version: '2'
+services:
+ carapp-sonar:
+ image: sonarqube:6.2-alpine
+ ports:
+ - 9000:9000
+ - 9092:9092
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/ApplicationWebXml.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/ApplicationWebXml.java
new file mode 100644
index 0000000000..edd9098f8a
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/ApplicationWebXml.java
@@ -0,0 +1,21 @@
+package com.car.app;
+
+import com.car.app.config.DefaultProfileUtil;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.support.SpringBootServletInitializer;
+
+/**
+ * This is a helper Java class that provides an alternative to creating a web.xml.
+ * This will be invoked only when the application is deployed to a servlet container like Tomcat, JBoss etc.
+ */
+public class ApplicationWebXml extends SpringBootServletInitializer {
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ /**
+ * set a default to use when no profile is configured.
+ */
+ DefaultProfileUtil.addDefaultProfile(application.application());
+ return application.sources(CarappApp.class);
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/CarappApp.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/CarappApp.java
new file mode 100644
index 0000000000..b85a50b156
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/CarappApp.java
@@ -0,0 +1,91 @@
+package com.car.app;
+
+import com.car.app.config.ApplicationProperties;
+import com.car.app.config.DefaultProfileUtil;
+
+import io.github.jhipster.config.JHipsterConstants;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.actuate.autoconfigure.*;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.core.env.Environment;
+
+import javax.annotation.PostConstruct;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.Collection;
+
+@ComponentScan
+@EnableAutoConfiguration(exclude = {MetricFilterAutoConfiguration.class, MetricRepositoryAutoConfiguration.class})
+@EnableConfigurationProperties({LiquibaseProperties.class, ApplicationProperties.class})
+@EnableDiscoveryClient
+public class CarappApp {
+
+ private static final Logger log = LoggerFactory.getLogger(CarappApp.class);
+
+ private final Environment env;
+
+ public CarappApp(Environment env) {
+ this.env = env;
+ }
+
+ /**
+ * Initializes carapp.
+ *
+ * Spring profiles can be configured with a program arguments --spring.profiles.active=your-active-profile
+ *
+ * You can find more information on how profiles work with JHipster on http://jhipster.github.io/profiles/.
+ */
+ @PostConstruct
+ public void initApplication() {
+ Collection activeProfiles = Arrays.asList(env.getActiveProfiles());
+ if (activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) && activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_PRODUCTION)) {
+ log.error("You have misconfigured your application! It should not run " +
+ "with both the 'dev' and 'prod' profiles at the same time.");
+ }
+ if (activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) && activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_CLOUD)) {
+ log.error("You have misconfigured your application! It should not" +
+ "run with both the 'dev' and 'cloud' profiles at the same time.");
+ }
+ }
+
+ /**
+ * Main method, used to run the application.
+ *
+ * @param args the command line arguments
+ * @throws UnknownHostException if the local host name could not be resolved into an address
+ */
+ public static void main(String[] args) throws UnknownHostException {
+ SpringApplication app = new SpringApplication(CarappApp.class);
+ DefaultProfileUtil.addDefaultProfile(app);
+ Environment env = app.run(args).getEnvironment();
+ String protocol = "http";
+ if (env.getProperty("server.ssl.key-store") != null) {
+ protocol = "https";
+ }
+ log.info("\n----------------------------------------------------------\n\t" +
+ "Application '{}' is running! Access URLs:\n\t" +
+ "Local: \t\t{}://localhost:{}\n\t" +
+ "External: \t{}://{}:{}\n\t" +
+ "Profile(s): \t{}\n----------------------------------------------------------",
+ env.getProperty("spring.application.name"),
+ protocol,
+ env.getProperty("server.port"),
+ protocol,
+ InetAddress.getLocalHost().getHostAddress(),
+ env.getProperty("server.port"),
+ env.getActiveProfiles());
+
+ String configServerStatus = env.getProperty("configserver.status");
+ log.info("\n----------------------------------------------------------\n\t" +
+ "Config Server: \t{}\n----------------------------------------------------------",
+ configServerStatus == null ? "Not found or not setup for this application" : configServerStatus);
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/aop/logging/LoggingAspect.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/aop/logging/LoggingAspect.java
new file mode 100644
index 0000000000..7171abbcd2
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/aop/logging/LoggingAspect.java
@@ -0,0 +1,79 @@
+package com.car.app.aop.logging;
+
+import io.github.jhipster.config.JHipsterConstants;
+
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.env.Environment;
+
+import java.util.Arrays;
+
+/**
+ * Aspect for logging execution of service and repository Spring components.
+ *
+ * By default, it only runs with the "dev" profile.
+ */
+@Aspect
+public class LoggingAspect {
+
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+ private final Environment env;
+
+ public LoggingAspect(Environment env) {
+ this.env = env;
+ }
+
+ /**
+ * Pointcut that matches all repositories, services and Web REST endpoints.
+ */
+ @Pointcut("within(com.car.app.repository..*) || within(com.car.app.service..*) || within(com.car.app.web.rest..*)")
+ public void loggingPointcut() {
+ // Method is empty as this is just a Pointcut, the implementations are in the advices.
+ }
+
+ /**
+ * Advice that logs methods throwing exceptions.
+ */
+ @AfterThrowing(pointcut = "loggingPointcut()", throwing = "e")
+ public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
+ if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
+ log.error("Exception in {}.{}() with cause = \'{}\' and exception = \'{}\'", joinPoint.getSignature().getDeclaringTypeName(),
+ joinPoint.getSignature().getName(), e.getCause() != null? e.getCause() : "NULL", e.getMessage(), e);
+
+ } else {
+ log.error("Exception in {}.{}() with cause = {}", joinPoint.getSignature().getDeclaringTypeName(),
+ joinPoint.getSignature().getName(), e.getCause() != null? e.getCause() : "NULL");
+ }
+ }
+
+ /**
+ * Advice that logs when a method is entered and exited.
+ */
+ @Around("loggingPointcut()")
+ public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
+ if (log.isDebugEnabled()) {
+ log.debug("Enter: {}.{}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
+ joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
+ }
+ try {
+ Object result = joinPoint.proceed();
+ if (log.isDebugEnabled()) {
+ log.debug("Exit: {}.{}() with result = {}", joinPoint.getSignature().getDeclaringTypeName(),
+ joinPoint.getSignature().getName(), result);
+ }
+ return result;
+ } catch (IllegalArgumentException e) {
+ log.error("Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()),
+ joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
+
+ throw e;
+ }
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/ApplicationProperties.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/ApplicationProperties.java
new file mode 100644
index 0000000000..1f69dd1529
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/ApplicationProperties.java
@@ -0,0 +1,15 @@
+package com.car.app.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * Properties specific to JHipster.
+ *
+ *
+ * Properties are configured in the application.yml file.
+ *
+ */
+@ConfigurationProperties(prefix = "application", ignoreUnknownFields = false)
+public class ApplicationProperties {
+
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/AsyncConfiguration.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/AsyncConfiguration.java
new file mode 100644
index 0000000000..67cb2ad402
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/AsyncConfiguration.java
@@ -0,0 +1,46 @@
+package com.car.app.config;
+
+import io.github.jhipster.async.ExceptionHandlingAsyncTaskExecutor;
+import io.github.jhipster.config.JHipsterProperties;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
+import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.*;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+
+@Configuration
+@EnableAsync
+@EnableScheduling
+public class AsyncConfiguration implements AsyncConfigurer {
+
+ private final Logger log = LoggerFactory.getLogger(AsyncConfiguration.class);
+
+ private final JHipsterProperties jHipsterProperties;
+
+ public AsyncConfiguration(JHipsterProperties jHipsterProperties) {
+ this.jHipsterProperties = jHipsterProperties;
+ }
+
+ @Override
+ @Bean(name = "taskExecutor")
+ public Executor getAsyncExecutor() {
+ log.debug("Creating Async Task Executor");
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ executor.setCorePoolSize(jHipsterProperties.getAsync().getCorePoolSize());
+ executor.setMaxPoolSize(jHipsterProperties.getAsync().getMaxPoolSize());
+ executor.setQueueCapacity(jHipsterProperties.getAsync().getQueueCapacity());
+ executor.setThreadNamePrefix("carapp-Executor-");
+ return new ExceptionHandlingAsyncTaskExecutor(executor);
+ }
+
+ @Override
+ public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
+ return new SimpleAsyncUncaughtExceptionHandler();
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/CacheConfiguration.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/CacheConfiguration.java
new file mode 100644
index 0000000000..0fdfff40f8
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/CacheConfiguration.java
@@ -0,0 +1,134 @@
+package com.car.app.config;
+
+import io.github.jhipster.config.JHipsterConstants;
+import io.github.jhipster.config.JHipsterProperties;
+
+import com.hazelcast.config.Config;
+import com.hazelcast.core.HazelcastInstance;
+import com.hazelcast.core.Hazelcast;
+import com.hazelcast.config.MapConfig;
+import com.hazelcast.config.EvictionPolicy;
+import com.hazelcast.config.MaxSizeConfig;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.web.ServerProperties;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.cloud.client.discovery.DiscoveryClient;
+import org.springframework.context.annotation.*;
+import org.springframework.core.env.Environment;
+
+import javax.annotation.PreDestroy;
+
+@Configuration
+@EnableCaching
+@AutoConfigureAfter(value = { MetricsConfiguration.class })
+@AutoConfigureBefore(value = { WebConfigurer.class, DatabaseConfiguration.class })
+public class CacheConfiguration {
+
+ private final Logger log = LoggerFactory.getLogger(CacheConfiguration.class);
+
+ private final Environment env;
+
+ private final DiscoveryClient discoveryClient;
+
+ private final ServerProperties serverProperties;
+
+ public CacheConfiguration(Environment env, DiscoveryClient discoveryClient, ServerProperties serverProperties) {
+ this.env = env;
+ this.discoveryClient = discoveryClient;
+ this.serverProperties = serverProperties;
+ }
+
+ @PreDestroy
+ public void destroy() {
+ log.info("Closing Cache Manager");
+ Hazelcast.shutdownAll();
+ }
+
+ @Bean
+ public CacheManager cacheManager(HazelcastInstance hazelcastInstance) {
+ log.debug("Starting HazelcastCacheManager");
+ CacheManager cacheManager = new com.hazelcast.spring.cache.HazelcastCacheManager(hazelcastInstance);
+ return cacheManager;
+ }
+
+ @Bean
+ public HazelcastInstance hazelcastInstance(JHipsterProperties jHipsterProperties) {
+ log.debug("Configuring Hazelcast");
+ Config config = new Config();
+ config.setInstanceName("carapp");
+ // The serviceId is by default the application's name, see Spring Boot's eureka.instance.appname property
+ String serviceId = discoveryClient.getLocalServiceInstance().getServiceId();
+ log.debug("Configuring Hazelcast clustering for instanceId: {}", serviceId);
+
+ // In development, everything goes through 127.0.0.1, with a different port
+ if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
+ log.debug("Application is running with the \"dev\" profile, Hazelcast " +
+ "cluster will only work with localhost instances");
+
+ System.setProperty("hazelcast.local.localAddress", "127.0.0.1");
+ config.getNetworkConfig().setPort(serverProperties.getPort() + 5701);
+ config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false);
+ config.getNetworkConfig().getJoin().getTcpIpConfig().setEnabled(true);
+ for (ServiceInstance instance : discoveryClient.getInstances(serviceId)) {
+ String clusterMember = "127.0.0.1:" + (instance.getPort() + 5701);
+ log.debug("Adding Hazelcast (dev) cluster member " + clusterMember);
+ config.getNetworkConfig().getJoin().getTcpIpConfig().addMember(clusterMember);
+ }
+ } else { // Production configuration, one host per instance all using port 5701
+ config.getNetworkConfig().setPort(5701);
+ config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false);
+ config.getNetworkConfig().getJoin().getTcpIpConfig().setEnabled(true);
+ for (ServiceInstance instance : discoveryClient.getInstances(serviceId)) {
+ String clusterMember = instance.getHost() + ":5701";
+ log.debug("Adding Hazelcast (prod) cluster member " + clusterMember);
+ config.getNetworkConfig().getJoin().getTcpIpConfig().addMember(clusterMember);
+ }
+ }
+ config.getMapConfigs().put("default", initializeDefaultMapConfig());
+ config.getMapConfigs().put("com.car.app.domain.*", initializeDomainMapConfig(jHipsterProperties));
+ return Hazelcast.newHazelcastInstance(config);
+ }
+
+ private MapConfig initializeDefaultMapConfig() {
+ MapConfig mapConfig = new MapConfig();
+
+ /*
+ Number of backups. If 1 is set as the backup-count for example,
+ then all entries of the map will be copied to another JVM for
+ fail-safety. Valid numbers are 0 (no backup), 1, 2, 3.
+ */
+ mapConfig.setBackupCount(0);
+
+ /*
+ Valid values are:
+ NONE (no eviction),
+ LRU (Least Recently Used),
+ LFU (Least Frequently Used).
+ NONE is the default.
+ */
+ mapConfig.setEvictionPolicy(EvictionPolicy.LRU);
+
+ /*
+ Maximum size of the map. When max size is reached,
+ map is evicted based on the policy defined.
+ Any integer between 0 and Integer.MAX_VALUE. 0 means
+ Integer.MAX_VALUE. Default is 0.
+ */
+ mapConfig.setMaxSizeConfig(new MaxSizeConfig(0, MaxSizeConfig.MaxSizePolicy.USED_HEAP_SIZE));
+
+ return mapConfig;
+ }
+
+ private MapConfig initializeDomainMapConfig(JHipsterProperties jHipsterProperties) {
+ MapConfig mapConfig = new MapConfig();
+ mapConfig.setTimeToLiveSeconds(jHipsterProperties.getCache().getHazelcast().getTimeToLiveSeconds());
+ return mapConfig;
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/CloudDatabaseConfiguration.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/CloudDatabaseConfiguration.java
new file mode 100644
index 0000000000..2ca29491c9
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/CloudDatabaseConfiguration.java
@@ -0,0 +1,24 @@
+package com.car.app.config;
+
+import io.github.jhipster.config.JHipsterConstants;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cache.CacheManager;
+import org.springframework.cloud.config.java.AbstractCloudConfig;
+import org.springframework.context.annotation.*;
+
+import javax.sql.DataSource;
+
+@Configuration
+@Profile(JHipsterConstants.SPRING_PROFILE_CLOUD)
+public class CloudDatabaseConfiguration extends AbstractCloudConfig {
+
+ private final Logger log = LoggerFactory.getLogger(CloudDatabaseConfiguration.class);
+
+ @Bean
+ public DataSource dataSource(CacheManager cacheManager) {
+ log.info("Configuring JDBC datasource from a cloud provider");
+ return connectionFactory().dataSource();
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/Constants.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/Constants.java
new file mode 100644
index 0000000000..260a3bbce8
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/Constants.java
@@ -0,0 +1,16 @@
+package com.car.app.config;
+
+/**
+ * Application constants.
+ */
+public final class Constants {
+
+ //Regex for acceptable logins
+ public static final String LOGIN_REGEX = "^[_'.@A-Za-z0-9-]*$";
+
+ public static final String SYSTEM_ACCOUNT = "system";
+ public static final String ANONYMOUS_USER = "anonymoususer";
+
+ private Constants() {
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/DatabaseConfiguration.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/DatabaseConfiguration.java
new file mode 100644
index 0000000000..35a8ee3f48
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/DatabaseConfiguration.java
@@ -0,0 +1,75 @@
+package com.car.app.config;
+
+import io.github.jhipster.config.JHipsterConstants;
+import io.github.jhipster.config.liquibase.AsyncSpringLiquibase;
+
+import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
+import liquibase.integration.spring.SpringLiquibase;
+import org.h2.tools.Server;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.core.env.Environment;
+import org.springframework.core.task.TaskExecutor;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import javax.sql.DataSource;
+import java.sql.SQLException;
+
+@Configuration
+@EnableJpaRepositories("com.car.app.repository")
+@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
+@EnableTransactionManagement
+public class DatabaseConfiguration {
+
+ private final Logger log = LoggerFactory.getLogger(DatabaseConfiguration.class);
+
+ private final Environment env;
+
+ public DatabaseConfiguration(Environment env) {
+ this.env = env;
+ }
+
+ /**
+ * Open the TCP port for the H2 database, so it is available remotely.
+ *
+ * @return the H2 database TCP server
+ * @throws SQLException if the server failed to start
+ */
+ @Bean(initMethod = "start", destroyMethod = "stop")
+ @Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)
+ public Server h2TCPServer() throws SQLException {
+ return Server.createTcpServer("-tcp","-tcpAllowOthers");
+ }
+
+ @Bean
+ public SpringLiquibase liquibase(@Qualifier("taskExecutor") TaskExecutor taskExecutor,
+ DataSource dataSource, LiquibaseProperties liquibaseProperties) {
+
+ // Use liquibase.integration.spring.SpringLiquibase if you don't want Liquibase to start asynchronously
+ SpringLiquibase liquibase = new AsyncSpringLiquibase(taskExecutor, env);
+ liquibase.setDataSource(dataSource);
+ liquibase.setChangeLog("classpath:config/liquibase/master.xml");
+ liquibase.setContexts(liquibaseProperties.getContexts());
+ liquibase.setDefaultSchema(liquibaseProperties.getDefaultSchema());
+ liquibase.setDropFirst(liquibaseProperties.isDropFirst());
+ if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_NO_LIQUIBASE)) {
+ liquibase.setShouldRun(false);
+ } else {
+ liquibase.setShouldRun(liquibaseProperties.isEnabled());
+ log.debug("Configuring Liquibase");
+ }
+ return liquibase;
+ }
+
+ @Bean
+ public Hibernate5Module hibernate5Module() {
+ return new Hibernate5Module();
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/DateTimeFormatConfiguration.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/DateTimeFormatConfiguration.java
new file mode 100644
index 0000000000..67fff05c84
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/DateTimeFormatConfiguration.java
@@ -0,0 +1,17 @@
+package com.car.app.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.format.FormatterRegistry;
+import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+
+@Configuration
+public class DateTimeFormatConfiguration extends WebMvcConfigurerAdapter {
+
+ @Override
+ public void addFormatters(FormatterRegistry registry) {
+ DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
+ registrar.setUseIsoFormat(true);
+ registrar.registerFormatters(registry);
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/DefaultProfileUtil.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/DefaultProfileUtil.java
new file mode 100644
index 0000000000..640458f9db
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/DefaultProfileUtil.java
@@ -0,0 +1,48 @@
+package com.car.app.config;
+
+import io.github.jhipster.config.JHipsterConstants;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.core.env.Environment;
+
+import java.util.*;
+
+/**
+ * Utility class to load a Spring profile to be used as default
+ * when there is no spring.profiles.active set in the environment or as command line argument.
+ * If the value is not available in application.yml then dev profile will be used as default.
+ */
+public final class DefaultProfileUtil {
+
+ private static final String SPRING_PROFILE_DEFAULT = "spring.profiles.default";
+
+ private DefaultProfileUtil() {
+ }
+
+ /**
+ * Set a default to use when no profile is configured.
+ *
+ * @param app the Spring application
+ */
+ public static void addDefaultProfile(SpringApplication app) {
+ Map defProperties = new HashMap<>();
+ /*
+ * The default profile to use when no other profiles are defined
+ * This cannot be set in the application.yml file.
+ * See https://github.com/spring-projects/spring-boot/issues/1219
+ */
+ defProperties.put(SPRING_PROFILE_DEFAULT, JHipsterConstants.SPRING_PROFILE_DEVELOPMENT);
+ app.setDefaultProperties(defProperties);
+ }
+
+ /**
+ * Get the profiles that are applied else get default profiles.
+ */
+ public static String[] getActiveProfiles(Environment env) {
+ String[] profiles = env.getActiveProfiles();
+ if (profiles.length == 0) {
+ return env.getDefaultProfiles();
+ }
+ return profiles;
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/LocaleConfiguration.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/LocaleConfiguration.java
new file mode 100644
index 0000000000..92adfb7f66
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/LocaleConfiguration.java
@@ -0,0 +1,35 @@
+package com.car.app.config;
+
+import io.github.jhipster.config.locale.AngularCookieLocaleResolver;
+
+import org.springframework.context.EnvironmentAware;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+import org.springframework.web.servlet.LocaleResolver;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
+
+@Configuration
+public class LocaleConfiguration extends WebMvcConfigurerAdapter implements EnvironmentAware {
+
+ @Override
+ public void setEnvironment(Environment environment) {
+ // unused
+ }
+
+ @Bean(name = "localeResolver")
+ public LocaleResolver localeResolver() {
+ AngularCookieLocaleResolver cookieLocaleResolver = new AngularCookieLocaleResolver();
+ cookieLocaleResolver.setCookieName("NG_TRANSLATE_LANG_KEY");
+ return cookieLocaleResolver;
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
+ localeChangeInterceptor.setParamName("language");
+ registry.addInterceptor(localeChangeInterceptor);
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/LoggingAspectConfiguration.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/LoggingAspectConfiguration.java
new file mode 100644
index 0000000000..e7370c954f
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/LoggingAspectConfiguration.java
@@ -0,0 +1,19 @@
+package com.car.app.config;
+
+import com.car.app.aop.logging.LoggingAspect;
+
+import io.github.jhipster.config.JHipsterConstants;
+
+import org.springframework.context.annotation.*;
+import org.springframework.core.env.Environment;
+
+@Configuration
+@EnableAspectJAutoProxy
+public class LoggingAspectConfiguration {
+
+ @Bean
+ @Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)
+ public LoggingAspect loggingAspect(Environment env) {
+ return new LoggingAspect(env);
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/LoggingConfiguration.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/LoggingConfiguration.java
new file mode 100644
index 0000000000..318323ae7c
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/LoggingConfiguration.java
@@ -0,0 +1,113 @@
+package com.car.app.config;
+
+import io.github.jhipster.config.JHipsterProperties;
+
+import ch.qos.logback.classic.AsyncAppender;
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.spi.LoggerContextListener;
+import ch.qos.logback.core.spi.ContextAwareBase;
+import net.logstash.logback.appender.LogstashSocketAppender;
+import net.logstash.logback.stacktrace.ShortenedThrowableConverter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class LoggingConfiguration {
+
+ private final Logger log = LoggerFactory.getLogger(LoggingConfiguration.class);
+
+ private LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
+
+ @Value("${spring.application.name}")
+ private String appName;
+
+ @Value("${server.port}")
+ private String serverPort;
+
+ @Value("${eureka.instance.instanceId}")
+ private String instanceId;
+
+ private final JHipsterProperties jHipsterProperties;
+
+ public LoggingConfiguration(JHipsterProperties jHipsterProperties) {
+ this.jHipsterProperties = jHipsterProperties;
+ if (jHipsterProperties.getLogging().getLogstash().isEnabled()) {
+ addLogstashAppender(context);
+
+ // Add context listener
+ LogbackLoggerContextListener loggerContextListener = new LogbackLoggerContextListener();
+ loggerContextListener.setContext(context);
+ context.addListener(loggerContextListener);
+ }
+ }
+
+ public void addLogstashAppender(LoggerContext context) {
+ log.info("Initializing Logstash logging");
+
+ LogstashSocketAppender logstashAppender = new LogstashSocketAppender();
+ logstashAppender.setName("LOGSTASH");
+ logstashAppender.setContext(context);
+ String customFields = "{\"app_name\":\"" + appName + "\",\"app_port\":\"" + serverPort + "\"," +
+ "\"instance_id\":\"" + instanceId + "\"}";
+
+ // Set the Logstash appender config from JHipster properties
+ logstashAppender.setSyslogHost(jHipsterProperties.getLogging().getLogstash().getHost());
+ logstashAppender.setPort(jHipsterProperties.getLogging().getLogstash().getPort());
+ logstashAppender.setCustomFields(customFields);
+
+ // Limit the maximum length of the forwarded stacktrace so that it won't exceed the 8KB UDP limit of logstash
+ ShortenedThrowableConverter throwableConverter = new ShortenedThrowableConverter();
+ throwableConverter.setMaxLength(7500);
+ throwableConverter.setRootCauseFirst(true);
+ logstashAppender.setThrowableConverter(throwableConverter);
+
+ logstashAppender.start();
+
+ // Wrap the appender in an Async appender for performance
+ AsyncAppender asyncLogstashAppender = new AsyncAppender();
+ asyncLogstashAppender.setContext(context);
+ asyncLogstashAppender.setName("ASYNC_LOGSTASH");
+ asyncLogstashAppender.setQueueSize(jHipsterProperties.getLogging().getLogstash().getQueueSize());
+ asyncLogstashAppender.addAppender(logstashAppender);
+ asyncLogstashAppender.start();
+
+ context.getLogger("ROOT").addAppender(asyncLogstashAppender);
+ }
+
+ /**
+ * Logback configuration is achieved by configuration file and API.
+ * When configuration file change is detected, the configuration is reset.
+ * This listener ensures that the programmatic configuration is also re-applied after reset.
+ */
+ class LogbackLoggerContextListener extends ContextAwareBase implements LoggerContextListener {
+
+ @Override
+ public boolean isResetResistant() {
+ return true;
+ }
+
+ @Override
+ public void onStart(LoggerContext context) {
+ addLogstashAppender(context);
+ }
+
+ @Override
+ public void onReset(LoggerContext context) {
+ addLogstashAppender(context);
+ }
+
+ @Override
+ public void onStop(LoggerContext context) {
+ // Nothing to do.
+ }
+
+ @Override
+ public void onLevelChange(ch.qos.logback.classic.Logger logger, Level level) {
+ // Nothing to do.
+ }
+ }
+
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/MetricsConfiguration.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/MetricsConfiguration.java
new file mode 100644
index 0000000000..27b617a190
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/MetricsConfiguration.java
@@ -0,0 +1,113 @@
+package com.car.app.config;
+
+import io.github.jhipster.config.JHipsterProperties;
+import io.github.jhipster.config.metrics.SpectatorLogMetricWriter;
+
+import com.netflix.spectator.api.Registry;
+import org.springframework.boot.actuate.autoconfigure.ExportMetricReader;
+import org.springframework.boot.actuate.autoconfigure.ExportMetricWriter;
+import org.springframework.boot.actuate.metrics.writer.MetricWriter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.cloud.netflix.metrics.spectator.SpectatorMetricReader;
+
+import com.codahale.metrics.JmxReporter;
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.Slf4jReporter;
+import com.codahale.metrics.health.HealthCheckRegistry;
+import com.codahale.metrics.jvm.*;
+import com.ryantenney.metrics.spring.config.annotation.EnableMetrics;
+import com.ryantenney.metrics.spring.config.annotation.MetricsConfigurerAdapter;
+import com.zaxxer.hikari.HikariDataSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.*;
+
+import javax.annotation.PostConstruct;
+import java.lang.management.ManagementFactory;
+import java.util.concurrent.TimeUnit;
+
+@Configuration
+@EnableMetrics(proxyTargetClass = true)
+public class MetricsConfiguration extends MetricsConfigurerAdapter {
+
+ private static final String PROP_METRIC_REG_JVM_MEMORY = "jvm.memory";
+ private static final String PROP_METRIC_REG_JVM_GARBAGE = "jvm.garbage";
+ private static final String PROP_METRIC_REG_JVM_THREADS = "jvm.threads";
+ private static final String PROP_METRIC_REG_JVM_FILES = "jvm.files";
+ private static final String PROP_METRIC_REG_JVM_BUFFERS = "jvm.buffers";
+ private final Logger log = LoggerFactory.getLogger(MetricsConfiguration.class);
+
+ private MetricRegistry metricRegistry = new MetricRegistry();
+
+ private HealthCheckRegistry healthCheckRegistry = new HealthCheckRegistry();
+
+ private final JHipsterProperties jHipsterProperties;
+
+ private HikariDataSource hikariDataSource;
+
+ public MetricsConfiguration(JHipsterProperties jHipsterProperties) {
+ this.jHipsterProperties = jHipsterProperties;
+ }
+
+ @Autowired(required = false)
+ public void setHikariDataSource(HikariDataSource hikariDataSource) {
+ this.hikariDataSource = hikariDataSource;
+ }
+
+ @Override
+ @Bean
+ public MetricRegistry getMetricRegistry() {
+ return metricRegistry;
+ }
+
+ @Override
+ @Bean
+ public HealthCheckRegistry getHealthCheckRegistry() {
+ return healthCheckRegistry;
+ }
+
+ @PostConstruct
+ public void init() {
+ log.debug("Registering JVM gauges");
+ metricRegistry.register(PROP_METRIC_REG_JVM_MEMORY, new MemoryUsageGaugeSet());
+ metricRegistry.register(PROP_METRIC_REG_JVM_GARBAGE, new GarbageCollectorMetricSet());
+ metricRegistry.register(PROP_METRIC_REG_JVM_THREADS, new ThreadStatesGaugeSet());
+ metricRegistry.register(PROP_METRIC_REG_JVM_FILES, new FileDescriptorRatioGauge());
+ metricRegistry.register(PROP_METRIC_REG_JVM_BUFFERS, new BufferPoolMetricSet(ManagementFactory.getPlatformMBeanServer()));
+ if (hikariDataSource != null) {
+ log.debug("Monitoring the datasource");
+ hikariDataSource.setMetricRegistry(metricRegistry);
+ }
+ if (jHipsterProperties.getMetrics().getJmx().isEnabled()) {
+ log.debug("Initializing Metrics JMX reporting");
+ JmxReporter jmxReporter = JmxReporter.forRegistry(metricRegistry).build();
+ jmxReporter.start();
+ }
+ if (jHipsterProperties.getMetrics().getLogs().isEnabled()) {
+ log.info("Initializing Metrics Log reporting");
+ final Slf4jReporter reporter = Slf4jReporter.forRegistry(metricRegistry)
+ .outputTo(LoggerFactory.getLogger("metrics"))
+ .convertRatesTo(TimeUnit.SECONDS)
+ .convertDurationsTo(TimeUnit.MILLISECONDS)
+ .build();
+ reporter.start(jHipsterProperties.getMetrics().getLogs().getReportFrequency(), TimeUnit.SECONDS);
+ }
+ }
+
+ /* Spectator metrics log reporting */
+ @Bean
+ @ConditionalOnProperty("jhipster.logging.spectator-metrics.enabled")
+ @ExportMetricReader
+ public SpectatorMetricReader SpectatorMetricReader(Registry registry) {
+ log.info("Initializing Spectator Metrics Log reporting");
+ return new SpectatorMetricReader(registry);
+ }
+
+ @Bean
+ @ConditionalOnProperty("jhipster.logging.spectator-metrics.enabled")
+ @ExportMetricWriter
+ MetricWriter metricWriter() {
+ return new SpectatorLogMetricWriter();
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/MicroserviceSecurityConfiguration.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/MicroserviceSecurityConfiguration.java
new file mode 100644
index 0000000000..3e7b125ad6
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/MicroserviceSecurityConfiguration.java
@@ -0,0 +1,71 @@
+package com.car.app.config;
+
+import com.car.app.security.AuthoritiesConstants;
+import com.car.app.security.jwt.JWTConfigurer;
+import com.car.app.security.jwt.TokenProvider;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.data.repository.query.SecurityEvaluationContextExtension;
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
+public class MicroserviceSecurityConfiguration extends WebSecurityConfigurerAdapter {
+
+ private final TokenProvider tokenProvider;
+
+ public MicroserviceSecurityConfiguration(TokenProvider tokenProvider) {
+ this.tokenProvider = tokenProvider;
+ }
+
+ @Override
+ public void configure(WebSecurity web) throws Exception {
+ web.ignoring()
+ .antMatchers(HttpMethod.OPTIONS, "/**")
+ .antMatchers("/app/**/*.{js,html}")
+ .antMatchers("/bower_components/**")
+ .antMatchers("/i18n/**")
+ .antMatchers("/content/**")
+ .antMatchers("/swagger-ui/index.html")
+ .antMatchers("/test/**")
+ .antMatchers("/h2-console/**");
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http
+ .csrf()
+ .disable()
+ .headers()
+ .frameOptions()
+ .disable()
+ .and()
+ .sessionManagement()
+ .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ .and()
+ .authorizeRequests()
+ .antMatchers("/api/**").authenticated()
+ .antMatchers("/management/health").permitAll()
+ .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
+ .antMatchers("/swagger-resources/configuration/ui").permitAll()
+ .and()
+ .apply(securityConfigurerAdapter());
+ }
+
+ private JWTConfigurer securityConfigurerAdapter() {
+ return new JWTConfigurer(tokenProvider);
+ }
+
+ @Bean
+ public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
+ return new SecurityEvaluationContextExtension();
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/ThymeleafConfiguration.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/ThymeleafConfiguration.java
new file mode 100644
index 0000000000..d84ca403d2
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/ThymeleafConfiguration.java
@@ -0,0 +1,26 @@
+package com.car.app.config;
+
+import org.apache.commons.lang3.CharEncoding;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.*;
+import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
+
+@Configuration
+public class ThymeleafConfiguration {
+
+ @SuppressWarnings("unused")
+ private final Logger log = LoggerFactory.getLogger(ThymeleafConfiguration.class);
+
+ @Bean
+ @Description("Thymeleaf template resolver serving HTML 5 emails")
+ public ClassLoaderTemplateResolver emailTemplateResolver() {
+ ClassLoaderTemplateResolver emailTemplateResolver = new ClassLoaderTemplateResolver();
+ emailTemplateResolver.setPrefix("mails/");
+ emailTemplateResolver.setSuffix(".html");
+ emailTemplateResolver.setTemplateMode("HTML5");
+ emailTemplateResolver.setCharacterEncoding(CharEncoding.UTF_8);
+ emailTemplateResolver.setOrder(1);
+ return emailTemplateResolver;
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/WebConfigurer.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/WebConfigurer.java
new file mode 100644
index 0000000000..c66579e940
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/WebConfigurer.java
@@ -0,0 +1,144 @@
+package com.car.app.config;
+
+import io.github.jhipster.config.JHipsterConstants;
+import io.github.jhipster.config.JHipsterProperties;
+
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.servlet.InstrumentedFilter;
+import com.codahale.metrics.servlets.MetricsServlet;
+import com.hazelcast.core.HazelcastInstance;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.embedded.*;
+import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory;
+import io.undertow.UndertowOptions;
+import org.springframework.boot.web.servlet.ServletContextInitializer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+import java.util.*;
+import javax.servlet.*;
+
+/**
+ * Configuration of web application with Servlet 3.0 APIs.
+ */
+@Configuration
+public class WebConfigurer implements ServletContextInitializer, EmbeddedServletContainerCustomizer {
+
+ private final Logger log = LoggerFactory.getLogger(WebConfigurer.class);
+
+ private final Environment env;
+
+ private final JHipsterProperties jHipsterProperties;
+
+ private final HazelcastInstance hazelcastInstance;
+
+ private MetricRegistry metricRegistry;
+
+ public WebConfigurer(Environment env, JHipsterProperties jHipsterProperties, HazelcastInstance hazelcastInstance) {
+
+ this.env = env;
+ this.jHipsterProperties = jHipsterProperties;
+ this.hazelcastInstance = hazelcastInstance;
+ }
+
+ @Override
+ public void onStartup(ServletContext servletContext) throws ServletException {
+ if (env.getActiveProfiles().length != 0) {
+ log.info("Web application configuration, using profiles: {}", (Object[]) env.getActiveProfiles());
+ }
+ EnumSet disps = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.ASYNC);
+ initMetrics(servletContext, disps);
+ if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
+ initH2Console(servletContext);
+ }
+ log.info("Web application fully configured");
+ }
+
+ /**
+ * Customize the Servlet engine: Mime types, the document root, the cache.
+ */
+ @Override
+ public void customize(ConfigurableEmbeddedServletContainer container) {
+ MimeMappings mappings = new MimeMappings(MimeMappings.DEFAULT);
+ // IE issue, see https://github.com/jhipster/generator-jhipster/pull/711
+ mappings.add("html", "text/html;charset=utf-8");
+ // CloudFoundry issue, see https://github.com/cloudfoundry/gorouter/issues/64
+ mappings.add("json", "text/html;charset=utf-8");
+ container.setMimeMappings(mappings);
+
+ /*
+ * Enable HTTP/2 for Undertow - https://twitter.com/ankinson/status/829256167700492288
+ * HTTP/2 requires HTTPS, so HTTP requests will fallback to HTTP/1.1.
+ * See the JHipsterProperties class and your application-*.yml configuration files
+ * for more information.
+ */
+ if (jHipsterProperties.getHttp().getVersion().equals(JHipsterProperties.Http.Version.V_2_0) &&
+ container instanceof UndertowEmbeddedServletContainerFactory) {
+
+ ((UndertowEmbeddedServletContainerFactory) container)
+ .addBuilderCustomizers(builder ->
+ builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true));
+ }
+ }
+
+ /**
+ * Initializes Metrics.
+ */
+ private void initMetrics(ServletContext servletContext, EnumSet disps) {
+ log.debug("Initializing Metrics registries");
+ servletContext.setAttribute(InstrumentedFilter.REGISTRY_ATTRIBUTE,
+ metricRegistry);
+ servletContext.setAttribute(MetricsServlet.METRICS_REGISTRY,
+ metricRegistry);
+
+ log.debug("Registering Metrics Filter");
+ FilterRegistration.Dynamic metricsFilter = servletContext.addFilter("webappMetricsFilter",
+ new InstrumentedFilter());
+
+ metricsFilter.addMappingForUrlPatterns(disps, true, "/*");
+ metricsFilter.setAsyncSupported(true);
+
+ log.debug("Registering Metrics Servlet");
+ ServletRegistration.Dynamic metricsAdminServlet =
+ servletContext.addServlet("metricsServlet", new MetricsServlet());
+
+ metricsAdminServlet.addMapping("/management/metrics/*");
+ metricsAdminServlet.setAsyncSupported(true);
+ metricsAdminServlet.setLoadOnStartup(2);
+ }
+
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ CorsConfiguration config = jHipsterProperties.getCors();
+ if (config.getAllowedOrigins() != null && !config.getAllowedOrigins().isEmpty()) {
+ log.debug("Registering CORS filter");
+ source.registerCorsConfiguration("/api/**", config);
+ source.registerCorsConfiguration("/v2/api-docs", config);
+ }
+ return new CorsFilter(source);
+ }
+
+ /**
+ * Initializes H2 console.
+ */
+ private void initH2Console(ServletContext servletContext) {
+ log.debug("Initialize H2 console");
+ ServletRegistration.Dynamic h2ConsoleServlet = servletContext.addServlet("H2Console", new org.h2.server.web.WebServlet());
+ h2ConsoleServlet.addMapping("/h2-console/*");
+ h2ConsoleServlet.setInitParameter("-properties", "src/main/resources/");
+ h2ConsoleServlet.setLoadOnStartup(1);
+ }
+
+ @Autowired(required = false)
+ public void setMetricRegistry(MetricRegistry metricRegistry) {
+ this.metricRegistry = metricRegistry;
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/audit/AuditEventConverter.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/audit/AuditEventConverter.java
new file mode 100644
index 0000000000..93680c0ef1
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/audit/AuditEventConverter.java
@@ -0,0 +1,91 @@
+package com.car.app.config.audit;
+
+import com.car.app.domain.PersistentAuditEvent;
+
+import org.springframework.boot.actuate.audit.AuditEvent;
+import org.springframework.security.web.authentication.WebAuthenticationDetails;
+import org.springframework.stereotype.Component;
+
+import java.time.Instant;
+import java.time.ZoneId;
+import java.util.*;
+
+@Component
+public class AuditEventConverter {
+
+ /**
+ * Convert a list of PersistentAuditEvent to a list of AuditEvent
+ *
+ * @param persistentAuditEvents the list to convert
+ * @return the converted list.
+ */
+ public List convertToAuditEvent(Iterable persistentAuditEvents) {
+ if (persistentAuditEvents == null) {
+ return Collections.emptyList();
+ }
+ List auditEvents = new ArrayList<>();
+ for (PersistentAuditEvent persistentAuditEvent : persistentAuditEvents) {
+ auditEvents.add(convertToAuditEvent(persistentAuditEvent));
+ }
+ return auditEvents;
+ }
+
+ /**
+ * Convert a PersistentAuditEvent to an AuditEvent
+ *
+ * @param persistentAuditEvent the event to convert
+ * @return the converted list.
+ */
+ public AuditEvent convertToAuditEvent(PersistentAuditEvent persistentAuditEvent) {
+ Instant instant = persistentAuditEvent.getAuditEventDate().atZone(ZoneId.systemDefault()).toInstant();
+ return new AuditEvent(Date.from(instant), persistentAuditEvent.getPrincipal(),
+ persistentAuditEvent.getAuditEventType(), convertDataToObjects(persistentAuditEvent.getData()));
+ }
+
+ /**
+ * Internal conversion. This is needed to support the current SpringBoot actuator AuditEventRepository interface
+ *
+ * @param data the data to convert
+ * @return a map of String, Object
+ */
+ public Map convertDataToObjects(Map data) {
+ Map results = new HashMap<>();
+
+ if (data != null) {
+ for (Map.Entry entry : data.entrySet()) {
+ results.put(entry.getKey(), entry.getValue());
+ }
+ }
+ return results;
+ }
+
+ /**
+ * Internal conversion. This method will allow to save additional data.
+ * By default, it will save the object as string
+ *
+ * @param data the data to convert
+ * @return a map of String, String
+ */
+ public Map convertDataToStrings(Map data) {
+ Map results = new HashMap<>();
+
+ if (data != null) {
+ for (Map.Entry entry : data.entrySet()) {
+ Object object = entry.getValue();
+
+ // Extract the data that will be saved.
+ if (object instanceof WebAuthenticationDetails) {
+ WebAuthenticationDetails authenticationDetails = (WebAuthenticationDetails) object;
+ results.put("remoteAddress", authenticationDetails.getRemoteAddress());
+ results.put("sessionId", authenticationDetails.getSessionId());
+ } else if (object != null) {
+ results.put(entry.getKey(), object.toString());
+ } else {
+ results.put(entry.getKey(), "null");
+ }
+ }
+ }
+
+ return results;
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/audit/package-info.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/audit/package-info.java
new file mode 100644
index 0000000000..0d1f9d950e
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/audit/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Audit specific code.
+ */
+package com.car.app.config.audit;
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/package-info.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/package-info.java
new file mode 100644
index 0000000000..1d4b771794
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/config/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Spring Framework configuration files.
+ */
+package com.car.app.config;
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/domain/AbstractAuditingEntity.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/domain/AbstractAuditingEntity.java
new file mode 100644
index 0000000000..ee265f27ae
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/domain/AbstractAuditingEntity.java
@@ -0,0 +1,80 @@
+package com.car.app.domain;
+
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import org.hibernate.envers.Audited;
+import org.springframework.data.annotation.CreatedBy;
+import org.springframework.data.annotation.CreatedDate;
+import org.springframework.data.annotation.LastModifiedBy;
+import org.springframework.data.annotation.LastModifiedDate;
+
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+import java.time.ZonedDateTime;
+import javax.persistence.Column;
+import javax.persistence.EntityListeners;
+import javax.persistence.MappedSuperclass;
+
+/**
+ * Base abstract class for entities which will hold definitions for created, last modified by and created,
+ * last modified by date.
+ */
+@MappedSuperclass
+@Audited
+@EntityListeners(AuditingEntityListener.class)
+public abstract class AbstractAuditingEntity implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @CreatedBy
+ @Column(name = "created_by", nullable = false, length = 50, updatable = false)
+ @JsonIgnore
+ private String createdBy;
+
+ @CreatedDate
+ @Column(name = "created_date", nullable = false)
+ @JsonIgnore
+ private ZonedDateTime createdDate = ZonedDateTime.now();
+
+ @LastModifiedBy
+ @Column(name = "last_modified_by", length = 50)
+ @JsonIgnore
+ private String lastModifiedBy;
+
+ @LastModifiedDate
+ @Column(name = "last_modified_date")
+ @JsonIgnore
+ private ZonedDateTime lastModifiedDate = ZonedDateTime.now();
+
+ public String getCreatedBy() {
+ return createdBy;
+ }
+
+ public void setCreatedBy(String createdBy) {
+ this.createdBy = createdBy;
+ }
+
+ public ZonedDateTime getCreatedDate() {
+ return createdDate;
+ }
+
+ public void setCreatedDate(ZonedDateTime createdDate) {
+ this.createdDate = createdDate;
+ }
+
+ public String getLastModifiedBy() {
+ return lastModifiedBy;
+ }
+
+ public void setLastModifiedBy(String lastModifiedBy) {
+ this.lastModifiedBy = lastModifiedBy;
+ }
+
+ public ZonedDateTime getLastModifiedDate() {
+ return lastModifiedDate;
+ }
+
+ public void setLastModifiedDate(ZonedDateTime lastModifiedDate) {
+ this.lastModifiedDate = lastModifiedDate;
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/domain/Car.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/domain/Car.java
new file mode 100644
index 0000000000..dad21815d3
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/domain/Car.java
@@ -0,0 +1,109 @@
+package com.car.app.domain;
+
+import org.hibernate.annotations.Cache;
+import org.hibernate.annotations.CacheConcurrencyStrategy;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * A Car.
+ */
+@Entity
+@Table(name = "car")
+@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
+public class Car implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(name = "make")
+ private String make;
+
+ @Column(name = "brand")
+ private String brand;
+
+ @Column(name = "price")
+ private Double price;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getMake() {
+ return make;
+ }
+
+ public Car make(String make) {
+ this.make = make;
+ return this;
+ }
+
+ public void setMake(String make) {
+ this.make = make;
+ }
+
+ public String getBrand() {
+ return brand;
+ }
+
+ public Car brand(String brand) {
+ this.brand = brand;
+ return this;
+ }
+
+ public void setBrand(String brand) {
+ this.brand = brand;
+ }
+
+ public Double getPrice() {
+ return price;
+ }
+
+ public Car price(Double price) {
+ this.price = price;
+ return this;
+ }
+
+ public void setPrice(Double price) {
+ this.price = price;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Car car = (Car) o;
+ if (car.id == null || id == null) {
+ return false;
+ }
+ return Objects.equals(id, car.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(id);
+ }
+
+ @Override
+ public String toString() {
+ return "Car{" +
+ "id=" + id +
+ ", make='" + make + "'" +
+ ", brand='" + brand + "'" +
+ ", price='" + price + "'" +
+ '}';
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/domain/PersistentAuditEvent.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/domain/PersistentAuditEvent.java
new file mode 100644
index 0000000000..d3d8eb86dc
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/domain/PersistentAuditEvent.java
@@ -0,0 +1,78 @@
+package com.car.app.domain;
+
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import javax.persistence.*;
+import javax.validation.constraints.NotNull;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Persist AuditEvent managed by the Spring Boot actuator
+ * @see org.springframework.boot.actuate.audit.AuditEvent
+ */
+@Entity
+@Table(name = "jhi_persistent_audit_event")
+public class PersistentAuditEvent implements Serializable {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "event_id")
+ private Long id;
+
+ @NotNull
+ @Column(nullable = false)
+ private String principal;
+
+ @Column(name = "event_date")
+ private LocalDateTime auditEventDate;
+ @Column(name = "event_type")
+ private String auditEventType;
+
+ @ElementCollection
+ @MapKeyColumn(name = "name")
+ @Column(name = "value")
+ @CollectionTable(name = "jhi_persistent_audit_evt_data", joinColumns=@JoinColumn(name="event_id"))
+ private Map data = new HashMap<>();
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getPrincipal() {
+ return principal;
+ }
+
+ public void setPrincipal(String principal) {
+ this.principal = principal;
+ }
+
+ public LocalDateTime getAuditEventDate() {
+ return auditEventDate;
+ }
+
+ public void setAuditEventDate(LocalDateTime auditEventDate) {
+ this.auditEventDate = auditEventDate;
+ }
+
+ public String getAuditEventType() {
+ return auditEventType;
+ }
+
+ public void setAuditEventType(String auditEventType) {
+ this.auditEventType = auditEventType;
+ }
+
+ public Map getData() {
+ return data;
+ }
+
+ public void setData(Map data) {
+ this.data = data;
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/domain/package-info.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/domain/package-info.java
new file mode 100644
index 0000000000..99ddca6167
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/domain/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * JPA domain objects.
+ */
+package com.car.app.domain;
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/repository/CarRepository.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/repository/CarRepository.java
new file mode 100644
index 0000000000..6aea5a0be8
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/repository/CarRepository.java
@@ -0,0 +1,15 @@
+package com.car.app.repository;
+
+import com.car.app.domain.Car;
+
+import org.springframework.data.jpa.repository.*;
+
+import java.util.List;
+
+/**
+ * Spring Data JPA repository for the Car entity.
+ */
+@SuppressWarnings("unused")
+public interface CarRepository extends JpaRepository {
+
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/repository/package-info.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/repository/package-info.java
new file mode 100644
index 0000000000..55d8e8e5e5
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/repository/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Spring Data JPA repositories.
+ */
+package com.car.app.repository;
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/security/AuthoritiesConstants.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/security/AuthoritiesConstants.java
new file mode 100644
index 0000000000..ca36d02c5c
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/security/AuthoritiesConstants.java
@@ -0,0 +1,16 @@
+package com.car.app.security;
+
+/**
+ * Constants for Spring Security authorities.
+ */
+public final class AuthoritiesConstants {
+
+ public static final String ADMIN = "ROLE_ADMIN";
+
+ public static final String USER = "ROLE_USER";
+
+ public static final String ANONYMOUS = "ROLE_ANONYMOUS";
+
+ private AuthoritiesConstants() {
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/security/SecurityUtils.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/security/SecurityUtils.java
new file mode 100644
index 0000000000..dc399d4220
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/security/SecurityUtils.java
@@ -0,0 +1,68 @@
+package com.car.app.security;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+
+/**
+ * Utility class for Spring Security.
+ */
+public final class SecurityUtils {
+
+ private SecurityUtils() {
+ }
+
+ /**
+ * Get the login of the current user.
+ *
+ * @return the login of the current user
+ */
+ public static String getCurrentUserLogin() {
+ SecurityContext securityContext = SecurityContextHolder.getContext();
+ Authentication authentication = securityContext.getAuthentication();
+ String userName = null;
+ if (authentication != null) {
+ if (authentication.getPrincipal() instanceof UserDetails) {
+ UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal();
+ userName = springSecurityUser.getUsername();
+ } else if (authentication.getPrincipal() instanceof String) {
+ userName = (String) authentication.getPrincipal();
+ }
+ }
+ return userName;
+ }
+
+ /**
+ * Check if a user is authenticated.
+ *
+ * @return true if the user is authenticated, false otherwise
+ */
+ public static boolean isAuthenticated() {
+ SecurityContext securityContext = SecurityContextHolder.getContext();
+ Authentication authentication = securityContext.getAuthentication();
+ if (authentication != null) {
+ return authentication.getAuthorities().stream()
+ .noneMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(AuthoritiesConstants.ANONYMOUS));
+ }
+ return false;
+ }
+
+ /**
+ * If the current user has a specific authority (security role).
+ *
+ *
The name of this method comes from the isUserInRole() method in the Servlet API
+ *
+ * @param authority the authority to check
+ * @return true if the current user has the authority, false otherwise
+ */
+ public static boolean isCurrentUserInRole(String authority) {
+ SecurityContext securityContext = SecurityContextHolder.getContext();
+ Authentication authentication = securityContext.getAuthentication();
+ if (authentication != null) {
+ return authentication.getAuthorities().stream()
+ .anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(authority));
+ }
+ return false;
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/security/SpringSecurityAuditorAware.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/security/SpringSecurityAuditorAware.java
new file mode 100644
index 0000000000..a99d9e5e88
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/security/SpringSecurityAuditorAware.java
@@ -0,0 +1,19 @@
+package com.car.app.security;
+
+import com.car.app.config.Constants;
+
+import org.springframework.data.domain.AuditorAware;
+import org.springframework.stereotype.Component;
+
+/**
+ * Implementation of AuditorAware based on Spring Security.
+ */
+@Component
+public class SpringSecurityAuditorAware implements AuditorAware {
+
+ @Override
+ public String getCurrentAuditor() {
+ String userName = SecurityUtils.getCurrentUserLogin();
+ return userName != null ? userName : Constants.SYSTEM_ACCOUNT;
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/security/jwt/JWTConfigurer.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/security/jwt/JWTConfigurer.java
new file mode 100644
index 0000000000..957bae3f1e
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/security/jwt/JWTConfigurer.java
@@ -0,0 +1,23 @@
+package com.car.app.security.jwt;
+
+import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.web.DefaultSecurityFilterChain;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+public class JWTConfigurer extends SecurityConfigurerAdapter {
+
+ public static final String AUTHORIZATION_HEADER = "Authorization";
+
+ private TokenProvider tokenProvider;
+
+ public JWTConfigurer(TokenProvider tokenProvider) {
+ this.tokenProvider = tokenProvider;
+ }
+
+ @Override
+ public void configure(HttpSecurity http) throws Exception {
+ JWTFilter customFilter = new JWTFilter(tokenProvider);
+ http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/security/jwt/JWTFilter.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/security/jwt/JWTFilter.java
new file mode 100644
index 0000000000..2785714cc2
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/security/jwt/JWTFilter.java
@@ -0,0 +1,58 @@
+package com.car.app.security.jwt;
+
+import java.io.IOException;
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.util.StringUtils;
+import org.springframework.web.filter.GenericFilterBean;
+
+import io.jsonwebtoken.ExpiredJwtException;
+
+/**
+ * Filters incoming requests and installs a Spring Security principal if a header corresponding to a valid user is
+ * found.
+ */
+public class JWTFilter extends GenericFilterBean {
+
+ private final Logger log = LoggerFactory.getLogger(JWTFilter.class);
+
+ private TokenProvider tokenProvider;
+
+ public JWTFilter(TokenProvider tokenProvider) {
+ this.tokenProvider = tokenProvider;
+ }
+
+ @Override
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
+ throws IOException, ServletException {
+ try {
+ HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
+ String jwt = resolveToken(httpServletRequest);
+ if (StringUtils.hasText(jwt) && this.tokenProvider.validateToken(jwt)) {
+ Authentication authentication = this.tokenProvider.getAuthentication(jwt);
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ }
+ filterChain.doFilter(servletRequest, servletResponse);
+ } catch (ExpiredJwtException eje) {
+ log.info("Security exception for user {} - {}",
+ eje.getClaims().getSubject(), eje.getMessage());
+
+ log.trace("Security exception trace: {}", eje);
+ ((HttpServletResponse) servletResponse).setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ }
+ }
+
+ private String resolveToken(HttpServletRequest request){
+ String bearerToken = request.getHeader(JWTConfigurer.AUTHORIZATION_HEADER);
+ if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
+ return bearerToken.substring(7, bearerToken.length());
+ }
+ return null;
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/security/jwt/TokenProvider.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/security/jwt/TokenProvider.java
new file mode 100644
index 0000000000..3908bfa8f3
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/security/jwt/TokenProvider.java
@@ -0,0 +1,109 @@
+package com.car.app.security.jwt;
+
+import io.github.jhipster.config.JHipsterProperties;
+
+import java.util.*;
+import java.util.stream.Collectors;
+import javax.annotation.PostConstruct;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.stereotype.Component;
+
+import io.jsonwebtoken.*;
+
+@Component
+public class TokenProvider {
+
+ private final Logger log = LoggerFactory.getLogger(TokenProvider.class);
+
+ private static final String AUTHORITIES_KEY = "auth";
+
+ private String secretKey;
+
+ private long tokenValidityInMilliseconds;
+
+ private long tokenValidityInMillisecondsForRememberMe;
+
+ private final JHipsterProperties jHipsterProperties;
+
+ public TokenProvider(JHipsterProperties jHipsterProperties) {
+ this.jHipsterProperties = jHipsterProperties;
+ }
+
+ @PostConstruct
+ public void init() {
+ this.secretKey =
+ jHipsterProperties.getSecurity().getAuthentication().getJwt().getSecret();
+
+ this.tokenValidityInMilliseconds =
+ 1000 * jHipsterProperties.getSecurity().getAuthentication().getJwt().getTokenValidityInSeconds();
+ this.tokenValidityInMillisecondsForRememberMe =
+ 1000 * jHipsterProperties.getSecurity().getAuthentication().getJwt().getTokenValidityInSecondsForRememberMe();
+ }
+
+ public String createToken(Authentication authentication, Boolean rememberMe) {
+ String authorities = authentication.getAuthorities().stream()
+ .map(GrantedAuthority::getAuthority)
+ .collect(Collectors.joining(","));
+
+ long now = (new Date()).getTime();
+ Date validity;
+ if (rememberMe) {
+ validity = new Date(now + this.tokenValidityInMillisecondsForRememberMe);
+ } else {
+ validity = new Date(now + this.tokenValidityInMilliseconds);
+ }
+
+ return Jwts.builder()
+ .setSubject(authentication.getName())
+ .claim(AUTHORITIES_KEY, authorities)
+ .signWith(SignatureAlgorithm.HS512, secretKey)
+ .setExpiration(validity)
+ .compact();
+ }
+
+ public Authentication getAuthentication(String token) {
+ Claims claims = Jwts.parser()
+ .setSigningKey(secretKey)
+ .parseClaimsJws(token)
+ .getBody();
+
+ Collection extends GrantedAuthority> authorities =
+ Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(","))
+ .map(SimpleGrantedAuthority::new)
+ .collect(Collectors.toList());
+
+ User principal = new User(claims.getSubject(), "", authorities);
+
+ return new UsernamePasswordAuthenticationToken(principal, "", authorities);
+ }
+
+ public boolean validateToken(String authToken) {
+ try {
+ Jwts.parser().setSigningKey(secretKey).parseClaimsJws(authToken);
+ return true;
+ } catch (SignatureException e) {
+ log.info("Invalid JWT signature.");
+ log.trace("Invalid JWT signature trace: {}", e);
+ } catch (MalformedJwtException e) {
+ log.info("Invalid JWT token.");
+ log.trace("Invalid JWT token trace: {}", e);
+ } catch (ExpiredJwtException e) {
+ log.info("Expired JWT token.");
+ log.trace("Expired JWT token trace: {}", e);
+ } catch (UnsupportedJwtException e) {
+ log.info("Unsupported JWT token.");
+ log.trace("Unsupported JWT token trace: {}", e);
+ } catch (IllegalArgumentException e) {
+ log.info("JWT token compact of handler are invalid.");
+ log.trace("JWT token compact of handler are invalid trace: {}", e);
+ }
+ return false;
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/service/package-info.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/service/package-info.java
new file mode 100644
index 0000000000..2d3df85add
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/service/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Service layer beans.
+ */
+package com.car.app.service;
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/CarResource.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/CarResource.java
new file mode 100644
index 0000000000..1ac6caf83c
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/CarResource.java
@@ -0,0 +1,128 @@
+package com.car.app.web.rest;
+
+import com.codahale.metrics.annotation.Timed;
+import com.car.app.domain.Car;
+
+import com.car.app.repository.CarRepository;
+import com.car.app.web.rest.util.HeaderUtil;
+import com.car.app.web.rest.util.PaginationUtil;
+import io.swagger.annotations.ApiParam;
+import io.github.jhipster.web.util.ResponseUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * REST controller for managing Car.
+ */
+@RestController
+@RequestMapping("/api")
+public class CarResource {
+
+ private final Logger log = LoggerFactory.getLogger(CarResource.class);
+
+ private static final String ENTITY_NAME = "car";
+
+ private final CarRepository carRepository;
+
+ public CarResource(CarRepository carRepository) {
+ this.carRepository = carRepository;
+ }
+
+ /**
+ * POST /cars : Create a new car.
+ *
+ * @param car the car to create
+ * @return the ResponseEntity with status 201 (Created) and with body the new car, or with status 400 (Bad Request) if the car has already an ID
+ * @throws URISyntaxException if the Location URI syntax is incorrect
+ */
+ @PostMapping("/cars")
+ @Timed
+ public ResponseEntity createCar(@RequestBody Car car) throws URISyntaxException {
+ log.debug("REST request to save Car : {}", car);
+ if (car.getId() != null) {
+ return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert(ENTITY_NAME, "idexists", "A new car cannot already have an ID")).body(null);
+ }
+ Car result = carRepository.save(car);
+ return ResponseEntity.created(new URI("/api/cars/" + result.getId()))
+ .headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString()))
+ .body(result);
+ }
+
+ /**
+ * PUT /cars : Updates an existing car.
+ *
+ * @param car the car to update
+ * @return the ResponseEntity with status 200 (OK) and with body the updated car,
+ * or with status 400 (Bad Request) if the car is not valid,
+ * or with status 500 (Internal Server Error) if the car couldnt be updated
+ * @throws URISyntaxException if the Location URI syntax is incorrect
+ */
+ @PutMapping("/cars")
+ @Timed
+ public ResponseEntity updateCar(@RequestBody Car car) throws URISyntaxException {
+ log.debug("REST request to update Car : {}", car);
+ if (car.getId() == null) {
+ return createCar(car);
+ }
+ Car result = carRepository.save(car);
+ return ResponseEntity.ok()
+ .headers(HeaderUtil.createEntityUpdateAlert(ENTITY_NAME, car.getId().toString()))
+ .body(result);
+ }
+
+ /**
+ * GET /cars : get all the cars.
+ *
+ * @param pageable the pagination information
+ * @return the ResponseEntity with status 200 (OK) and the list of cars in body
+ * @throws URISyntaxException if there is an error to generate the pagination HTTP headers
+ */
+ @GetMapping("/cars")
+ @Timed
+ public ResponseEntity> getAllCars(@ApiParam Pageable pageable) {
+ log.debug("REST request to get a page of Cars");
+ Page page = carRepository.findAll(pageable);
+ HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/cars");
+ return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
+ }
+
+ /**
+ * GET /cars/:id : get the "id" car.
+ *
+ * @param id the id of the car to retrieve
+ * @return the ResponseEntity with status 200 (OK) and with body the car, or with status 404 (Not Found)
+ */
+ @GetMapping("/cars/{id}")
+ @Timed
+ public ResponseEntity getCar(@PathVariable Long id) {
+ log.debug("REST request to get Car : {}", id);
+ Car car = carRepository.findOne(id);
+ return ResponseUtil.wrapOrNotFound(Optional.ofNullable(car));
+ }
+
+ /**
+ * DELETE /cars/:id : delete the "id" car.
+ *
+ * @param id the id of the car to delete
+ * @return the ResponseEntity with status 200 (OK)
+ */
+ @DeleteMapping("/cars/{id}")
+ @Timed
+ public ResponseEntity deleteCar(@PathVariable Long id) {
+ log.debug("REST request to delete Car : {}", id);
+ carRepository.delete(id);
+ return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert(ENTITY_NAME, id.toString())).build();
+ }
+
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/LogsResource.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/LogsResource.java
new file mode 100644
index 0000000000..b9054ac4f7
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/LogsResource.java
@@ -0,0 +1,39 @@
+package com.car.app.web.rest;
+
+import com.car.app.web.rest.vm.LoggerVM;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.LoggerContext;
+import com.codahale.metrics.annotation.Timed;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Controller for view and managing Log Level at runtime.
+ */
+@RestController
+@RequestMapping("/management")
+public class LogsResource {
+
+ @GetMapping("/logs")
+ @Timed
+ public List getList() {
+ LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
+ return context.getLoggerList()
+ .stream()
+ .map(LoggerVM::new)
+ .collect(Collectors.toList());
+ }
+
+ @PutMapping("/logs")
+ @ResponseStatus(HttpStatus.NO_CONTENT)
+ @Timed
+ public void changeLevel(@RequestBody LoggerVM jsonLogger) {
+ LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
+ context.getLogger(jsonLogger.getName()).setLevel(Level.valueOf(jsonLogger.getLevel()));
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/ProfileInfoResource.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/ProfileInfoResource.java
new file mode 100644
index 0000000000..ad2262f458
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/ProfileInfoResource.java
@@ -0,0 +1,69 @@
+package com.car.app.web.rest;
+
+import com.car.app.config.DefaultProfileUtil;
+
+import io.github.jhipster.config.JHipsterProperties;
+
+import org.springframework.core.env.Environment;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Resource to return information about the currently running Spring profiles.
+ */
+@RestController
+@RequestMapping("/api")
+public class ProfileInfoResource {
+
+ private final Environment env;
+
+ private final JHipsterProperties jHipsterProperties;
+
+ public ProfileInfoResource(Environment env, JHipsterProperties jHipsterProperties) {
+ this.env = env;
+ this.jHipsterProperties = jHipsterProperties;
+ }
+
+ @GetMapping("/profile-info")
+ public ProfileInfoVM getActiveProfiles() {
+ String[] activeProfiles = DefaultProfileUtil.getActiveProfiles(env);
+ return new ProfileInfoVM(activeProfiles, getRibbonEnv(activeProfiles));
+ }
+
+ private String getRibbonEnv(String[] activeProfiles) {
+ String[] displayOnActiveProfiles = jHipsterProperties.getRibbon().getDisplayOnActiveProfiles();
+ if (displayOnActiveProfiles == null) {
+ return null;
+ }
+ List ribbonProfiles = new ArrayList<>(Arrays.asList(displayOnActiveProfiles));
+ List springBootProfiles = Arrays.asList(activeProfiles);
+ ribbonProfiles.retainAll(springBootProfiles);
+ if (!ribbonProfiles.isEmpty()) {
+ return ribbonProfiles.get(0);
+ }
+ return null;
+ }
+
+ class ProfileInfoVM {
+
+ private String[] activeProfiles;
+
+ private String ribbonEnv;
+
+ ProfileInfoVM(String[] activeProfiles, String ribbonEnv) {
+ this.activeProfiles = activeProfiles;
+ this.ribbonEnv = ribbonEnv;
+ }
+
+ public String[] getActiveProfiles() {
+ return activeProfiles;
+ }
+
+ public String getRibbonEnv() {
+ return ribbonEnv;
+ }
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/errors/CustomParameterizedException.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/errors/CustomParameterizedException.java
new file mode 100644
index 0000000000..0bf41f2fdb
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/errors/CustomParameterizedException.java
@@ -0,0 +1,34 @@
+package com.car.app.web.rest.errors;
+
+/**
+ * Custom, parameterized exception, which can be translated on the client side.
+ * For example:
+ *
+ *
+ * throw new CustomParameterizedException("myCustomError", "hello", "world");
+ *
+ *
+ * Can be translated with:
+ *
+ *
+ * "error.myCustomError" : "The server says {{params[0]}} to {{params[1]}}"
+ *
+ */
+public class CustomParameterizedException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String message;
+ private final String[] params;
+
+ public CustomParameterizedException(String message, String... params) {
+ super(message);
+ this.message = message;
+ this.params = params;
+ }
+
+ public ParameterizedErrorVM getErrorVM() {
+ return new ParameterizedErrorVM(message, params);
+ }
+
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/errors/ErrorConstants.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/errors/ErrorConstants.java
new file mode 100644
index 0000000000..f6db48f223
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/errors/ErrorConstants.java
@@ -0,0 +1,14 @@
+package com.car.app.web.rest.errors;
+
+public final class ErrorConstants {
+
+ public static final String ERR_CONCURRENCY_FAILURE = "error.concurrencyFailure";
+ public static final String ERR_ACCESS_DENIED = "error.accessDenied";
+ public static final String ERR_VALIDATION = "error.validation";
+ public static final String ERR_METHOD_NOT_SUPPORTED = "error.methodNotSupported";
+ public static final String ERR_INTERNAL_SERVER_ERROR = "error.internalServerError";
+
+ private ErrorConstants() {
+ }
+
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/errors/ErrorVM.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/errors/ErrorVM.java
new file mode 100644
index 0000000000..69d00c00d5
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/errors/ErrorVM.java
@@ -0,0 +1,52 @@
+package com.car.app.web.rest.errors;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * View Model for transferring error message with a list of field errors.
+ */
+public class ErrorVM implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String message;
+ private final String description;
+
+ private List fieldErrors;
+
+ public ErrorVM(String message) {
+ this(message, null);
+ }
+
+ public ErrorVM(String message, String description) {
+ this.message = message;
+ this.description = description;
+ }
+
+ public ErrorVM(String message, String description, List fieldErrors) {
+ this.message = message;
+ this.description = description;
+ this.fieldErrors = fieldErrors;
+ }
+
+ public void add(String objectName, String field, String message) {
+ if (fieldErrors == null) {
+ fieldErrors = new ArrayList<>();
+ }
+ fieldErrors.add(new FieldErrorVM(objectName, field, message));
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public List getFieldErrors() {
+ return fieldErrors;
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/errors/ExceptionTranslator.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/errors/ExceptionTranslator.java
new file mode 100644
index 0000000000..6282b816e1
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/errors/ExceptionTranslator.java
@@ -0,0 +1,85 @@
+package com.car.app.web.rest.errors;
+
+import java.util.List;
+
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.dao.ConcurrencyFailureException;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.ResponseEntity.BodyBuilder;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.FieldError;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * Controller advice to translate the server side exceptions to client-friendly json structures.
+ */
+@ControllerAdvice
+public class ExceptionTranslator {
+
+ @ExceptionHandler(ConcurrencyFailureException.class)
+ @ResponseStatus(HttpStatus.CONFLICT)
+ @ResponseBody
+ public ErrorVM processConcurrencyError(ConcurrencyFailureException ex) {
+ return new ErrorVM(ErrorConstants.ERR_CONCURRENCY_FAILURE);
+ }
+
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ResponseBody
+ public ErrorVM processValidationError(MethodArgumentNotValidException ex) {
+ BindingResult result = ex.getBindingResult();
+ List fieldErrors = result.getFieldErrors();
+
+ return processFieldErrors(fieldErrors);
+ }
+
+ @ExceptionHandler(CustomParameterizedException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ResponseBody
+ public ParameterizedErrorVM processParameterizedValidationError(CustomParameterizedException ex) {
+ return ex.getErrorVM();
+ }
+
+ @ExceptionHandler(AccessDeniedException.class)
+ @ResponseStatus(HttpStatus.FORBIDDEN)
+ @ResponseBody
+ public ErrorVM processAccessDeniedException(AccessDeniedException e) {
+ return new ErrorVM(ErrorConstants.ERR_ACCESS_DENIED, e.getMessage());
+ }
+
+ private ErrorVM processFieldErrors(List fieldErrors) {
+ ErrorVM dto = new ErrorVM(ErrorConstants.ERR_VALIDATION);
+
+ for (FieldError fieldError : fieldErrors) {
+ dto.add(fieldError.getObjectName(), fieldError.getField(), fieldError.getCode());
+ }
+
+ return dto;
+ }
+
+ @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
+ @ResponseBody
+ @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
+ public ErrorVM processMethodNotSupportedException(HttpRequestMethodNotSupportedException exception) {
+ return new ErrorVM(ErrorConstants.ERR_METHOD_NOT_SUPPORTED, exception.getMessage());
+ }
+
+ @ExceptionHandler(Exception.class)
+ public ResponseEntity processRuntimeException(Exception ex) {
+ BodyBuilder builder;
+ ErrorVM errorVM;
+ ResponseStatus responseStatus = AnnotationUtils.findAnnotation(ex.getClass(), ResponseStatus.class);
+ if (responseStatus != null) {
+ builder = ResponseEntity.status(responseStatus.value());
+ errorVM = new ErrorVM("error." + responseStatus.value().value(), responseStatus.reason());
+ } else {
+ builder = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR);
+ errorVM = new ErrorVM(ErrorConstants.ERR_INTERNAL_SERVER_ERROR, "Internal server error");
+ }
+ return builder.body(errorVM);
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/errors/FieldErrorVM.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/errors/FieldErrorVM.java
new file mode 100644
index 0000000000..cdb2fc07e5
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/errors/FieldErrorVM.java
@@ -0,0 +1,33 @@
+package com.car.app.web.rest.errors;
+
+import java.io.Serializable;
+
+public class FieldErrorVM implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String objectName;
+
+ private final String field;
+
+ private final String message;
+
+ public FieldErrorVM(String dto, String field, String message) {
+ this.objectName = dto;
+ this.field = field;
+ this.message = message;
+ }
+
+ public String getObjectName() {
+ return objectName;
+ }
+
+ public String getField() {
+ return field;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/errors/ParameterizedErrorVM.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/errors/ParameterizedErrorVM.java
new file mode 100644
index 0000000000..b0c40c9cbb
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/errors/ParameterizedErrorVM.java
@@ -0,0 +1,27 @@
+package com.car.app.web.rest.errors;
+
+import java.io.Serializable;
+
+/**
+ * View Model for sending a parameterized error message.
+ */
+public class ParameterizedErrorVM implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ private final String message;
+ private final String[] params;
+
+ public ParameterizedErrorVM(String message, String... params) {
+ this.message = message;
+ this.params = params;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public String[] getParams() {
+ return params;
+ }
+
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/package-info.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/package-info.java
new file mode 100644
index 0000000000..fb696c0d89
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Spring MVC REST controllers.
+ */
+package com.car.app.web.rest;
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/util/HeaderUtil.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/util/HeaderUtil.java
new file mode 100644
index 0000000000..f6f9c1abb3
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/util/HeaderUtil.java
@@ -0,0 +1,43 @@
+package com.car.app.web.rest.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpHeaders;
+
+/**
+ * Utility class for HTTP headers creation.
+ */
+public final class HeaderUtil {
+
+ private static final Logger log = LoggerFactory.getLogger(HeaderUtil.class);
+
+ private HeaderUtil() {
+ }
+
+ public static HttpHeaders createAlert(String message, String param) {
+ HttpHeaders headers = new HttpHeaders();
+ headers.add("X-carappApp-alert", message);
+ headers.add("X-carappApp-params", param);
+ return headers;
+ }
+
+ public static HttpHeaders createEntityCreationAlert(String entityName, String param) {
+ return createAlert("A new " + entityName + " is created with identifier " + param, param);
+ }
+
+ public static HttpHeaders createEntityUpdateAlert(String entityName, String param) {
+ return createAlert("A " + entityName + " is updated with identifier " + param, param);
+ }
+
+ public static HttpHeaders createEntityDeletionAlert(String entityName, String param) {
+ return createAlert("A " + entityName + " is deleted with identifier " + param, param);
+ }
+
+ public static HttpHeaders createFailureAlert(String entityName, String errorKey, String defaultMessage) {
+ log.error("Entity creation failed, {}", defaultMessage);
+ HttpHeaders headers = new HttpHeaders();
+ headers.add("X-carappApp-error", defaultMessage);
+ headers.add("X-carappApp-params", entityName);
+ return headers;
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/util/PaginationUtil.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/util/PaginationUtil.java
new file mode 100644
index 0000000000..9ba36f7a44
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/util/PaginationUtil.java
@@ -0,0 +1,47 @@
+package com.car.app.web.rest.util;
+
+import org.springframework.data.domain.Page;
+import org.springframework.http.HttpHeaders;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import java.net.URISyntaxException;
+
+/**
+ * Utility class for handling pagination.
+ *
+ *
+ * Pagination uses the same principles as the Github API,
+ * and follow RFC 5988 (Link header).
+ */
+public final class PaginationUtil {
+
+ private PaginationUtil() {
+ }
+
+ public static HttpHeaders generatePaginationHttpHeaders(Page page, String baseUrl) {
+
+ HttpHeaders headers = new HttpHeaders();
+ headers.add("X-Total-Count", "" + Long.toString(page.getTotalElements()));
+ String link = "";
+ if ((page.getNumber() + 1) < page.getTotalPages()) {
+ link = "<" + generateUri(baseUrl, page.getNumber() + 1, page.getSize()) + ">; rel=\"next\",";
+ }
+ // prev link
+ if ((page.getNumber()) > 0) {
+ link += "<" + generateUri(baseUrl, page.getNumber() - 1, page.getSize()) + ">; rel=\"prev\",";
+ }
+ // last and first link
+ int lastPage = 0;
+ if (page.getTotalPages() > 0) {
+ lastPage = page.getTotalPages() - 1;
+ }
+ link += "<" + generateUri(baseUrl, lastPage, page.getSize()) + ">; rel=\"last\",";
+ link += "<" + generateUri(baseUrl, 0, page.getSize()) + ">; rel=\"first\"";
+ headers.add(HttpHeaders.LINK, link);
+ return headers;
+ }
+
+ private static String generateUri(String baseUrl, int page, int size) {
+ return UriComponentsBuilder.fromUriString(baseUrl).queryParam("page", page).queryParam("size", size).toUriString();
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/vm/LoggerVM.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/vm/LoggerVM.java
new file mode 100644
index 0000000000..ff76466df7
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/vm/LoggerVM.java
@@ -0,0 +1,48 @@
+package com.car.app.web.rest.vm;
+
+import ch.qos.logback.classic.Logger;
+import com.fasterxml.jackson.annotation.JsonCreator;
+
+/**
+ * View Model object for storing a Logback logger.
+ */
+public class LoggerVM {
+
+ private String name;
+
+ private String level;
+
+ public LoggerVM(Logger logger) {
+ this.name = logger.getName();
+ this.level = logger.getEffectiveLevel().toString();
+ }
+
+ @JsonCreator
+ public LoggerVM() {
+ // Empty public constructor used by Jackson.
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getLevel() {
+ return level;
+ }
+
+ public void setLevel(String level) {
+ this.level = level;
+ }
+
+ @Override
+ public String toString() {
+ return "LoggerVM{" +
+ "name='" + name + '\'' +
+ ", level='" + level + '\'' +
+ '}';
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/vm/package-info.java b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/vm/package-info.java
new file mode 100644
index 0000000000..02b0247926
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/java/com/car/app/web/rest/vm/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * View Models used by Spring MVC REST controllers.
+ */
+package com.car.app.web.rest.vm;
diff --git a/jhipster/jhipster-microservice/car-app/src/main/resources/.h2.server.properties b/jhipster/jhipster-microservice/car-app/src/main/resources/.h2.server.properties
new file mode 100644
index 0000000000..54cdead92e
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/resources/.h2.server.properties
@@ -0,0 +1,5 @@
+#H2 Server Properties
+0=JHipster H2 (Disk)|org.h2.Driver|jdbc\:h2\:file\:./target/h2db/db/carapp|carapp
+webAllowOthers=true
+webPort=8082
+webSSL=false
diff --git a/jhipster/src/main/resources/banner.txt b/jhipster/jhipster-microservice/car-app/src/main/resources/banner.txt
similarity index 100%
rename from jhipster/src/main/resources/banner.txt
rename to jhipster/jhipster-microservice/car-app/src/main/resources/banner.txt
diff --git a/jhipster/jhipster-microservice/car-app/src/main/resources/config/application-dev.yml b/jhipster/jhipster-microservice/car-app/src/main/resources/config/application-dev.yml
new file mode 100644
index 0000000000..87462edc75
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/resources/config/application-dev.yml
@@ -0,0 +1,148 @@
+# ===================================================================
+# Spring Boot configuration for the "dev" profile.
+#
+# This configuration overrides the application.yml file.
+#
+# More information on profiles: https://jhipster.github.io/profiles/
+# More information on configuration properties: https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+# ===================================================================
+# Standard Spring Boot properties.
+# Full reference is available at:
+# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
+# ===================================================================
+
+eureka:
+ instance:
+ prefer-ip-address: true
+ client:
+ enabled: true
+ healthcheck:
+ enabled: true
+ registerWithEureka: true
+ fetchRegistry: true
+ serviceUrl:
+ defaultZone: http://admin:${jhipster.registry.password}@localhost:8761/eureka/
+
+spring:
+ profiles:
+ active: dev
+ include: swagger
+ devtools:
+ restart:
+ enabled: true
+ livereload:
+ enabled: false # we use gulp + BrowserSync for livereload
+ jackson:
+ serialization.indent_output: true
+ datasource:
+ type: com.zaxxer.hikari.HikariDataSource
+ url: jdbc:h2:file:./target/h2db/db/carapp;DB_CLOSE_DELAY=-1
+ username: carapp
+ password:
+ h2:
+ console:
+ enabled: false
+ jpa:
+ database-platform: io.github.jhipster.domain.util.FixedH2Dialect
+ database: H2
+ show-sql: true
+ properties:
+ hibernate.id.new_generator_mappings: true
+ hibernate.cache.use_second_level_cache: true
+ hibernate.cache.use_query_cache: false
+ hibernate.generate_statistics: true
+ hibernate.cache.region.factory_class: com.hazelcast.hibernate.HazelcastCacheRegionFactory
+ hibernate.cache.hazelcast.instance_name: carapp
+ hibernate.cache.use_minimal_puts: true
+ hibernate.cache.hazelcast.use_lite_member: true
+ mail:
+ host: localhost
+ port: 25
+ username:
+ password:
+ messages:
+ cache-seconds: 1
+ thymeleaf:
+ cache: false
+
+liquibase:
+ contexts: dev
+
+# ===================================================================
+# To enable SSL, generate a certificate using:
+# keytool -genkey -alias carapp -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650
+#
+# You can also use Let's Encrypt:
+# https://maximilian-boehm.com/hp2121/Create-a-Java-Keystore-JKS-from-Let-s-Encrypt-Certificates.htm
+#
+# Then, modify the server.ssl properties so your "server" configuration looks like:
+#
+# server:
+# port: 8443
+# ssl:
+# key-store: keystore.p12
+# key-store-password:
+# keyStoreType: PKCS12
+# keyAlias: carapp
+# ===================================================================
+server:
+ port: 8081
+
+# ===================================================================
+# JHipster specific properties
+#
+# Full reference is available at: https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+jhipster:
+ http:
+ version: V_1_1 # To use HTTP/2 you will need SSL support (see above the "server.ssl" configuration)
+ cache: # Cache configuration
+ hazelcast: # Hazelcast distributed cache
+ time-to-live-seconds: 3600
+ backup-count: 1
+ security:
+ authentication:
+ jwt:
+ secret: my-secret-token-to-change-in-production
+ # Token is valid 24 hours
+ token-validity-in-seconds: 86400
+ token-validity-in-seconds-for-remember-me: 2592000
+ mail: # specific JHipster mail property, for standard properties see MailProperties
+ from: carapp@localhost
+ base-url: http://127.0.0.1:8081
+ metrics: # DropWizard Metrics configuration, used by MetricsConfiguration
+ jmx.enabled: true
+ graphite: # Use the "graphite" Maven profile to have the Graphite dependencies
+ enabled: false
+ host: localhost
+ port: 2003
+ prefix: carapp
+ prometheus: # Use the "prometheus" Maven profile to have the Prometheus dependencies
+ enabled: false
+ endpoint: /prometheusMetrics
+ logs: # Reports Dropwizard metrics in the logs
+ enabled: false
+ reportFrequency: 60 # in seconds
+ logging:
+ logstash: # Forward logs to logstash over a socket, used by LoggingConfiguration
+ enabled: false
+ host: localhost
+ port: 5000
+ queue-size: 512
+ spectator-metrics: # Reports Spectator Circuit Breaker metrics in the logs
+ enabled: false
+ # edit spring.metrics.export.delay-millis to set report frequency
+
+# ===================================================================
+# Application specific properties
+# Add your own application properties here, see the ApplicationProperties class
+# to have type-safe configuration, like in the JHipsterProperties above
+#
+# More documentation is available at:
+# https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+application:
diff --git a/jhipster/jhipster-microservice/car-app/src/main/resources/config/application-prod.yml b/jhipster/jhipster-microservice/car-app/src/main/resources/config/application-prod.yml
new file mode 100644
index 0000000000..9a7f557371
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/resources/config/application-prod.yml
@@ -0,0 +1,150 @@
+# ===================================================================
+# Spring Boot configuration for the "prod" profile.
+#
+# This configuration overrides the application.yml file.
+#
+# More information on profiles: https://jhipster.github.io/profiles/
+# More information on configuration properties: https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+# ===================================================================
+# Standard Spring Boot properties.
+# Full reference is available at:
+# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
+# ===================================================================
+
+eureka:
+ instance:
+ prefer-ip-address: true
+ client:
+ enabled: true
+ healthcheck:
+ enabled: true
+ registerWithEureka: true
+ fetchRegistry: true
+ serviceUrl:
+ defaultZone: http://admin:${jhipster.registry.password}@localhost:8761/eureka/
+
+spring:
+ devtools:
+ restart:
+ enabled: false
+ livereload:
+ enabled: false
+ datasource:
+ type: com.zaxxer.hikari.HikariDataSource
+ url: jdbc:mysql://localhost:3306/carapp?useUnicode=true&characterEncoding=utf8&useSSL=false
+ username: root
+ password:
+ hikari:
+ data-source-properties:
+ cachePrepStmts: true
+ prepStmtCacheSize: 250
+ prepStmtCacheSqlLimit: 2048
+ useServerPrepStmts: true
+ jpa:
+ database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
+ database: MYSQL
+ show-sql: false
+ properties:
+ hibernate.id.new_generator_mappings: true
+ hibernate.cache.use_second_level_cache: true
+ hibernate.cache.use_query_cache: false
+ hibernate.generate_statistics: false
+ hibernate.cache.region.factory_class: com.hazelcast.hibernate.HazelcastCacheRegionFactory
+ hibernate.cache.hazelcast.instance_name: carapp
+ hibernate.cache.use_minimal_puts: true
+ hibernate.cache.hazelcast.use_lite_member: true
+ mail:
+ host: localhost
+ port: 25
+ username:
+ password:
+ thymeleaf:
+ cache: true
+
+liquibase:
+ contexts: prod
+
+# ===================================================================
+# To enable SSL, generate a certificate using:
+# keytool -genkey -alias carapp -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650
+#
+# You can also use Let's Encrypt:
+# https://maximilian-boehm.com/hp2121/Create-a-Java-Keystore-JKS-from-Let-s-Encrypt-Certificates.htm
+#
+# Then, modify the server.ssl properties so your "server" configuration looks like:
+#
+# server:
+# port: 443
+# ssl:
+# key-store: keystore.p12
+# key-store-password:
+# keyStoreType: PKCS12
+# keyAlias: carapp
+# ===================================================================
+server:
+ port: 8081
+ compression:
+ enabled: true
+ mime-types: text/html,text/xml,text/plain,text/css, application/javascript, application/json
+ min-response-size: 1024
+
+# ===================================================================
+# JHipster specific properties
+#
+# Full reference is available at: https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+jhipster:
+ http:
+ version: V_1_1 # To use HTTP/2 you will need SSL support (see above the "server.ssl" configuration)
+ cache: # Used by the CachingHttpHeadersFilter
+ timeToLiveInDays: 1461
+ cache: # Cache configuration
+ hazelcast: # Hazelcast distributed cache
+ time-to-live-seconds: 3600
+ backup-count: 1
+ security:
+ authentication:
+ jwt:
+ secret: 0ebd193e0552c4ac548217d353abbde0761a1997
+ # Token is valid 24 hours
+ token-validity-in-seconds: 86400
+ token-validity-in-seconds-for-remember-me: 2592000
+ mail: # specific JHipster mail property, for standard properties see MailProperties
+ from: carapp@localhost
+ base-url: http://my-server-url-to-change # Modify according to your server's URL
+ metrics: # DropWizard Metrics configuration, used by MetricsConfiguration
+ jmx.enabled: true
+ graphite:
+ enabled: false
+ host: localhost
+ port: 2003
+ prefix: carapp
+ prometheus:
+ enabled: false
+ endpoint: /prometheusMetrics
+ logs: # Reports Dropwizard metrics in the logs
+ enabled: false
+ reportFrequency: 60 # in seconds
+ logging:
+ logstash: # Forward logs to logstash over a socket, used by LoggingConfiguration
+ enabled: false
+ host: localhost
+ port: 5000
+ queue-size: 512
+ spectator-metrics: # Reports Spectator Circuit Breaker metrics in the logs
+ enabled: false
+ # edit spring.metrics.export.delay-millis to set report frequency
+
+# ===================================================================
+# Application specific properties
+# Add your own application properties here, see the ApplicationProperties class
+# to have type-safe configuration, like in the JHipsterProperties above
+#
+# More documentation is available at:
+# https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+application:
diff --git a/jhipster/jhipster-microservice/car-app/src/main/resources/config/application.yml b/jhipster/jhipster-microservice/car-app/src/main/resources/config/application.yml
new file mode 100644
index 0000000000..40ccb38cad
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/resources/config/application.yml
@@ -0,0 +1,119 @@
+# ===================================================================
+# Spring Boot configuration.
+#
+# This configuration will be overriden by the Spring profile you use,
+# for example application-dev.yml if you use the "dev" profile.
+#
+# More information on profiles: https://jhipster.github.io/profiles/
+# More information on configuration properties: https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+# ===================================================================
+# Standard Spring Boot properties.
+# Full reference is available at:
+# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
+# ===================================================================
+
+eureka:
+ instance:
+ appname: carapp
+ instanceId: carapp:${spring.application.instance_id:${random.value}}
+ statusPageUrlPath: ${management.context-path}/info
+ healthCheckUrlPath: ${management.context-path}/health
+ metadata-map:
+ profile: ${spring.profiles.active}
+ version: ${info.project.version}
+ribbon:
+ eureka:
+ enabled: true
+# See https://github.com/Netflix/Hystrix/wiki/Configuration
+#hystrix:
+# command:
+# default:
+# execution:
+# isolation:
+# thread:
+# timeoutInMilliseconds: 10000
+
+management:
+ security:
+ roles: ADMIN
+ context-path: /management
+ health:
+ mail:
+ enabled: false # When using the MailService, configure an SMTP server and set this to true
+spring:
+ application:
+ name: carapp
+ jackson:
+ serialization.write_dates_as_timestamps: false
+ jpa:
+ open-in-view: false
+ hibernate:
+ ddl-auto: none
+ naming:
+ physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
+ implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
+ messages:
+ basename: i18n/messages
+ mvc:
+ favicon:
+ enabled: false
+ thymeleaf:
+ mode: XHTML
+
+security:
+ basic:
+ enabled: false
+
+server:
+ session:
+ cookie:
+ http-only: true
+
+
+# ===================================================================
+# JHipster specific properties
+#
+# Full reference is available at: https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+jhipster:
+ async:
+ core-pool-size: 2
+ max-pool-size: 50
+ queue-capacity: 10000
+ # By default CORS is disabled. Uncomment to enable.
+ #cors:
+ #allowed-origins: "*"
+ #allowed-methods: GET, PUT, POST, DELETE, OPTIONS
+ #allowed-headers: "*"
+ #exposed-headers:
+ #allow-credentials: true
+ #max-age: 1800
+ mail:
+ from: carapp@localhost
+ swagger:
+ default-include-pattern: /api/.*
+ title: carapp API
+ description: carapp API documentation
+ version: 0.0.1
+ terms-of-service-url:
+ contact-name:
+ contact-url:
+ contact-email:
+ license:
+ license-url:
+ ribbon:
+ display-on-active-profiles: dev
+
+# ===================================================================
+# Application specific properties
+# Add your own application properties here, see the ApplicationProperties class
+# to have type-safe configuration, like in the JHipsterProperties above
+#
+# More documentation is available at:
+# https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+application:
diff --git a/jhipster/jhipster-microservice/car-app/src/main/resources/config/bootstrap-prod.yml b/jhipster/jhipster-microservice/car-app/src/main/resources/config/bootstrap-prod.yml
new file mode 100644
index 0000000000..524e37ea53
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/resources/config/bootstrap-prod.yml
@@ -0,0 +1,22 @@
+# ===================================================================
+# Spring Cloud Config bootstrap configuration for the "prod" profile
+# ===================================================================
+
+spring:
+ cloud:
+ config:
+ fail-fast: true
+ retry:
+ initial-interval: 1000
+ max-interval: 2000
+ max-attempts: 100
+ uri: http://admin:${jhipster.registry.password}@localhost:8761/config
+ # name of the config server's property source (file.yml) that we want to use
+ name: carapp
+ profile: prod # profile(s) of the property source
+ label: master # toggle to switch to a different version of the configuration as stored in git
+ # it can be set to any label, branch or commit of the config source git repository
+
+jhipster:
+ registry:
+ password: admin
diff --git a/jhipster/jhipster-microservice/car-app/src/main/resources/config/bootstrap.yml b/jhipster/jhipster-microservice/car-app/src/main/resources/config/bootstrap.yml
new file mode 100644
index 0000000000..c1a608c4a5
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/resources/config/bootstrap.yml
@@ -0,0 +1,30 @@
+# ===================================================================
+# Spring Cloud Config bootstrap configuration for the "dev" profile
+# In prod profile, properties will be overwriten by the ones defined in bootstrap-prod.yml
+# ===================================================================
+
+jhipster:
+ registry:
+ password: admin
+
+spring:
+ application:
+ name: carapp
+ profiles:
+ # The commented value for `active` can be replaced with valid Spring profiles to load.
+ # Otherwise, it will be filled in by maven when building the WAR file
+ # Either way, it can be overridden by `--spring.profiles.active` value passed in the commandline or `-Dspring.profiles.active` set in `JAVA_OPTS`
+ active: #spring.profiles.active#
+ cloud:
+ config:
+ fail-fast: true
+ uri: http://admin:${jhipster.registry.password}@localhost:8761/config
+ # name of the config server's property source (file.yml) that we want to use
+ name: carapp
+ profile: dev # profile(s) of the property source
+ label: master # toggle to switch to a different version of the configuration as stored in git
+ # it can be set to any label, branch or commit of the config source git repository
+
+info:
+ project:
+ version: #project.version#
diff --git a/jhipster/jhipster-microservice/car-app/src/main/resources/config/liquibase/changelog/00000000000000_initial_schema.xml b/jhipster/jhipster-microservice/car-app/src/main/resources/config/liquibase/changelog/00000000000000_initial_schema.xml
new file mode 100644
index 0000000000..2a1ee4d6bf
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/resources/config/liquibase/changelog/00000000000000_initial_schema.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jhipster/jhipster-microservice/car-app/src/main/resources/config/liquibase/changelog/20170503041524_added_entity_Car.xml b/jhipster/jhipster-microservice/car-app/src/main/resources/config/liquibase/changelog/20170503041524_added_entity_Car.xml
new file mode 100644
index 0000000000..0b8c3f5136
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/resources/config/liquibase/changelog/20170503041524_added_entity_Car.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jhipster/jhipster-microservice/car-app/src/main/resources/config/liquibase/master.xml b/jhipster/jhipster-microservice/car-app/src/main/resources/config/liquibase/master.xml
new file mode 100644
index 0000000000..398b615ea1
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/resources/config/liquibase/master.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
diff --git a/jhipster/jhipster-microservice/car-app/src/main/resources/i18n/messages.properties b/jhipster/jhipster-microservice/car-app/src/main/resources/i18n/messages.properties
new file mode 100644
index 0000000000..9a850cb789
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/resources/i18n/messages.properties
@@ -0,0 +1,22 @@
+# Error page
+error.title=Your request cannot be processed
+error.subtitle=Sorry, an error has occurred.
+error.status=Status:
+error.message=Message:
+
+# Activation e-mail
+email.activation.title=carapp account activation
+email.activation.greeting=Dear {0}
+email.activation.text1=Your carapp account has been created, please click on the URL below to activate it:
+email.activation.text2=Regards,
+email.signature=carapp Team.
+
+# Creation email
+email.creation.text1=Your carapp account has been created, please click on the URL below to access it:
+
+# Reset e-mail
+email.reset.title=carapp password reset
+email.reset.greeting=Dear {0}
+email.reset.text1=For your carapp account a password reset was requested, please click on the URL below to reset it:
+email.reset.text2=Regards,
+
diff --git a/jhipster/jhipster-microservice/car-app/src/main/resources/logback-spring.xml b/jhipster/jhipster-microservice/car-app/src/main/resources/logback-spring.xml
new file mode 100644
index 0000000000..33c3d4fde4
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/main/resources/logback-spring.xml
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
diff --git a/jhipster/src/main/resources/templates/error.html b/jhipster/jhipster-microservice/car-app/src/main/resources/templates/error.html
similarity index 100%
rename from jhipster/src/main/resources/templates/error.html
rename to jhipster/jhipster-microservice/car-app/src/main/resources/templates/error.html
diff --git a/jhipster/jhipster-microservice/car-app/src/test/java/com/car/app/web/rest/CarResourceIntTest.java b/jhipster/jhipster-microservice/car-app/src/test/java/com/car/app/web/rest/CarResourceIntTest.java
new file mode 100644
index 0000000000..b18e5950d3
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/test/java/com/car/app/web/rest/CarResourceIntTest.java
@@ -0,0 +1,244 @@
+package com.car.app.web.rest;
+
+import com.car.app.CarappApp;
+
+import com.car.app.domain.Car;
+import com.car.app.repository.CarRepository;
+import com.car.app.web.rest.errors.ExceptionTranslator;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.persistence.EntityManager;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.Matchers.hasItem;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
+
+/**
+ * Test class for the CarResource REST controller.
+ *
+ * @see CarResource
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = CarappApp.class)
+public class CarResourceIntTest {
+
+ private static final String DEFAULT_MAKE = "AAAAAAAAAA";
+ private static final String UPDATED_MAKE = "BBBBBBBBBB";
+
+ private static final String DEFAULT_BRAND = "AAAAAAAAAA";
+ private static final String UPDATED_BRAND = "BBBBBBBBBB";
+
+ private static final Double DEFAULT_PRICE = 1D;
+ private static final Double UPDATED_PRICE = 2D;
+
+ @Autowired
+ private CarRepository carRepository;
+
+ @Autowired
+ private MappingJackson2HttpMessageConverter jacksonMessageConverter;
+
+ @Autowired
+ private PageableHandlerMethodArgumentResolver pageableArgumentResolver;
+
+ @Autowired
+ private ExceptionTranslator exceptionTranslator;
+
+ @Autowired
+ private EntityManager em;
+
+ private MockMvc restCarMockMvc;
+
+ private Car car;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ CarResource carResource = new CarResource(carRepository);
+ this.restCarMockMvc = MockMvcBuilders.standaloneSetup(carResource)
+ .setCustomArgumentResolvers(pageableArgumentResolver)
+ .setControllerAdvice(exceptionTranslator)
+ .setMessageConverters(jacksonMessageConverter).build();
+ }
+
+ /**
+ * Create an entity for this test.
+ *
+ * This is a static method, as tests for other entities might also need it,
+ * if they test an entity which requires the current entity.
+ */
+ public static Car createEntity(EntityManager em) {
+ Car car = new Car()
+ .make(DEFAULT_MAKE)
+ .brand(DEFAULT_BRAND)
+ .price(DEFAULT_PRICE);
+ return car;
+ }
+
+ @Before
+ public void initTest() {
+ car = createEntity(em);
+ }
+
+ @Test
+ @Transactional
+ public void createCar() throws Exception {
+ int databaseSizeBeforeCreate = carRepository.findAll().size();
+
+ // Create the Car
+ restCarMockMvc.perform(post("/api/cars")
+ .contentType(TestUtil.APPLICATION_JSON_UTF8)
+ .content(TestUtil.convertObjectToJsonBytes(car)))
+ .andExpect(status().isCreated());
+
+ // Validate the Car in the database
+ List carList = carRepository.findAll();
+ assertThat(carList).hasSize(databaseSizeBeforeCreate + 1);
+ Car testCar = carList.get(carList.size() - 1);
+ assertThat(testCar.getMake()).isEqualTo(DEFAULT_MAKE);
+ assertThat(testCar.getBrand()).isEqualTo(DEFAULT_BRAND);
+ assertThat(testCar.getPrice()).isEqualTo(DEFAULT_PRICE);
+ }
+
+ @Test
+ @Transactional
+ public void createCarWithExistingId() throws Exception {
+ int databaseSizeBeforeCreate = carRepository.findAll().size();
+
+ // Create the Car with an existing ID
+ car.setId(1L);
+
+ // An entity with an existing ID cannot be created, so this API call must fail
+ restCarMockMvc.perform(post("/api/cars")
+ .contentType(TestUtil.APPLICATION_JSON_UTF8)
+ .content(TestUtil.convertObjectToJsonBytes(car)))
+ .andExpect(status().isBadRequest());
+
+ // Validate the Alice in the database
+ List carList = carRepository.findAll();
+ assertThat(carList).hasSize(databaseSizeBeforeCreate);
+ }
+
+ @Test
+ @Transactional
+ public void getAllCars() throws Exception {
+ // Initialize the database
+ carRepository.saveAndFlush(car);
+
+ // Get all the carList
+ restCarMockMvc.perform(get("/api/cars?sort=id,desc"))
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
+ .andExpect(jsonPath("$.[*].id").value(hasItem(car.getId().intValue())))
+ .andExpect(jsonPath("$.[*].make").value(hasItem(DEFAULT_MAKE.toString())))
+ .andExpect(jsonPath("$.[*].brand").value(hasItem(DEFAULT_BRAND.toString())))
+ .andExpect(jsonPath("$.[*].price").value(hasItem(DEFAULT_PRICE.doubleValue())));
+ }
+
+ @Test
+ @Transactional
+ public void getCar() throws Exception {
+ // Initialize the database
+ carRepository.saveAndFlush(car);
+
+ // Get the car
+ restCarMockMvc.perform(get("/api/cars/{id}", car.getId()))
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
+ .andExpect(jsonPath("$.id").value(car.getId().intValue()))
+ .andExpect(jsonPath("$.make").value(DEFAULT_MAKE.toString()))
+ .andExpect(jsonPath("$.brand").value(DEFAULT_BRAND.toString()))
+ .andExpect(jsonPath("$.price").value(DEFAULT_PRICE.doubleValue()));
+ }
+
+ @Test
+ @Transactional
+ public void getNonExistingCar() throws Exception {
+ // Get the car
+ restCarMockMvc.perform(get("/api/cars/{id}", Long.MAX_VALUE))
+ .andExpect(status().isNotFound());
+ }
+
+ @Test
+ @Transactional
+ public void updateCar() throws Exception {
+ // Initialize the database
+ carRepository.saveAndFlush(car);
+ int databaseSizeBeforeUpdate = carRepository.findAll().size();
+
+ // Update the car
+ Car updatedCar = carRepository.findOne(car.getId());
+ updatedCar
+ .make(UPDATED_MAKE)
+ .brand(UPDATED_BRAND)
+ .price(UPDATED_PRICE);
+
+ restCarMockMvc.perform(put("/api/cars")
+ .contentType(TestUtil.APPLICATION_JSON_UTF8)
+ .content(TestUtil.convertObjectToJsonBytes(updatedCar)))
+ .andExpect(status().isOk());
+
+ // Validate the Car in the database
+ List carList = carRepository.findAll();
+ assertThat(carList).hasSize(databaseSizeBeforeUpdate);
+ Car testCar = carList.get(carList.size() - 1);
+ assertThat(testCar.getMake()).isEqualTo(UPDATED_MAKE);
+ assertThat(testCar.getBrand()).isEqualTo(UPDATED_BRAND);
+ assertThat(testCar.getPrice()).isEqualTo(UPDATED_PRICE);
+ }
+
+ @Test
+ @Transactional
+ public void updateNonExistingCar() throws Exception {
+ int databaseSizeBeforeUpdate = carRepository.findAll().size();
+
+ // Create the Car
+
+ // If the entity doesn't have an ID, it will be created instead of just being updated
+ restCarMockMvc.perform(put("/api/cars")
+ .contentType(TestUtil.APPLICATION_JSON_UTF8)
+ .content(TestUtil.convertObjectToJsonBytes(car)))
+ .andExpect(status().isCreated());
+
+ // Validate the Car in the database
+ List carList = carRepository.findAll();
+ assertThat(carList).hasSize(databaseSizeBeforeUpdate + 1);
+ }
+
+ @Test
+ @Transactional
+ public void deleteCar() throws Exception {
+ // Initialize the database
+ carRepository.saveAndFlush(car);
+ int databaseSizeBeforeDelete = carRepository.findAll().size();
+
+ // Get the car
+ restCarMockMvc.perform(delete("/api/cars/{id}", car.getId())
+ .accept(TestUtil.APPLICATION_JSON_UTF8))
+ .andExpect(status().isOk());
+
+ // Validate the database is empty
+ List carList = carRepository.findAll();
+ assertThat(carList).hasSize(databaseSizeBeforeDelete - 1);
+ }
+
+ @Test
+ @Transactional
+ public void equalsVerifier() throws Exception {
+ TestUtil.equalsVerifier(Car.class);
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/test/java/com/car/app/web/rest/TestUtil.java b/jhipster/jhipster-microservice/car-app/src/test/java/com/car/app/web/rest/TestUtil.java
new file mode 100644
index 0000000000..631200376b
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/test/java/com/car/app/web/rest/TestUtil.java
@@ -0,0 +1,120 @@
+package com.car.app.web.rest;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.http.MediaType;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeParseException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Utility class for testing REST controllers.
+ */
+public class TestUtil {
+
+ /** MediaType for JSON UTF8 */
+ public static final MediaType APPLICATION_JSON_UTF8 = new MediaType(
+ MediaType.APPLICATION_JSON.getType(),
+ MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8"));
+
+ /**
+ * Convert an object to JSON byte array.
+ *
+ * @param object
+ * the object to convert
+ * @return the JSON byte array
+ * @throws IOException
+ */
+ public static byte[] convertObjectToJsonBytes(Object object)
+ throws IOException {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+
+ JavaTimeModule module = new JavaTimeModule();
+ mapper.registerModule(module);
+
+ return mapper.writeValueAsBytes(object);
+ }
+
+ /**
+ * Create a byte array with a specific size filled with specified data.
+ *
+ * @param size the size of the byte array
+ * @param data the data to put in the byte array
+ * @return the JSON byte array
+ */
+ public static byte[] createByteArray(int size, String data) {
+ byte[] byteArray = new byte[size];
+ for (int i = 0; i < size; i++) {
+ byteArray[i] = Byte.parseByte(data, 2);
+ }
+ return byteArray;
+ }
+
+ /**
+ * A matcher that tests that the examined string represents the same instant as the reference datetime.
+ */
+ public static class ZonedDateTimeMatcher extends TypeSafeDiagnosingMatcher {
+
+ private final ZonedDateTime date;
+
+ public ZonedDateTimeMatcher(ZonedDateTime date) {
+ this.date = date;
+ }
+
+ @Override
+ protected boolean matchesSafely(String item, Description mismatchDescription) {
+ try {
+ if (!date.isEqual(ZonedDateTime.parse(item))) {
+ mismatchDescription.appendText("was ").appendValue(item);
+ return false;
+ }
+ return true;
+ } catch (DateTimeParseException e) {
+ mismatchDescription.appendText("was ").appendValue(item)
+ .appendText(", which could not be parsed as a ZonedDateTime");
+ return false;
+ }
+
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("a String representing the same Instant as ").appendValue(date);
+ }
+ }
+
+ /**
+ * Creates a matcher that matches when the examined string reprensents the same instant as the reference datetime
+ * @param date the reference datetime against which the examined string is checked
+ */
+ public static ZonedDateTimeMatcher sameInstant(ZonedDateTime date) {
+ return new ZonedDateTimeMatcher(date);
+ }
+
+ /**
+ * Verifies the equals/hashcode contract on the domain object.
+ */
+ public static void equalsVerifier(Class clazz) throws Exception {
+ Object domainObject1 = clazz.getConstructor().newInstance();
+ assertThat(domainObject1.toString()).isNotNull();
+ assertThat(domainObject1).isEqualTo(domainObject1);
+ assertThat(domainObject1.hashCode()).isEqualTo(domainObject1.hashCode());
+ // Test with an instance of another class
+ Object testOtherObject = new Object();
+ assertThat(domainObject1).isNotEqualTo(testOtherObject);
+ // Test with an instance of the same class
+ Object domainObject2 = clazz.getConstructor().newInstance();
+ assertThat(domainObject1).isNotEqualTo(domainObject2);
+ // HashCodes are equals because the objects are not persisted yet
+ assertThat(domainObject1.hashCode()).isEqualTo(domainObject2.hashCode());
+ }
+}
diff --git a/jhipster/jhipster-microservice/car-app/src/test/resources/config/application.yml b/jhipster/jhipster-microservice/car-app/src/test/resources/config/application.yml
new file mode 100644
index 0000000000..a9e3b02b64
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/test/resources/config/application.yml
@@ -0,0 +1,102 @@
+# ===================================================================
+# Spring Boot configuration.
+#
+# This configuration is used for unit/integration tests.
+#
+# More information on profiles: https://jhipster.github.io/profiles/
+# More information on configuration properties: https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+# ===================================================================
+# Standard Spring Boot properties.
+# Full reference is available at:
+# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
+# ===================================================================
+
+eureka:
+ client:
+ enabled: false
+ instance:
+ appname: carapp
+ instanceId: carapp:${spring.application.instance_id:${random.value}}
+
+spring:
+ application:
+ name: carapp
+ jackson:
+ serialization.write_dates_as_timestamps: false
+ cache:
+ type: none
+ datasource:
+ type: com.zaxxer.hikari.HikariDataSource
+ url: jdbc:h2:mem:carapp;DB_CLOSE_DELAY=-1
+ name:
+ username:
+ password:
+ jpa:
+ database-platform: io.github.jhipster.domain.util.FixedH2Dialect
+ database: H2
+ open-in-view: false
+ show-sql: true
+ hibernate:
+ ddl-auto: none
+ naming:
+ physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
+ implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
+ properties:
+ hibernate.id.new_generator_mappings: true
+ hibernate.cache.use_second_level_cache: false
+ hibernate.cache.use_query_cache: false
+ hibernate.generate_statistics: true
+ hibernate.hbm2ddl.auto: validate
+ mail:
+ host: localhost
+ messages:
+ basename: i18n/messages
+ mvc:
+ favicon:
+ enabled: false
+ thymeleaf:
+ mode: XHTML
+
+liquibase:
+ contexts: test
+
+security:
+ basic:
+ enabled: false
+
+server:
+ port: 10344
+ address: localhost
+
+# ===================================================================
+# JHipster specific properties
+#
+# Full reference is available at: https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+jhipster:
+ async:
+ core-pool-size: 2
+ max-pool-size: 50
+ queue-capacity: 10000
+ security:
+ authentication:
+ jwt:
+ secret: 0ebd193e0552c4ac548217d353abbde0761a1997
+ # Token is valid 24 hours
+ token-validity-in-seconds: 86400
+ metrics: # DropWizard Metrics configuration, used by MetricsConfiguration
+ jmx.enabled: true
+
+# ===================================================================
+# Application specific properties
+# Add your own application properties here, see the ApplicationProperties class
+# to have type-safe configuration, like in the JHipsterProperties above
+#
+# More documentation is available at:
+# https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+application:
diff --git a/jhipster/jhipster-microservice/car-app/src/test/resources/config/bootstrap.yml b/jhipster/jhipster-microservice/car-app/src/test/resources/config/bootstrap.yml
new file mode 100644
index 0000000000..11cd6af21c
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/test/resources/config/bootstrap.yml
@@ -0,0 +1,4 @@
+spring:
+ cloud:
+ config:
+ enabled: false
diff --git a/jhipster/jhipster-microservice/car-app/src/test/resources/logback-test.xml b/jhipster/jhipster-microservice/car-app/src/test/resources/logback-test.xml
new file mode 100644
index 0000000000..aace473c4c
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/src/test/resources/logback-test.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jhipster/jhipster-microservice/car-app/yarn.lock b/jhipster/jhipster-microservice/car-app/yarn.lock
new file mode 100644
index 0000000000..4333a516f1
--- /dev/null
+++ b/jhipster/jhipster-microservice/car-app/yarn.lock
@@ -0,0 +1,2439 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+abbrev@1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f"
+
+acorn-jsx@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b"
+ dependencies:
+ acorn "^3.0.4"
+
+acorn@^3.0.4:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
+
+ajv@^4.9.1:
+ version "4.11.8"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
+ dependencies:
+ co "^4.6.0"
+ json-stable-stringify "^1.0.1"
+
+amdefine@>=0.0.4:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
+
+ansi-escapes@^1.1.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
+
+ansi-regex@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+
+ansi-styles@^2.0.0, ansi-styles@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+
+ansi@^0.3.0, ansi@~0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/ansi/-/ansi-0.3.1.tgz#0c42d4fb17160d5a9af1e484bace1c66922c1b21"
+
+are-we-there-yet@~1.1.2:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d"
+ dependencies:
+ delegates "^1.0.0"
+ readable-stream "^2.0.6"
+
+argparse@^1.0.7:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86"
+ dependencies:
+ sprintf-js "~1.0.2"
+
+array-differ@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031"
+
+array-find-index@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
+
+array-union@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
+ dependencies:
+ array-uniq "^1.0.1"
+
+array-uniq@^1.0.0, array-uniq@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
+
+arrify@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
+
+asn1@~0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86"
+
+assert-plus@1.0.0, assert-plus@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
+
+assert-plus@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234"
+
+ast-query@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ast-query/-/ast-query-2.0.0.tgz#3588e79ad8de07ce50df1e781cc2bda1fd69a453"
+ dependencies:
+ acorn-jsx "^3.0.1"
+ class-extend "^0.1.1"
+ escodegen-wallaby "^1.6.7"
+ lodash "^4.6.1"
+ traverse "^0.6.6"
+
+async@^1.0.0, async@^1.4.2:
+ version "1.5.2"
+ resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
+
+async@^2.0.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/async/-/async-2.4.0.tgz#4990200f18ea5b837c2cc4f8c031a6985c385611"
+ dependencies:
+ lodash "^4.14.0"
+
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+
+aws-sign2@~0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f"
+
+aws4@^1.2.1:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
+
+balanced-match@^0.4.1:
+ version "0.4.2"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
+
+bcrypt-pbkdf@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d"
+ dependencies:
+ tweetnacl "^0.14.3"
+
+bin-version-check@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/bin-version-check/-/bin-version-check-2.1.0.tgz#e4e5df290b9069f7d111324031efc13fdd11a5b0"
+ dependencies:
+ bin-version "^1.0.0"
+ minimist "^1.1.0"
+ semver "^4.0.3"
+ semver-truncate "^1.0.0"
+
+bin-version@^1.0.0:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/bin-version/-/bin-version-1.0.4.tgz#9eb498ee6fd76f7ab9a7c160436f89579435d78e"
+ dependencies:
+ find-versions "^1.0.0"
+
+"binaryextensions@1 || 2":
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-2.0.0.tgz#e597d1a7a6a3558a2d1c7241a16c99965e6aa40f"
+
+boolbase@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
+
+boom@2.x.x:
+ version "2.10.1"
+ resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f"
+ dependencies:
+ hoek "2.x.x"
+
+boxen@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/boxen/-/boxen-0.3.1.tgz#a7d898243ae622f7abb6bb604d740a76c6a5461b"
+ dependencies:
+ chalk "^1.1.1"
+ filled-array "^1.0.0"
+ object-assign "^4.0.1"
+ repeating "^2.0.0"
+ string-width "^1.0.1"
+ widest-line "^1.0.0"
+
+brace-expansion@^1.0.0:
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59"
+ dependencies:
+ balanced-match "^0.4.1"
+ concat-map "0.0.1"
+
+buffer-shims@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51"
+
+builtin-modules@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
+
+camelcase-keys@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
+ dependencies:
+ camelcase "^2.0.0"
+ map-obj "^1.0.0"
+
+camelcase@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
+
+capture-stack-trace@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d"
+
+caseless@~0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
+
+chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+ dependencies:
+ ansi-styles "^2.2.1"
+ escape-string-regexp "^1.0.2"
+ has-ansi "^2.0.0"
+ strip-ansi "^3.0.0"
+ supports-color "^2.0.0"
+
+cheerio@0.22.0:
+ version "0.22.0"
+ resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e"
+ dependencies:
+ css-select "~1.2.0"
+ dom-serializer "~0.1.0"
+ entities "~1.1.1"
+ htmlparser2 "^3.9.1"
+ lodash.assignin "^4.0.9"
+ lodash.bind "^4.1.4"
+ lodash.defaults "^4.0.1"
+ lodash.filter "^4.4.0"
+ lodash.flatten "^4.2.0"
+ lodash.foreach "^4.3.0"
+ lodash.map "^4.4.0"
+ lodash.merge "^4.4.0"
+ lodash.pick "^4.2.1"
+ lodash.reduce "^4.4.0"
+ lodash.reject "^4.4.0"
+ lodash.some "^4.4.0"
+
+cheerio@^0.19.0:
+ version "0.19.0"
+ resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.19.0.tgz#772e7015f2ee29965096d71ea4175b75ab354925"
+ dependencies:
+ css-select "~1.0.0"
+ dom-serializer "~0.1.0"
+ entities "~1.1.1"
+ htmlparser2 "~3.8.1"
+ lodash "^3.2.0"
+
+class-extend@^0.1.0, class-extend@^0.1.1:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/class-extend/-/class-extend-0.1.2.tgz#8057a82b00f53f82a5d62c50ef8cffdec6fabc34"
+ dependencies:
+ object-assign "^2.0.0"
+
+cli-boxes@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143"
+
+cli-cursor@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987"
+ dependencies:
+ restore-cursor "^1.0.1"
+
+cli-list@^0.1.1:
+ version "0.1.8"
+ resolved "https://registry.yarnpkg.com/cli-list/-/cli-list-0.1.8.tgz#aee6d45c4c59bf80068bb968089fb06f1aeddc0a"
+
+cli-table@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23"
+ dependencies:
+ colors "1.0.3"
+
+cli-width@^1.0.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-1.1.1.tgz#a4d293ef67ebb7b88d4a4d42c0ccf00c4d1e366d"
+
+cli-width@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a"
+
+clone-regexp@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-1.0.0.tgz#eae0a2413f55c0942f818c229fefce845d7f3b1c"
+ dependencies:
+ is-regexp "^1.0.0"
+ is-supported-regexp-flag "^1.0.0"
+
+clone-stats@^0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1"
+
+clone@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.2.tgz#260b7a99ebb1edfe247538175f783243cb19d149"
+
+co@^4.6.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
+
+code-point-at@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
+
+colors@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
+
+combined-stream@^1.0.5, combined-stream@~1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009"
+ dependencies:
+ delayed-stream "~1.0.0"
+
+commondir@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+
+concat-stream@^1.4.7:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
+ dependencies:
+ inherits "^2.0.3"
+ readable-stream "^2.2.2"
+ typedarray "^0.0.6"
+
+config-chain@~1.1.8:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.11.tgz#aba09747dfbe4c3e70e766a6e41586e1859fc6f2"
+ dependencies:
+ ini "^1.3.4"
+ proto-list "~1.2.1"
+
+configstore@^1.0.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/configstore/-/configstore-1.4.0.tgz#c35781d0501d268c25c54b8b17f6240e8a4fb021"
+ dependencies:
+ graceful-fs "^4.1.2"
+ mkdirp "^0.5.0"
+ object-assign "^4.0.1"
+ os-tmpdir "^1.0.0"
+ osenv "^0.1.0"
+ uuid "^2.0.1"
+ write-file-atomic "^1.1.2"
+ xdg-basedir "^2.0.0"
+
+configstore@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/configstore/-/configstore-2.1.0.tgz#737a3a7036e9886102aa6099e47bb33ab1aba1a1"
+ dependencies:
+ dot-prop "^3.0.0"
+ graceful-fs "^4.1.2"
+ mkdirp "^0.5.0"
+ object-assign "^4.0.1"
+ os-tmpdir "^1.0.0"
+ osenv "^0.1.0"
+ uuid "^2.0.1"
+ write-file-atomic "^1.1.2"
+ xdg-basedir "^2.0.0"
+
+core-util-is@~1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
+
+create-error-class@^3.0.1:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6"
+ dependencies:
+ capture-stack-trace "^1.0.0"
+
+cross-spawn@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982"
+ dependencies:
+ lru-cache "^4.0.1"
+ which "^1.2.9"
+
+cross-spawn@^4.0.0:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41"
+ dependencies:
+ lru-cache "^4.0.1"
+ which "^1.2.9"
+
+cryptiles@2.x.x:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
+ dependencies:
+ boom "2.x.x"
+
+css-select@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.0.0.tgz#b1121ca51848dd264e2244d058cee254deeb44b0"
+ dependencies:
+ boolbase "~1.0.0"
+ css-what "1.0"
+ domutils "1.4"
+ nth-check "~1.0.0"
+
+css-select@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
+ dependencies:
+ boolbase "~1.0.0"
+ css-what "2.1"
+ domutils "1.5.1"
+ nth-check "~1.0.1"
+
+css-what@1.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/css-what/-/css-what-1.0.0.tgz#d7cc2df45180666f99d2b14462639469e00f736c"
+
+css-what@2.1:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd"
+
+currently-unhandled@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
+ dependencies:
+ array-find-index "^1.0.1"
+
+dargs@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/dargs/-/dargs-4.1.0.tgz#03a9dbb4b5c2f139bf14ae53f0b8a2a6a86f4e17"
+ dependencies:
+ number-is-nan "^1.0.0"
+
+dashdash@^1.12.0:
+ version "1.14.1"
+ resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
+ dependencies:
+ assert-plus "^1.0.0"
+
+dateformat@^1.0.11:
+ version "1.0.12"
+ resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9"
+ dependencies:
+ get-stdin "^4.0.1"
+ meow "^3.3.0"
+
+debug@^2.0.0, debug@^2.1.0, debug@^2.2.0:
+ version "2.6.6"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.6.tgz#a9fa6fbe9ca43cf1e79f73b75c0189cbb7d6db5a"
+ dependencies:
+ ms "0.7.3"
+
+decamelize@^1.0.0, decamelize@^1.1.2:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+
+deep-extend@^0.4.0, deep-extend@~0.4.0:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.1.tgz#efe4113d08085f4e6f9687759810f807469e2253"
+
+deep-is@~0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
+
+default-uid@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/default-uid/-/default-uid-1.0.0.tgz#fcefa9df9f5ac40c8916d912dd1fe1146aa3c59e"
+
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+
+delegates@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
+
+detect-conflict@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/detect-conflict/-/detect-conflict-1.0.1.tgz#088657a66a961c05019db7c4230883b1c6b4176e"
+
+detect-newline@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-1.0.3.tgz#e97b1003877d70c09af1af35bfadff168de4920d"
+ dependencies:
+ get-stdin "^4.0.1"
+ minimist "^1.1.0"
+
+diff@^2.1.2:
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/diff/-/diff-2.2.3.tgz#60eafd0d28ee906e4e8ff0a52c1229521033bf99"
+
+discontinuous-range@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a"
+
+dom-serializer@0, dom-serializer@~0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82"
+ dependencies:
+ domelementtype "~1.1.1"
+ entities "~1.1.1"
+
+domelementtype@1, domelementtype@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2"
+
+domelementtype@~1.1.1:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b"
+
+domhandler@2.3, domhandler@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.3.0.tgz#2de59a0822d5027fabff6f032c2b25a2a8abe738"
+ dependencies:
+ domelementtype "1"
+
+domutils@1.4:
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.4.3.tgz#0865513796c6b306031850e175516baf80b72a6f"
+ dependencies:
+ domelementtype "1"
+
+domutils@1.5, domutils@1.5.1, domutils@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf"
+ dependencies:
+ dom-serializer "0"
+ domelementtype "1"
+
+dot-prop@^2.0.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-2.4.0.tgz#848e28f7f1d50740c6747ab3cb07670462b6f89c"
+ dependencies:
+ is-obj "^1.0.0"
+
+dot-prop@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-3.0.0.tgz#1b708af094a49c9a0e7dbcad790aba539dac1177"
+ dependencies:
+ is-obj "^1.0.0"
+
+downgrade-root@^1.0.0:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/downgrade-root/-/downgrade-root-1.2.2.tgz#531319715b0e81ffcc22eb28478ba27643e12c6c"
+ dependencies:
+ default-uid "^1.0.0"
+ is-root "^1.0.0"
+
+duplexer2@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
+ dependencies:
+ readable-stream "^2.0.2"
+
+each-async@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/each-async/-/each-async-1.1.1.tgz#dee5229bdf0ab6ba2012a395e1b869abf8813473"
+ dependencies:
+ onetime "^1.0.0"
+ set-immediate-shim "^1.0.0"
+
+ecc-jsbn@~0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505"
+ dependencies:
+ jsbn "~0.1.0"
+
+editions@^1.1.1:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.3.tgz#0907101bdda20fac3cbe334c27cbd0688dc99a5b"
+
+ejs@2.5.6, ejs@^2.3.1:
+ version "2.5.6"
+ resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.6.tgz#479636bfa3fe3b1debd52087f0acb204b4f19c88"
+
+entities@1.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26"
+
+entities@^1.1.1, entities@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0"
+
+error-ex@^1.2.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc"
+ dependencies:
+ is-arrayish "^0.2.1"
+
+error@^7.0.2:
+ version "7.0.2"
+ resolved "https://registry.yarnpkg.com/error/-/error-7.0.2.tgz#a5f75fff4d9926126ddac0ea5dc38e689153cb02"
+ dependencies:
+ string-template "~0.2.1"
+ xtend "~4.0.0"
+
+escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+
+escodegen-wallaby@^1.6.7:
+ version "1.6.11"
+ resolved "https://registry.yarnpkg.com/escodegen-wallaby/-/escodegen-wallaby-1.6.11.tgz#39100cde743f9acdd24bd868db5a12fbacde6ed1"
+ dependencies:
+ esprima "^2.7.1"
+ estraverse "^1.9.1"
+ esutils "^2.0.2"
+ optionator "^0.8.1"
+ optionalDependencies:
+ source-map "~0.2.0"
+
+esprima@^2.7.1:
+ version "2.7.3"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
+
+esprima@^3.1.1:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
+
+estraverse@^1.9.1:
+ version "1.9.3"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44"
+
+esutils@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
+
+execall@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/execall/-/execall-1.0.0.tgz#73d0904e395b3cab0658b08d09ec25307f29bb73"
+ dependencies:
+ clone-regexp "^1.0.0"
+
+exit-hook@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8"
+
+extend@^3.0.0, extend@~3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
+
+external-editor@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-1.1.1.tgz#12d7b0db850f7ff7e7081baf4005700060c4600b"
+ dependencies:
+ extend "^3.0.0"
+ spawn-sync "^1.0.15"
+ tmp "^0.0.29"
+
+extsprintf@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550"
+
+fast-levenshtein@~2.0.4:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
+
+figures@^1.3.5:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
+ dependencies:
+ escape-string-regexp "^1.0.5"
+ object-assign "^4.1.0"
+
+filled-array@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/filled-array/-/filled-array-1.1.0.tgz#c3c4f6c663b923459a9aa29912d2d031f1507f84"
+
+find-up@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
+ dependencies:
+ path-exists "^2.0.0"
+ pinkie-promise "^2.0.0"
+
+find-versions@^1.0.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-1.2.1.tgz#cbde9f12e38575a0af1be1b9a2c5d5fd8f186b62"
+ dependencies:
+ array-uniq "^1.0.0"
+ get-stdin "^4.0.1"
+ meow "^3.5.0"
+ semver-regex "^1.0.0"
+
+first-chunk-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz#1bdecdb8e083c0664b91945581577a43a9f31d70"
+ dependencies:
+ readable-stream "^2.0.2"
+
+foreachasync@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/foreachasync/-/foreachasync-3.0.0.tgz#5502987dc8714be3392097f32e0071c9dee07cf6"
+
+forever-agent@~0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
+
+form-data@~2.1.1:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1"
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.5"
+ mime-types "^2.1.12"
+
+formatio@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9"
+ dependencies:
+ samsam "~1.1"
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+
+fullname@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/fullname/-/fullname-2.1.0.tgz#c46bf0f7c3f24fd5b3358d00e4a41380eef87350"
+ dependencies:
+ npmconf "^2.1.1"
+ pify "^2.2.0"
+ pinkie-promise "^2.0.0"
+
+gauge@~1.2.5:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/gauge/-/gauge-1.2.7.tgz#e9cec5483d3d4ee0ef44b60a7d99e4935e136d93"
+ dependencies:
+ ansi "^0.3.0"
+ has-unicode "^2.0.0"
+ lodash.pad "^4.1.0"
+ lodash.padend "^4.1.0"
+ lodash.padstart "^4.1.0"
+
+generator-jhipster@4.0.8:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/generator-jhipster/-/generator-jhipster-4.0.8.tgz#9daff076cc628500726026fad6cfb0a8b55eb1b0"
+ dependencies:
+ chalk "1.1.3"
+ cheerio "0.22.0"
+ ejs "2.5.6"
+ glob "7.1.1"
+ html-wiring "1.2.0"
+ insight "0.8.4"
+ jhipster-core "1.2.8"
+ js-yaml "3.8.1"
+ lodash "4.17.4"
+ mkdirp "0.5.1"
+ pluralize "3.1.0"
+ randexp "0.4.4"
+ semver "5.3.0"
+ shelljs "0.7.6"
+ yeoman-generator "0.24.1"
+ yo "1.8.5"
+
+get-stdin@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
+
+getpass@^0.1.1:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
+ dependencies:
+ assert-plus "^1.0.0"
+
+gh-got@^2.2.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/gh-got/-/gh-got-2.4.0.tgz#aa51418911ca5e4f92437114cd1209383a4aa019"
+ dependencies:
+ got "^5.2.0"
+ object-assign "^4.0.1"
+ pinkie-promise "^2.0.0"
+
+github-username@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/github-username/-/github-username-2.1.0.tgz#200e5a104af42ba08a54096c708d4b6ec2fa256b"
+ dependencies:
+ gh-got "^2.2.0"
+ meow "^3.5.0"
+
+glob@7.1.1, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.0.2"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+glob@^6.0.1:
+ version "6.0.4"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22"
+ dependencies:
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "2 || 3"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+globby@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-4.1.0.tgz#080f54549ec1b82a6c60e631fc82e1211dbe95f8"
+ dependencies:
+ array-union "^1.0.1"
+ arrify "^1.0.0"
+ glob "^6.0.1"
+ object-assign "^4.0.1"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+
+got@^5.0.0, got@^5.2.0:
+ version "5.7.1"
+ resolved "https://registry.yarnpkg.com/got/-/got-5.7.1.tgz#5f81635a61e4a6589f180569ea4e381680a51f35"
+ dependencies:
+ create-error-class "^3.0.1"
+ duplexer2 "^0.1.4"
+ is-redirect "^1.0.0"
+ is-retry-allowed "^1.0.0"
+ is-stream "^1.0.0"
+ lowercase-keys "^1.0.0"
+ node-status-codes "^1.0.0"
+ object-assign "^4.0.1"
+ parse-json "^2.1.0"
+ pinkie-promise "^2.0.0"
+ read-all-stream "^3.0.0"
+ readable-stream "^2.0.5"
+ timed-out "^3.0.0"
+ unzip-response "^1.0.2"
+ url-parse-lax "^1.0.0"
+
+graceful-fs@^4.1.11, graceful-fs@^4.1.2:
+ version "4.1.11"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
+
+grouped-queue@^0.3.0:
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/grouped-queue/-/grouped-queue-0.3.3.tgz#c167d2a5319c5a0e0964ef6a25b7c2df8996c85c"
+ dependencies:
+ lodash "^4.17.2"
+
+gruntfile-editor@^1.0.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/gruntfile-editor/-/gruntfile-editor-1.2.1.tgz#366fc1f93cbf045813e1448aef1da9f18289d5eb"
+ dependencies:
+ ast-query "^2.0.0"
+ lodash "^4.6.1"
+
+har-schema@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
+
+har-validator@~4.2.1:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
+ dependencies:
+ ajv "^4.9.1"
+ har-schema "^1.0.5"
+
+has-ansi@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
+ dependencies:
+ ansi-regex "^2.0.0"
+
+has-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
+
+has-unicode@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
+
+hawk@~3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
+ dependencies:
+ boom "2.x.x"
+ cryptiles "2.x.x"
+ hoek "2.x.x"
+ sntp "1.x.x"
+
+hoek@2.x.x:
+ version "2.16.3"
+ resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
+
+hosted-git-info@^2.1.4:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.4.2.tgz#0076b9f46a270506ddbaaea56496897460612a67"
+
+html-wiring@1.2.0, html-wiring@^1.0.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/html-wiring/-/html-wiring-1.2.0.tgz#c5f90a776e0a27241dc6df9022c37186d0270f9e"
+ dependencies:
+ cheerio "^0.19.0"
+ detect-newline "^1.0.3"
+
+htmlparser2@^3.9.1:
+ version "3.9.2"
+ resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338"
+ dependencies:
+ domelementtype "^1.3.0"
+ domhandler "^2.3.0"
+ domutils "^1.5.1"
+ entities "^1.1.1"
+ inherits "^2.0.1"
+ readable-stream "^2.0.2"
+
+htmlparser2@~3.8.1:
+ version "3.8.3"
+ resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.8.3.tgz#996c28b191516a8be86501a7d79757e5c70c1068"
+ dependencies:
+ domelementtype "1"
+ domhandler "2.3"
+ domutils "1.5"
+ entities "1.0"
+ readable-stream "1.1"
+
+http-signature@~1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
+ dependencies:
+ assert-plus "^0.2.0"
+ jsprim "^1.2.2"
+ sshpk "^1.7.0"
+
+humanize-string@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/humanize-string/-/humanize-string-1.0.1.tgz#fce2d6c545efc25dea1f23235182c98da0180b42"
+ dependencies:
+ decamelize "^1.0.0"
+
+imurmurhash@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
+
+indent-string@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
+ dependencies:
+ repeating "^2.0.0"
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+
+inherits@2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
+
+ini@^1.2.0, ini@^1.3.4, ini@~1.3.0:
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e"
+
+inquirer@^0.10.0:
+ version "0.10.1"
+ resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.10.1.tgz#ea25e4ce69ca145e05c99e46dcfec05e4012594a"
+ dependencies:
+ ansi-escapes "^1.1.0"
+ ansi-regex "^2.0.0"
+ chalk "^1.0.0"
+ cli-cursor "^1.0.1"
+ cli-width "^1.0.1"
+ figures "^1.3.5"
+ lodash "^3.3.1"
+ readline2 "^1.0.1"
+ run-async "^0.1.0"
+ rx-lite "^3.1.2"
+ strip-ansi "^3.0.0"
+ through "^2.3.6"
+
+inquirer@^0.11.0:
+ version "0.11.4"
+ resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.11.4.tgz#81e3374e8361beaff2d97016206d359d0b32fa4d"
+ dependencies:
+ ansi-escapes "^1.1.0"
+ ansi-regex "^2.0.0"
+ chalk "^1.0.0"
+ cli-cursor "^1.0.1"
+ cli-width "^1.0.1"
+ figures "^1.3.5"
+ lodash "^3.3.1"
+ readline2 "^1.0.1"
+ run-async "^0.1.0"
+ rx-lite "^3.1.2"
+ string-width "^1.0.1"
+ strip-ansi "^3.0.0"
+ through "^2.3.6"
+
+inquirer@^1.0.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-1.2.3.tgz#4dec6f32f37ef7bb0b2ed3f1d1a5c3f545074918"
+ dependencies:
+ ansi-escapes "^1.1.0"
+ chalk "^1.0.0"
+ cli-cursor "^1.0.1"
+ cli-width "^2.0.0"
+ external-editor "^1.1.0"
+ figures "^1.3.5"
+ lodash "^4.3.0"
+ mute-stream "0.0.6"
+ pinkie-promise "^2.0.0"
+ run-async "^2.2.0"
+ rx "^4.1.0"
+ string-width "^1.0.1"
+ strip-ansi "^3.0.0"
+ through "^2.3.6"
+
+insight@0.8.4:
+ version "0.8.4"
+ resolved "https://registry.yarnpkg.com/insight/-/insight-0.8.4.tgz#671caf65b47c9fe8c3d1b3206cf45bb211b75884"
+ dependencies:
+ async "^1.4.2"
+ chalk "^1.0.0"
+ configstore "^1.0.0"
+ inquirer "^0.10.0"
+ lodash.debounce "^3.0.1"
+ object-assign "^4.0.1"
+ os-name "^1.0.0"
+ request "^2.74.0"
+ tough-cookie "^2.0.0"
+ uuid "^3.0.0"
+
+insight@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/insight/-/insight-0.7.0.tgz#061f9189835bd38a97a60c2b76ea0c6b30099ff6"
+ dependencies:
+ async "^1.4.2"
+ chalk "^1.0.0"
+ configstore "^1.0.0"
+ inquirer "^0.10.0"
+ lodash.debounce "^3.0.1"
+ object-assign "^4.0.1"
+ os-name "^1.0.0"
+ request "^2.40.0"
+ tough-cookie "^2.0.0"
+
+interpret@^1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90"
+
+is-arrayish@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
+
+is-builtin-module@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"
+ dependencies:
+ builtin-modules "^1.0.0"
+
+is-docker@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-1.1.0.tgz#f04374d4eee5310e9a8e113bf1495411e46176a1"
+
+is-finite@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
+ dependencies:
+ number-is-nan "^1.0.0"
+
+is-fullwidth-code-point@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
+ dependencies:
+ number-is-nan "^1.0.0"
+
+is-npm@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4"
+
+is-obj@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
+
+is-promise@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
+
+is-redirect@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24"
+
+is-regexp@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
+
+is-retry-allowed@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34"
+
+is-root@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-root/-/is-root-1.0.0.tgz#07b6c233bc394cd9d02ba15c966bd6660d6342d5"
+
+is-stream@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
+
+is-supported-regexp-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.0.tgz#8b520c85fae7a253382d4b02652e045576e13bb8"
+
+is-typedarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
+
+is-utf8@^0.2.0:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
+
+isarray@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
+
+isarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+
+isstream@~0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
+
+istextorbinary@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-2.1.0.tgz#dbed2a6f51be2f7475b68f89465811141b758874"
+ dependencies:
+ binaryextensions "1 || 2"
+ editions "^1.1.1"
+ textextensions "1 || 2"
+
+jhipster-core@1.2.8:
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/jhipster-core/-/jhipster-core-1.2.8.tgz#2211a468761a7132c5ddc7f101400e2fc57d5be4"
+ dependencies:
+ lodash "4.17.4"
+
+jodid25519@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967"
+ dependencies:
+ jsbn "~0.1.0"
+
+js-yaml@3.8.1:
+ version "3.8.1"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.1.tgz#782ba50200be7b9e5a8537001b7804db3ad02628"
+ dependencies:
+ argparse "^1.0.7"
+ esprima "^3.1.1"
+
+jsbn@~0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
+
+json-schema@0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
+
+json-stable-stringify@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
+ dependencies:
+ jsonify "~0.0.0"
+
+json-stringify-safe@~5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
+
+jsonify@~0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
+
+jsprim@^1.2.2:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.0.tgz#a3b87e40298d8c380552d8cc7628a0bb95a22918"
+ dependencies:
+ assert-plus "1.0.0"
+ extsprintf "1.0.2"
+ json-schema "0.2.3"
+ verror "1.3.6"
+
+latest-version@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-2.0.0.tgz#56f8d6139620847b8017f8f1f4d78e211324168b"
+ dependencies:
+ package-json "^2.0.0"
+
+levn@~0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
+ dependencies:
+ prelude-ls "~1.1.2"
+ type-check "~0.3.2"
+
+load-json-file@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
+ dependencies:
+ graceful-fs "^4.1.2"
+ parse-json "^2.2.0"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+ strip-bom "^2.0.0"
+
+lodash._getnative@^3.0.0:
+ version "3.9.1"
+ resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
+
+lodash.assignin@^4.0.9:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2"
+
+lodash.bind@^4.1.4:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35"
+
+lodash.debounce@^3.0.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-3.1.1.tgz#812211c378a94cc29d5aa4e3346cf0bfce3a7df5"
+ dependencies:
+ lodash._getnative "^3.0.0"
+
+lodash.defaults@^4.0.1:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
+
+lodash.filter@^4.4.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace"
+
+lodash.flatten@^4.2.0:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
+
+lodash.foreach@^4.3.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53"
+
+lodash.map@^4.4.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3"
+
+lodash.merge@^4.4.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.0.tgz#69884ba144ac33fe699737a6086deffadd0f89c5"
+
+lodash.pad@^4.1.0:
+ version "4.5.1"
+ resolved "https://registry.yarnpkg.com/lodash.pad/-/lodash.pad-4.5.1.tgz#4330949a833a7c8da22cc20f6a26c4d59debba70"
+
+lodash.padend@^4.1.0:
+ version "4.6.1"
+ resolved "https://registry.yarnpkg.com/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e"
+
+lodash.padstart@^4.1.0:
+ version "4.6.1"
+ resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b"
+
+lodash.pick@^4.2.1:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
+
+lodash.reduce@^4.4.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b"
+
+lodash.reject@^4.4.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415"
+
+lodash.some@^4.4.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d"
+
+lodash@4.17.4, lodash@^4.11.1, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.3.0, lodash@^4.6.1:
+ version "4.17.4"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
+
+lodash@^3.2.0, lodash@^3.3.1:
+ version "3.10.1"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
+
+log-symbols@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
+ dependencies:
+ chalk "^1.0.0"
+
+lolex@1.3.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31"
+
+loud-rejection@^1.0.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
+ dependencies:
+ currently-unhandled "^0.4.1"
+ signal-exit "^3.0.0"
+
+lowercase-keys@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306"
+
+lru-cache@^4.0.1:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e"
+ dependencies:
+ pseudomap "^1.0.1"
+ yallist "^2.0.0"
+
+map-obj@^1.0.0, map-obj@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
+
+mem-fs-editor@^2.0.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/mem-fs-editor/-/mem-fs-editor-2.3.0.tgz#42a0ae1f55e76fd03f09e7c7b15b6307bdf5cb13"
+ dependencies:
+ commondir "^1.0.1"
+ deep-extend "^0.4.0"
+ ejs "^2.3.1"
+ glob "^7.0.3"
+ globby "^4.0.0"
+ mkdirp "^0.5.0"
+ multimatch "^2.0.0"
+ rimraf "^2.2.8"
+ through2 "^2.0.0"
+ vinyl "^1.1.0"
+
+mem-fs@^1.1.0:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/mem-fs/-/mem-fs-1.1.3.tgz#b8ae8d2e3fcb6f5d3f9165c12d4551a065d989cc"
+ dependencies:
+ through2 "^2.0.0"
+ vinyl "^1.1.0"
+ vinyl-file "^2.0.0"
+
+meow@^3.0.0, meow@^3.3.0, meow@^3.5.0:
+ version "3.7.0"
+ resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
+ dependencies:
+ camelcase-keys "^2.0.0"
+ decamelize "^1.1.2"
+ loud-rejection "^1.0.0"
+ map-obj "^1.0.1"
+ minimist "^1.1.3"
+ normalize-package-data "^2.3.4"
+ object-assign "^4.0.1"
+ read-pkg-up "^1.0.1"
+ redent "^1.0.0"
+ trim-newlines "^1.0.0"
+
+mime-db@~1.27.0:
+ version "1.27.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1"
+
+mime-types@^2.1.12, mime-types@~2.1.7:
+ version "2.1.15"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed"
+ dependencies:
+ mime-db "~1.27.0"
+
+"minimatch@2 || 3", minimatch@3.0.x, minimatch@^3.0.0, minimatch@^3.0.2:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774"
+ dependencies:
+ brace-expansion "^1.0.0"
+
+minimist@0.0.8:
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
+
+minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
+
+mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1:
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
+ dependencies:
+ minimist "0.0.8"
+
+ms@0.7.3:
+ version "0.7.3"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff"
+
+multimatch@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b"
+ dependencies:
+ array-differ "^1.0.0"
+ array-union "^1.0.1"
+ arrify "^1.0.0"
+ minimatch "^3.0.0"
+
+mute-stream@0.0.5:
+ version "0.0.5"
+ resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0"
+
+mute-stream@0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.6.tgz#48962b19e169fd1dfc240b3f1e7317627bbc47db"
+
+node-status-codes@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/node-status-codes/-/node-status-codes-1.0.0.tgz#5ae5541d024645d32a58fcddc9ceecea7ae3ac2f"
+
+nopt@^3.0.0, nopt@~3.0.1:
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
+ dependencies:
+ abbrev "1"
+
+normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.8.tgz#d819eda2a9dedbd1ffa563ea4071d936782295bb"
+ dependencies:
+ hosted-git-info "^2.1.4"
+ is-builtin-module "^1.0.0"
+ semver "2 || 3 || 4 || 5"
+ validate-npm-package-license "^3.0.1"
+
+npm-keyword@^4.1.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/npm-keyword/-/npm-keyword-4.2.0.tgz#98ffebfdbb1336f27ef5fe1baca0dcacd0acf6c0"
+ dependencies:
+ got "^5.0.0"
+ object-assign "^4.0.1"
+ pinkie-promise "^2.0.0"
+ registry-url "^3.0.3"
+
+npmconf@^2.1.1:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/npmconf/-/npmconf-2.1.2.tgz#66606a4a736f1e77a059aa071a79c94ab781853a"
+ dependencies:
+ config-chain "~1.1.8"
+ inherits "~2.0.0"
+ ini "^1.2.0"
+ mkdirp "^0.5.0"
+ nopt "~3.0.1"
+ once "~1.3.0"
+ osenv "^0.1.0"
+ semver "2 || 3 || 4"
+ uid-number "0.0.5"
+
+npmlog@^2.0.3:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-2.0.4.tgz#98b52530f2514ca90d09ec5b22c8846722375692"
+ dependencies:
+ ansi "~0.3.1"
+ are-we-there-yet "~1.1.2"
+ gauge "~1.2.5"
+
+nth-check@~1.0.0, nth-check@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4"
+ dependencies:
+ boolbase "~1.0.0"
+
+number-is-nan@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
+
+oauth-sign@~0.8.1:
+ version "0.8.2"
+ resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
+
+object-assign@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-2.1.1.tgz#43c36e5d569ff8e4816c4efa8be02d26967c18aa"
+
+object-assign@^4.0.1, object-assign@^4.1.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
+
+object-values@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/object-values/-/object-values-1.0.0.tgz#72af839630119e5b98c3b02bb8c27e3237158105"
+
+once@^1.3.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ dependencies:
+ wrappy "1"
+
+once@~1.3.0:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20"
+ dependencies:
+ wrappy "1"
+
+onetime@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789"
+
+opn@^3.0.2:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/opn/-/opn-3.0.3.tgz#b6d99e7399f78d65c3baaffef1fb288e9b85243a"
+ dependencies:
+ object-assign "^4.0.1"
+
+optionator@^0.8.1:
+ version "0.8.2"
+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
+ dependencies:
+ deep-is "~0.1.3"
+ fast-levenshtein "~2.0.4"
+ levn "~0.3.0"
+ prelude-ls "~1.1.2"
+ type-check "~0.3.2"
+ wordwrap "~1.0.0"
+
+os-homedir@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
+
+os-name@^1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/os-name/-/os-name-1.0.3.tgz#1b379f64835af7c5a7f498b357cb95215c159edf"
+ dependencies:
+ osx-release "^1.0.0"
+ win-release "^1.0.0"
+
+os-shim@^0.1.2:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/os-shim/-/os-shim-0.1.3.tgz#6b62c3791cf7909ea35ed46e17658bb417cb3917"
+
+os-tmpdir@^1.0.0, os-tmpdir@~1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
+
+osenv@^0.1.0:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644"
+ dependencies:
+ os-homedir "^1.0.0"
+ os-tmpdir "^1.0.0"
+
+osx-release@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/osx-release/-/osx-release-1.1.0.tgz#f217911a28136949af1bf9308b241e2737d3cd6c"
+ dependencies:
+ minimist "^1.1.0"
+
+package-json@^2.0.0, package-json@^2.1.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/package-json/-/package-json-2.4.0.tgz#0d15bd67d1cbbddbb2ca222ff2edb86bcb31a8bb"
+ dependencies:
+ got "^5.0.0"
+ registry-auth-token "^3.0.1"
+ registry-url "^3.0.3"
+ semver "^5.1.0"
+
+pad-component@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/pad-component/-/pad-component-0.0.1.tgz#ad1f22ce1bf0fdc0d6ddd908af17f351a404b8ac"
+
+parse-help@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/parse-help/-/parse-help-0.1.1.tgz#2f4df942e77a5581bba9967c0c3f48e4c66d7dda"
+ dependencies:
+ execall "^1.0.0"
+
+parse-json@^2.1.0, parse-json@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
+ dependencies:
+ error-ex "^1.2.0"
+
+path-exists@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
+ dependencies:
+ pinkie-promise "^2.0.0"
+
+path-is-absolute@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+
+path-parse@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1"
+
+path-type@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
+ dependencies:
+ graceful-fs "^4.1.2"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+
+performance-now@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
+
+pify@^2.0.0, pify@^2.2.0, pify@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+
+pinkie-promise@^2.0.0, pinkie-promise@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
+ dependencies:
+ pinkie "^2.0.0"
+
+pinkie@^2.0.0:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
+
+pluralize@3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-3.1.0.tgz#84213d0a12356069daa84060c559242633161368"
+
+prelude-ls@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
+
+prepend-http@^1.0.1:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
+
+pretty-bytes@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-3.0.1.tgz#27d0008d778063a0b4811bb35c79f1bd5d5fbccf"
+ dependencies:
+ number-is-nan "^1.0.0"
+
+process-nextick-args@~1.0.6:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
+
+proto-list@~1.2.1:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
+
+pseudomap@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
+
+punycode@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
+
+qs@~6.4.0:
+ version "6.4.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
+
+randexp@0.4.4:
+ version "0.4.4"
+ resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.4.tgz#ba68265f4a9f9e85f5814d34e160291f939f168e"
+ dependencies:
+ discontinuous-range "1.0.0"
+ ret "~0.1.10"
+
+rc@^1.0.1, rc@^1.1.6:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95"
+ dependencies:
+ deep-extend "~0.4.0"
+ ini "~1.3.0"
+ minimist "^1.2.0"
+ strip-json-comments "~2.0.1"
+
+read-all-stream@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/read-all-stream/-/read-all-stream-3.1.0.tgz#35c3e177f2078ef789ee4bfafa4373074eaef4fa"
+ dependencies:
+ pinkie-promise "^2.0.0"
+ readable-stream "^2.0.0"
+
+read-chunk@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/read-chunk/-/read-chunk-1.0.1.tgz#5f68cab307e663f19993527d9b589cace4661194"
+
+read-pkg-up@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
+ dependencies:
+ find-up "^1.0.0"
+ read-pkg "^1.0.0"
+
+read-pkg@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
+ dependencies:
+ load-json-file "^1.0.0"
+ normalize-package-data "^2.3.2"
+ path-type "^1.0.0"
+
+readable-stream@1.1:
+ version "1.1.13"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e"
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.1"
+ isarray "0.0.1"
+ string_decoder "~0.10.x"
+
+readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2:
+ version "2.2.9"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.9.tgz#cf78ec6f4a6d1eb43d26488cac97f042e74b7fc8"
+ dependencies:
+ buffer-shims "~1.0.0"
+ core-util-is "~1.0.0"
+ inherits "~2.0.1"
+ isarray "~1.0.0"
+ process-nextick-args "~1.0.6"
+ string_decoder "~1.0.0"
+ util-deprecate "~1.0.1"
+
+readline2@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35"
+ dependencies:
+ code-point-at "^1.0.0"
+ is-fullwidth-code-point "^1.0.0"
+ mute-stream "0.0.5"
+
+rechoir@^0.6.2:
+ version "0.6.2"
+ resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
+ dependencies:
+ resolve "^1.1.6"
+
+redent@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
+ dependencies:
+ indent-string "^2.1.0"
+ strip-indent "^1.0.1"
+
+registry-auth-token@^3.0.1:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.1.tgz#fb0d3289ee0d9ada2cbb52af5dfe66cb070d3006"
+ dependencies:
+ rc "^1.1.6"
+ safe-buffer "^5.0.1"
+
+registry-url@^3.0.3:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942"
+ dependencies:
+ rc "^1.0.1"
+
+repeating@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
+ dependencies:
+ is-finite "^1.0.0"
+
+replace-ext@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924"
+
+request@^2.40.0, request@^2.74.0:
+ version "2.81.0"
+ resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
+ dependencies:
+ aws-sign2 "~0.6.0"
+ aws4 "^1.2.1"
+ caseless "~0.12.0"
+ combined-stream "~1.0.5"
+ extend "~3.0.0"
+ forever-agent "~0.6.1"
+ form-data "~2.1.1"
+ har-validator "~4.2.1"
+ hawk "~3.1.3"
+ http-signature "~1.1.0"
+ is-typedarray "~1.0.0"
+ isstream "~0.1.2"
+ json-stringify-safe "~5.0.1"
+ mime-types "~2.1.7"
+ oauth-sign "~0.8.1"
+ performance-now "^0.2.0"
+ qs "~6.4.0"
+ safe-buffer "^5.0.1"
+ stringstream "~0.0.4"
+ tough-cookie "~2.3.0"
+ tunnel-agent "^0.6.0"
+ uuid "^3.0.0"
+
+resolve@^1.1.6:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5"
+ dependencies:
+ path-parse "^1.0.5"
+
+restore-cursor@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
+ dependencies:
+ exit-hook "^1.0.0"
+ onetime "^1.0.0"
+
+ret@~0.1.10:
+ version "0.1.14"
+ resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.14.tgz#58c636837b12e161f8a380cf081c6a230fd1664e"
+
+rimraf@^2.2.0, rimraf@^2.2.8, rimraf@^2.4.4:
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d"
+ dependencies:
+ glob "^7.0.5"
+
+root-check@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/root-check/-/root-check-1.0.0.tgz#c52a794bf0db9fad567536e41898f0c9e0a86697"
+ dependencies:
+ downgrade-root "^1.0.0"
+ sudo-block "^1.1.0"
+
+run-async@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389"
+ dependencies:
+ once "^1.3.0"
+
+run-async@^2.0.0, run-async@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
+ dependencies:
+ is-promise "^2.1.0"
+
+rx-lite@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
+
+rx@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782"
+
+safe-buffer@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7"
+
+samsam@1.1.2, samsam@~1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567"
+
+semver-diff@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36"
+ dependencies:
+ semver "^5.0.3"
+
+semver-regex@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-1.0.0.tgz#92a4969065f9c70c694753d55248fc68f8f652c9"
+
+semver-truncate@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/semver-truncate/-/semver-truncate-1.1.2.tgz#57f41de69707a62709a7e0104ba2117109ea47e8"
+ dependencies:
+ semver "^5.3.0"
+
+"semver@2 || 3 || 4", semver@^4.0.3:
+ version "4.3.6"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da"
+
+"semver@2 || 3 || 4 || 5", semver@5.3.0, semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
+
+set-immediate-shim@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
+
+shelljs@0.7.6, shelljs@^0.7.0:
+ version "0.7.6"
+ resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.6.tgz#379cccfb56b91c8601e4793356eb5382924de9ad"
+ dependencies:
+ glob "^7.0.0"
+ interpret "^1.0.0"
+ rechoir "^0.6.2"
+
+signal-exit@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
+
+sinon@^1.17.2:
+ version "1.17.7"
+ resolved "https://registry.yarnpkg.com/sinon/-/sinon-1.17.7.tgz#4542a4f49ba0c45c05eb2e9dd9d203e2b8efe0bf"
+ dependencies:
+ formatio "1.1.1"
+ lolex "1.3.2"
+ samsam "1.1.2"
+ util ">=0.10.3 <1"
+
+slide@^1.1.5:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707"
+
+sntp@1.x.x:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198"
+ dependencies:
+ hoek "2.x.x"
+
+sort-on@^1.0.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/sort-on/-/sort-on-1.3.0.tgz#0dfd5b364b23df7f2acd86985daeb889e1a7c840"
+ dependencies:
+ arrify "^1.0.0"
+ dot-prop "^2.0.0"
+
+source-map@~0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d"
+ dependencies:
+ amdefine ">=0.0.4"
+
+spawn-sync@^1.0.15:
+ version "1.0.15"
+ resolved "https://registry.yarnpkg.com/spawn-sync/-/spawn-sync-1.0.15.tgz#b00799557eb7fb0c8376c29d44e8a1ea67e57476"
+ dependencies:
+ concat-stream "^1.4.7"
+ os-shim "^0.1.2"
+
+spdx-correct@~1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40"
+ dependencies:
+ spdx-license-ids "^1.0.2"
+
+spdx-expression-parse@~1.0.0:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c"
+
+spdx-license-ids@^1.0.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57"
+
+sprintf-js@^1.0.3, sprintf-js@~1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+
+sshpk@^1.7.0:
+ version "1.13.0"
+ resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.0.tgz#ff2a3e4fd04497555fed97b39a0fd82fafb3a33c"
+ dependencies:
+ asn1 "~0.2.3"
+ assert-plus "^1.0.0"
+ dashdash "^1.12.0"
+ getpass "^0.1.1"
+ optionalDependencies:
+ bcrypt-pbkdf "^1.0.0"
+ ecc-jsbn "~0.1.1"
+ jodid25519 "^1.0.0"
+ jsbn "~0.1.0"
+ tweetnacl "~0.14.0"
+
+string-length@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/string-length/-/string-length-1.0.1.tgz#56970fb1c38558e9e70b728bf3de269ac45adfac"
+ dependencies:
+ strip-ansi "^3.0.0"
+
+string-template@~0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add"
+
+string-width@^1.0.0, string-width@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
+ dependencies:
+ code-point-at "^1.0.0"
+ is-fullwidth-code-point "^1.0.0"
+ strip-ansi "^3.0.0"
+
+string_decoder@~0.10.x:
+ version "0.10.31"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
+
+string_decoder@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.0.tgz#f06f41157b664d86069f84bdbdc9b0d8ab281667"
+ dependencies:
+ buffer-shims "~1.0.0"
+
+stringstream@~0.0.4:
+ version "0.0.5"
+ resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
+
+strip-ansi@^3.0.0, strip-ansi@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+ dependencies:
+ ansi-regex "^2.0.0"
+
+strip-bom-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz#f87db5ef2613f6968aa545abfe1ec728b6a829ca"
+ dependencies:
+ first-chunk-stream "^2.0.0"
+ strip-bom "^2.0.0"
+
+strip-bom@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
+ dependencies:
+ is-utf8 "^0.2.0"
+
+strip-indent@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
+ dependencies:
+ get-stdin "^4.0.1"
+
+strip-json-comments@~2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
+
+sudo-block@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/sudo-block/-/sudo-block-1.2.0.tgz#cc539bf8191624d4f507d83eeb45b4cea27f3463"
+ dependencies:
+ chalk "^1.0.0"
+ is-docker "^1.0.0"
+ is-root "^1.0.0"
+
+supports-color@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+
+supports-color@^3.1.2:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
+ dependencies:
+ has-flag "^1.0.0"
+
+tabtab@^1.3.0:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/tabtab/-/tabtab-1.3.2.tgz#bb9c2ca6324f659fde7634c2caf3c096e1187ca7"
+ dependencies:
+ debug "^2.2.0"
+ inquirer "^1.0.2"
+ minimist "^1.2.0"
+ mkdirp "^0.5.1"
+ npmlog "^2.0.3"
+ object-assign "^4.1.0"
+
+taketalk@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/taketalk/-/taketalk-1.0.0.tgz#b4d4f0deed206ae7df775b129ea2ca6de52f26dd"
+ dependencies:
+ get-stdin "^4.0.1"
+ minimist "^1.1.0"
+
+text-table@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+
+"textextensions@1 || 2":
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-2.1.0.tgz#1be0dc2a0dc244d44be8a09af6a85afb93c4dbc3"
+
+through2@^2.0.0:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be"
+ dependencies:
+ readable-stream "^2.1.5"
+ xtend "~4.0.1"
+
+through@^2.3.6:
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+
+timed-out@^3.0.0:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-3.1.3.tgz#95860bfcc5c76c277f8f8326fd0f5b2e20eba217"
+
+titleize@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/titleize/-/titleize-1.0.0.tgz#7d350722061830ba6617631e0cfd3ea08398d95a"
+
+tmp@^0.0.29:
+ version "0.0.29"
+ resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.29.tgz#f25125ff0dd9da3ccb0c2dd371ee1288bb9128c0"
+ dependencies:
+ os-tmpdir "~1.0.1"
+
+tough-cookie@^2.0.0, tough-cookie@~2.3.0:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a"
+ dependencies:
+ punycode "^1.4.1"
+
+traverse@^0.6.6:
+ version "0.6.6"
+ resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137"
+
+trim-newlines@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
+
+tunnel-agent@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
+ dependencies:
+ safe-buffer "^5.0.1"
+
+tweetnacl@^0.14.3, tweetnacl@~0.14.0:
+ version "0.14.5"
+ resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
+
+twig@^0.8.2:
+ version "0.8.9"
+ resolved "https://registry.yarnpkg.com/twig/-/twig-0.8.9.tgz#b1594f002b684e5f029de3e54e87bec4f084b6c2"
+ dependencies:
+ minimatch "3.0.x"
+ walk "2.3.x"
+
+type-check@~0.3.2:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
+ dependencies:
+ prelude-ls "~1.1.2"
+
+typedarray@^0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
+
+uid-number@0.0.5:
+ version "0.0.5"
+ resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.5.tgz#5a3db23ef5dbd55b81fce0ec9a2ac6fccdebb81e"
+
+underscore.string@^3.0.3:
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.3.4.tgz#2c2a3f9f83e64762fdc45e6ceac65142864213db"
+ dependencies:
+ sprintf-js "^1.0.3"
+ util-deprecate "^1.0.2"
+
+untildify@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/untildify/-/untildify-2.1.0.tgz#17eb2807987f76952e9c0485fc311d06a826a2e0"
+ dependencies:
+ os-homedir "^1.0.0"
+
+unzip-response@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-1.0.2.tgz#b984f0877fc0a89c2c773cc1ef7b5b232b5b06fe"
+
+update-notifier@^0.6.0:
+ version "0.6.3"
+ resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-0.6.3.tgz#776dec8daa13e962a341e8a1d98354306b67ae08"
+ dependencies:
+ boxen "^0.3.1"
+ chalk "^1.0.0"
+ configstore "^2.0.0"
+ is-npm "^1.0.0"
+ latest-version "^2.0.0"
+ semver-diff "^2.0.0"
+
+url-parse-lax@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73"
+ dependencies:
+ prepend-http "^1.0.1"
+
+user-home@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f"
+ dependencies:
+ os-homedir "^1.0.0"
+
+util-deprecate@^1.0.2, util-deprecate@~1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+
+"util@>=0.10.3 <1":
+ version "0.10.3"
+ resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
+ dependencies:
+ inherits "2.0.1"
+
+uuid@^2.0.1:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a"
+
+uuid@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1"
+
+validate-npm-package-license@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"
+ dependencies:
+ spdx-correct "~1.0.0"
+ spdx-expression-parse "~1.0.0"
+
+verror@1.3.6:
+ version "1.3.6"
+ resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c"
+ dependencies:
+ extsprintf "1.0.2"
+
+vinyl-file@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/vinyl-file/-/vinyl-file-2.0.0.tgz#a7ebf5ffbefda1b7d18d140fcb07b223efb6751a"
+ dependencies:
+ graceful-fs "^4.1.2"
+ pify "^2.3.0"
+ pinkie-promise "^2.0.0"
+ strip-bom "^2.0.0"
+ strip-bom-stream "^2.0.0"
+ vinyl "^1.1.0"
+
+vinyl@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884"
+ dependencies:
+ clone "^1.0.0"
+ clone-stats "^0.0.1"
+ replace-ext "0.0.1"
+
+walk@2.3.x:
+ version "2.3.9"
+ resolved "https://registry.yarnpkg.com/walk/-/walk-2.3.9.tgz#31b4db6678f2ae01c39ea9fb8725a9031e558a7b"
+ dependencies:
+ foreachasync "^3.0.0"
+
+which@^1.2.9:
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5"
+ dependencies:
+ isexe "^2.0.0"
+
+widest-line@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-1.0.0.tgz#0c09c85c2a94683d0d7eaf8ee097d564bf0e105c"
+ dependencies:
+ string-width "^1.0.1"
+
+win-release@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/win-release/-/win-release-1.1.1.tgz#5fa55e02be7ca934edfc12665632e849b72e5209"
+ dependencies:
+ semver "^5.0.1"
+
+wordwrap@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
+
+wrap-ansi@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
+ dependencies:
+ string-width "^1.0.1"
+ strip-ansi "^3.0.1"
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+
+write-file-atomic@^1.1.2:
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f"
+ dependencies:
+ graceful-fs "^4.1.11"
+ imurmurhash "^0.1.4"
+ slide "^1.1.5"
+
+xdg-basedir@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-2.0.0.tgz#edbc903cc385fc04523d966a335504b5504d1bd2"
+ dependencies:
+ os-homedir "^1.0.0"
+
+xtend@~4.0.0, xtend@~4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
+
+yallist@^2.0.0:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
+
+yeoman-assert@^2.0.0:
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/yeoman-assert/-/yeoman-assert-2.2.3.tgz#a5682a83632c50ac0ee84173a5a10fd6f3206474"
+
+yeoman-character@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/yeoman-character/-/yeoman-character-1.1.0.tgz#90d4b5beaf92759086177015b2fdfa2e0684d7c7"
+ dependencies:
+ supports-color "^3.1.2"
+
+yeoman-doctor@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/yeoman-doctor/-/yeoman-doctor-2.1.0.tgz#94ab784896a64f53a9fac452d5e9133e2750a236"
+ dependencies:
+ bin-version-check "^2.1.0"
+ chalk "^1.0.0"
+ each-async "^1.1.1"
+ log-symbols "^1.0.1"
+ object-values "^1.0.0"
+ semver "^5.0.3"
+ twig "^0.8.2"
+ user-home "^2.0.0"
+
+yeoman-environment@^1.1.0, yeoman-environment@^1.5.2, yeoman-environment@^1.6.1:
+ version "1.6.6"
+ resolved "https://registry.yarnpkg.com/yeoman-environment/-/yeoman-environment-1.6.6.tgz#cd85fa67d156060e440d7807d7ef7cf0d2d1d671"
+ dependencies:
+ chalk "^1.0.0"
+ debug "^2.0.0"
+ diff "^2.1.2"
+ escape-string-regexp "^1.0.2"
+ globby "^4.0.0"
+ grouped-queue "^0.3.0"
+ inquirer "^1.0.2"
+ lodash "^4.11.1"
+ log-symbols "^1.0.1"
+ mem-fs "^1.1.0"
+ text-table "^0.2.0"
+ untildify "^2.0.0"
+
+yeoman-generator@0.24.1, yeoman-generator@^0.24.1:
+ version "0.24.1"
+ resolved "https://registry.yarnpkg.com/yeoman-generator/-/yeoman-generator-0.24.1.tgz#1ca74429d9c5c95db0b22859ec180a2599bc1f8e"
+ dependencies:
+ async "^2.0.0"
+ chalk "^1.0.0"
+ class-extend "^0.1.0"
+ cli-table "^0.3.1"
+ cross-spawn "^4.0.0"
+ dargs "^4.0.0"
+ dateformat "^1.0.11"
+ debug "^2.1.0"
+ detect-conflict "^1.0.0"
+ error "^7.0.2"
+ find-up "^1.0.0"
+ github-username "^2.0.0"
+ glob "^7.0.3"
+ gruntfile-editor "^1.0.0"
+ html-wiring "^1.0.0"
+ istextorbinary "^2.1.0"
+ lodash "^4.11.1"
+ mem-fs-editor "^2.0.0"
+ mkdirp "^0.5.0"
+ nopt "^3.0.0"
+ path-exists "^2.0.0"
+ path-is-absolute "^1.0.0"
+ pretty-bytes "^3.0.1"
+ read-chunk "^1.0.0"
+ read-pkg-up "^1.0.1"
+ rimraf "^2.2.0"
+ run-async "^2.0.0"
+ shelljs "^0.7.0"
+ text-table "^0.2.0"
+ through2 "^2.0.0"
+ underscore.string "^3.0.3"
+ user-home "^2.0.0"
+ yeoman-assert "^2.0.0"
+ yeoman-environment "^1.1.0"
+ yeoman-test "^1.0.0"
+ yeoman-welcome "^1.0.0"
+
+yeoman-test@^1.0.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/yeoman-test/-/yeoman-test-1.6.0.tgz#abff291733e16e8923d9eefc8691c632888bf948"
+ dependencies:
+ inquirer "^1.0.2"
+ lodash "^4.3.0"
+ mkdirp "^0.5.1"
+ pinkie-promise "^2.0.1"
+ rimraf "^2.4.4"
+ sinon "^1.17.2"
+ yeoman-environment "^1.5.2"
+ yeoman-generator "^0.24.1"
+
+yeoman-welcome@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/yeoman-welcome/-/yeoman-welcome-1.0.1.tgz#f6cf198fd4fba8a771672c26cdfb8a64795c84ec"
+ dependencies:
+ chalk "^1.0.0"
+
+yo@1.8.5:
+ version "1.8.5"
+ resolved "https://registry.yarnpkg.com/yo/-/yo-1.8.5.tgz#776ab9ec79a7882f8d4f7a9e10214fdab050d928"
+ dependencies:
+ async "^1.0.0"
+ chalk "^1.0.0"
+ cli-list "^0.1.1"
+ configstore "^1.0.0"
+ cross-spawn "^3.0.1"
+ figures "^1.3.5"
+ fullname "^2.0.0"
+ got "^5.0.0"
+ humanize-string "^1.0.0"
+ inquirer "^0.11.0"
+ insight "^0.7.0"
+ lodash "^3.2.0"
+ meow "^3.0.0"
+ npm-keyword "^4.1.0"
+ opn "^3.0.2"
+ package-json "^2.1.0"
+ parse-help "^0.1.1"
+ read-pkg-up "^1.0.1"
+ repeating "^2.0.0"
+ root-check "^1.0.0"
+ sort-on "^1.0.0"
+ string-length "^1.0.0"
+ tabtab "^1.3.0"
+ titleize "^1.0.0"
+ update-notifier "^0.6.0"
+ user-home "^2.0.0"
+ yeoman-character "^1.0.0"
+ yeoman-doctor "^2.0.0"
+ yeoman-environment "^1.6.1"
+ yosay "^1.0.0"
+
+yosay@^1.0.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/yosay/-/yosay-1.2.1.tgz#9466ef969830e85b474e267b50f7688693ed3b5b"
+ dependencies:
+ ansi-regex "^2.0.0"
+ ansi-styles "^2.0.0"
+ chalk "^1.0.0"
+ cli-boxes "^1.0.0"
+ pad-component "0.0.1"
+ repeating "^2.0.0"
+ string-width "^1.0.0"
+ strip-ansi "^3.0.0"
+ taketalk "^1.0.0"
+ wrap-ansi "^2.0.0"
diff --git a/jhipster/jhipster-microservice/dealer-app/.editorconfig b/jhipster/jhipster-microservice/dealer-app/.editorconfig
new file mode 100644
index 0000000000..a03599dd04
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/.editorconfig
@@ -0,0 +1,24 @@
+# EditorConfig helps developers define and maintain consistent
+# coding styles between different editors and IDEs
+# editorconfig.org
+
+root = true
+
+[*]
+
+# Change these settings to your own preference
+indent_style = space
+indent_size = 4
+
+# We recommend you to keep these unchanged
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
+
+[{package,bower}.json]
+indent_style = space
+indent_size = 2
diff --git a/jhipster/jhipster-microservice/dealer-app/.gitattributes b/jhipster/jhipster-microservice/dealer-app/.gitattributes
new file mode 100644
index 0000000000..2a13efa88f
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/.gitattributes
@@ -0,0 +1,22 @@
+# All text files should have the "lf" (Unix) line endings
+* text eol=lf
+
+# Explicitly declare text files you want to always be normalized and converted
+# to native line endings on checkout.
+*.java text
+*.js text
+*.css text
+*.html text
+
+# Denote all files that are truly binary and should not be modified.
+*.png binary
+*.jpg binary
+*.jar binary
+*.pdf binary
+*.eot binary
+*.ttf binary
+*.gzip binary
+*.gz binary
+*.ai binary
+*.eps binary
+*.swf binary
diff --git a/jhipster/jhipster-microservice/dealer-app/.gitignore b/jhipster/jhipster-microservice/dealer-app/.gitignore
new file mode 100644
index 0000000000..74b29e2042
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/.gitignore
@@ -0,0 +1,141 @@
+######################
+# Project Specific
+######################
+/target/www/**
+/src/test/javascript/coverage/
+/src/test/javascript/PhantomJS*/
+
+######################
+# Node
+######################
+/node/
+node_tmp/
+node_modules/
+npm-debug.log.*
+
+######################
+# SASS
+######################
+.sass-cache/
+
+######################
+# Eclipse
+######################
+*.pydevproject
+.project
+.metadata
+tmp/
+tmp/**/*
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.classpath
+.settings/
+.loadpath
+.factorypath
+/src/main/resources/rebel.xml
+
+# External tool builders
+.externalToolBuilders/**
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# CDT-specific
+.cproject
+
+# PDT-specific
+.buildpath
+
+######################
+# Intellij
+######################
+.idea/
+*.iml
+*.iws
+*.ipr
+*.ids
+*.orig
+
+######################
+# Visual Studio Code
+######################
+.vscode/
+
+######################
+# Maven
+######################
+/log/
+/target/
+
+######################
+# Gradle
+######################
+.gradle/
+/build/
+
+######################
+# Package Files
+######################
+*.jar
+*.war
+*.ear
+*.db
+
+######################
+# Windows
+######################
+# Windows image file caches
+Thumbs.db
+
+# Folder config file
+Desktop.ini
+
+######################
+# Mac OSX
+######################
+.DS_Store
+.svn
+
+# Thumbnails
+._*
+
+# Files that might appear on external disk
+.Spotlight-V100
+.Trashes
+
+######################
+# Directories
+######################
+/bin/
+/deploy/
+
+######################
+# Logs
+######################
+*.log
+
+######################
+# Others
+######################
+*.class
+*.*~
+*~
+.merge_file*
+
+######################
+# Gradle Wrapper
+######################
+!gradle/wrapper/gradle-wrapper.jar
+
+######################
+# Maven Wrapper
+######################
+!.mvn/wrapper/maven-wrapper.jar
+
+######################
+# ESLint
+######################
+.eslintcache
diff --git a/jhipster/jhipster-microservice/dealer-app/.jhipster/Dealer.json b/jhipster/jhipster-microservice/dealer-app/.jhipster/Dealer.json
new file mode 100644
index 0000000000..e9b4a8112e
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/.jhipster/Dealer.json
@@ -0,0 +1,21 @@
+{
+ "fluentMethods": true,
+ "relationships": [],
+ "fields": [
+ {
+ "fieldName": "name",
+ "fieldType": "String"
+ },
+ {
+ "fieldName": "address",
+ "fieldType": "String"
+ }
+ ],
+ "changelogDate": "20170503044952",
+ "dto": "no",
+ "service": "no",
+ "entityTableName": "dealer",
+ "pagination": "infinite-scroll",
+ "microserviceName": "dealerapp",
+ "searchEngine": false
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/.mvn/wrapper/maven-wrapper.jar b/jhipster/jhipster-microservice/dealer-app/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000000..5fd4d5023f
Binary files /dev/null and b/jhipster/jhipster-microservice/dealer-app/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/jhipster/jhipster-microservice/dealer-app/.mvn/wrapper/maven-wrapper.properties b/jhipster/jhipster-microservice/dealer-app/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000000..c954cec91c
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip
diff --git a/jhipster/jhipster-microservice/dealer-app/.yo-rc.json b/jhipster/jhipster-microservice/dealer-app/.yo-rc.json
new file mode 100644
index 0000000000..aa9167a92e
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/.yo-rc.json
@@ -0,0 +1,29 @@
+{
+ "generator-jhipster": {
+ "jhipsterVersion": "4.0.8",
+ "baseName": "dealerapp",
+ "packageName": "com.dealer.app",
+ "packageFolder": "com/dealer/app",
+ "serverPort": "8082",
+ "authenticationType": "jwt",
+ "hibernateCache": "hazelcast",
+ "clusteredHttpSession": false,
+ "websocket": false,
+ "databaseType": "sql",
+ "devDatabaseType": "h2Disk",
+ "prodDatabaseType": "mysql",
+ "searchEngine": false,
+ "messageBroker": false,
+ "serviceDiscoveryType": "eureka",
+ "buildTool": "maven",
+ "enableSocialSignIn": false,
+ "jwtSecretKey": "d4c73e937677223a85c7fcebae7a6ce0c48c3b01",
+ "enableTranslation": false,
+ "applicationType": "microservice",
+ "testFrameworks": [],
+ "jhiPrefix": "jhi",
+ "skipClient": true,
+ "skipUserManagement": true,
+ "clientPackageManager": "yarn"
+ }
+}
\ No newline at end of file
diff --git a/jhipster/jhipster-microservice/dealer-app/README.md b/jhipster/jhipster-microservice/dealer-app/README.md
new file mode 100644
index 0000000000..f0fb5fb820
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/README.md
@@ -0,0 +1,75 @@
+# dealerapp
+This application was generated using JHipster 4.0.8, you can find documentation and help at [https://jhipster.github.io/documentation-archive/v4.0.8](https://jhipster.github.io/documentation-archive/v4.0.8).
+
+This is a "microservice" application intended to be part of a microservice architecture, please refer to the [Doing microservices with JHipster][] page of the documentation for more information.
+
+This application is configured for Service Discovery and Configuration with the JHipster-Registry. On launch, it will refuse to start if it is not able to connect to the JHipster-Registry at [http://localhost:8761](http://localhost:8761). For more information, read our documentation on [Service Discovery and Configuration with the JHipster-Registry][].
+
+## Development
+
+To start your application in the dev profile, simply run:
+
+ ./mvnw
+
+
+For further instructions on how to develop with JHipster, have a look at [Using JHipster in development][].
+
+
+## Building for production
+
+To optimize the dealerapp application for production, run:
+
+ ./mvnw -Pprod clean package
+
+To ensure everything worked, run:
+
+ java -jar target/*.war
+
+
+Refer to [Using JHipster in production][] for more details.
+
+## Testing
+
+To launch your application's tests, run:
+
+ ./mvnw clean test
+
+For more information, refer to the [Running tests page][].
+
+## Using Docker to simplify development (optional)
+
+You can use Docker to improve your JHipster development experience. A number of docker-compose configuration are available in the [src/main/docker](src/main/docker) folder to launch required third party services.
+For example, to start a mysql database in a docker container, run:
+
+ docker-compose -f src/main/docker/mysql.yml up -d
+
+To stop it and remove the container, run:
+
+ docker-compose -f src/main/docker/mysql.yml down
+
+You can also fully dockerize your application and all the services that it depends on.
+To achieve this, first build a docker image of your app by running:
+
+ ./mvnw package -Pprod docker:build
+
+Then run:
+
+ docker-compose -f src/main/docker/app.yml up -d
+
+For more information refer to [Using Docker and Docker-Compose][], this page also contains information on the docker-compose sub-generator (`yo jhipster:docker-compose`), which is able to generate docker configurations for one or several JHipster applications.
+
+## Continuous Integration (optional)
+
+To configure CI for your project, run the ci-cd sub-generator (`yo jhipster:ci-cd`), this will let you generate configuration files for a number of Continuous Integration systems. Consult the [Setting up Continuous Integration][] page for more information.
+
+[JHipster Homepage and latest documentation]: https://jhipster.github.io
+[JHipster 4.0.8 archive]: https://jhipster.github.io/documentation-archive/v4.0.8
+[Doing microservices with JHipster]: https://jhipster.github.io/documentation-archive/v4.0.8/microservices-architecture/
+[Using JHipster in development]: https://jhipster.github.io/documentation-archive/v4.0.8/development/
+[Service Discovery and Configuration with the JHipster-Registry]: https://jhipster.github.io/documentation-archive/v4.0.8/microservices-architecture/#jhipster-registry
+[Using Docker and Docker-Compose]: https://jhipster.github.io/documentation-archive/v4.0.8/docker-compose
+[Using JHipster in production]: https://jhipster.github.io/documentation-archive/v4.0.8/production/
+[Running tests page]: https://jhipster.github.io/documentation-archive/v4.0.8/running-tests/
+[Setting up Continuous Integration]: https://jhipster.github.io/documentation-archive/v4.0.8/setting-up-ci/
+
+
diff --git a/jhipster/jhipster-microservice/dealer-app/mvnw b/jhipster/jhipster-microservice/dealer-app/mvnw
new file mode 100755
index 0000000000..a1ba1bf554
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/mvnw
@@ -0,0 +1,233 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven2 Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ #
+ # Look for the Apple JDKs first to preserve the existing behaviour, and then look
+ # for the new JDKs provided by Oracle.
+ #
+ if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then
+ #
+ # Apple JDKs
+ #
+ export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
+ fi
+
+ if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then
+ #
+ # Apple JDKs
+ #
+ export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
+ fi
+
+ if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then
+ #
+ # Oracle JDKs
+ #
+ export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
+ fi
+
+ if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then
+ #
+ # Apple JDKs
+ #
+ export JAVA_HOME=`/usr/libexec/java_home`
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Migwn, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+ # TODO classpath?
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+ local basedir=$(pwd)
+ local wdir=$(pwd)
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ wdir=$(cd "$wdir/.."; pwd)
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)}
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} "$@"
diff --git a/jhipster/jhipster-microservice/dealer-app/mvnw.cmd b/jhipster/jhipster-microservice/dealer-app/mvnw.cmd
new file mode 100644
index 0000000000..2b934e89dd
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/mvnw.cmd
@@ -0,0 +1,145 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven2 Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+set MAVEN_CMD_LINE_ARGS=%*
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+
+set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar""
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS%
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
\ No newline at end of file
diff --git a/jhipster/jhipster-microservice/dealer-app/package.json b/jhipster/jhipster-microservice/dealer-app/package.json
new file mode 100644
index 0000000000..ac56dd89a7
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/package.json
@@ -0,0 +1,5 @@
+{
+ "devDependencies": {
+ "generator-jhipster": "4.0.8"
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/pom.xml b/jhipster/jhipster-microservice/dealer-app/pom.xml
new file mode 100644
index 0000000000..199d383e39
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/pom.xml
@@ -0,0 +1,934 @@
+
+
+ 4.0.0
+
+
+ spring-boot-starter-parent
+ org.springframework.boot
+ 1.5.2.RELEASE
+
+
+
+ com.dealer.app
+ dealerapp
+ 0.0.1-SNAPSHOT
+ war
+ Dealerapp
+
+
+ ${maven.version}
+
+
+
+ -Djava.security.egd=file:/dev/./urandom -Xmx256m
+ 3.6.2
+ 2.0.0
+ 2.5
+ 3.5
+ 0.4.13
+ 1.2
+ 5.2.8.Final
+ 2.6.0
+ 0.7.9
+ 1.8
+ 3.21.0-GA
+ 1.0.0
+ 1.1.0
+ 0.7.0
+ 3.6
+ 2.0.0
+ 4.8
+ jdt_apt
+ 1.1.0.Final
+ 3.6.0
+ 1.4.1
+ 3.0.1
+ yyyyMMddHHmmss
+ ${java.version}
+ ${java.version}
+ 3.0.0
+ 3.1.3
+ v6.10.0
+
+
+
+ 0.0.20
+
+ ${project.build.directory}/test-results
+ false
+ 3.2.2
+ 2.12.1
+ 3.2
+
+ src/main/webapp/content/**/*.*, src/main/webapp/bower_components/**/*.*, src/main/webapp/i18n/*.js, target/www/**/*.*
+
+ S3437,UndocumentedApi,BoldAndItalicTagsCheck
+
+
+ src/main/webapp/app/**/*.*
+ Web:BoldAndItalicTagsCheck
+
+ src/main/java/**/*
+ squid:S3437
+
+ src/main/java/**/*
+ squid:UndocumentedApi
+
+ ${project.testresult.directory}/coverage/jacoco/jacoco-it.exec
+ ${project.testresult.directory}/coverage/jacoco/jacoco.exec
+ jacoco
+
+ ${project.testresult.directory}/karma
+
+ ${project.testresult.directory}/coverage/report-lcov/lcov.info
+
+ ${project.testresult.directory}/coverage/report-lcov/lcov.info
+
+ ${project.basedir}/src/main/
+ ${project.testresult.directory}/surefire-reports
+ ${project.basedir}/src/test/
+
+ 2.5.0
+
+ Camden.SR5
+ 2.6.1
+ 1.4.10.Final
+ 1.1.0.Final
+ v0.21.3
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+ io.github.jhipster
+ jhipster
+ ${jhipster.server.version}
+
+
+ io.dropwizard.metrics
+ metrics-core
+
+
+ io.dropwizard.metrics
+ metrics-annotation
+ ${dropwizard-metrics.version}
+
+
+ io.dropwizard.metrics
+ metrics-json
+ ${dropwizard-metrics.version}
+
+
+ io.dropwizard.metrics
+ metrics-jvm
+ ${dropwizard-metrics.version}
+
+
+ io.dropwizard.metrics
+ metrics-servlet
+ ${dropwizard-metrics.version}
+
+
+ io.dropwizard.metrics
+ metrics-servlets
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-hibernate5
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-hppc
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-json-org
+
+
+ com.h2database
+ h2
+
+
+ com.hazelcast
+ hazelcast
+
+
+ com.hazelcast
+ hazelcast-hibernate52
+ ${hazelcast-hibernate52.version}
+
+
+ com.hazelcast
+ hazelcast-spring
+
+
+ org.awaitility
+ awaitility
+ ${awaitility.version}
+ test
+
+
+ com.jayway.jsonpath
+ json-path
+ test
+
+
+
+ io.springfox
+ springfox-swagger2
+ ${springfox.version}
+
+
+ org.mapstruct
+ mapstruct
+
+
+
+
+ io.springfox
+ springfox-bean-validators
+ ${springfox.version}
+
+
+ com.mattbertolini
+ liquibase-slf4j
+ ${liquibase-slf4j.version}
+
+
+ com.ryantenney.metrics
+ metrics-spring
+ ${metrics-spring.version}
+
+
+ com.codahale.metrics
+ metrics-annotation
+
+
+ com.codahale.metrics
+ metrics-core
+
+
+ com.codahale.metrics
+ metrics-healthchecks
+
+
+
+
+ com.zaxxer
+ HikariCP
+
+
+ tools
+ com.sun
+
+
+
+
+
+ commons-io
+ commons-io
+ ${commons-io.version}
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang.version}
+
+
+ javax.cache
+ cache-api
+
+
+ mysql
+ mysql-connector-java
+
+
+ org.assertj
+ assertj-core
+ test
+
+
+ org.hibernate
+ hibernate-envers
+
+
+ org.hibernate
+ hibernate-validator
+
+
+ org.liquibase
+ liquibase-core
+
+
+ jetty-servlet
+ org.eclipse.jetty
+
+
+
+
+ org.mapstruct
+ mapstruct-jdk8
+ ${mapstruct.version}
+
+
+ org.springframework
+ spring-context-support
+
+
+ org.springframework.boot
+ spring-boot-actuator
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ org.springframework.boot
+ spring-boot-loader-tools
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+ org.springframework.boot
+ spring-boot-starter-mail
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.security
+ spring-security-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+
+
+
+
+ io.jsonwebtoken
+ jjwt
+ ${jjwt.version}
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter
+
+
+ org.springframework.cloud
+ spring-cloud-starter-ribbon
+
+
+
+ io.netty
+ netty-transport-native-epoll
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-hystrix
+
+
+ org.springframework.cloud
+ spring-cloud-starter-spectator
+
+
+ org.springframework.retry
+ spring-retry
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+ org.springframework.cloud
+ spring-cloud-starter-feign
+
+
+ net.logstash.logback
+ logstash-logback-encoder
+ ${logstash-logback-encoder.version}
+
+
+ ch.qos.logback
+ logback-core
+
+
+ ch.qos.logback
+ logback-classic
+
+
+ ch.qos.logback
+ logback-access
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-cloud-connectors
+
+
+
+ org.springframework.security
+ spring-security-data
+
+
+
+
+ spring-boot:run
+
+
+ com.github.ekryd.sortpom
+ sortpom-maven-plugin
+ ${sortpom-maven-plugin.version}
+
+
+ verify
+
+ sort
+
+
+
+
+ true
+ 4
+ groupId,artifactId
+ groupId,artifactId
+ true
+ false
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+
+
+ org.mapstruct
+ mapstruct-processor
+ ${mapstruct.version}
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-eclipse-plugin
+
+ true
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ ${maven-enforcer-plugin.version}
+
+
+ enforce-versions
+
+ enforce
+
+
+
+
+
+
+ You are running an older version of Maven. JHipster requires at least Maven ${maven.version}
+ [${maven.version},)
+
+
+ You are running an older version of Java. JHipster requires at least JDK ${java.version}
+ [${java.version}.0,)
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ ${maven-resources-plugin.version}
+
+
+ default-resources
+ validate
+
+ copy-resources
+
+
+ target/classes
+ false
+
+ #
+
+
+
+ src/main/resources/
+ true
+
+ **/*.xml
+ **/*.yml
+
+
+
+ src/main/resources/
+ false
+
+ **/*.xml
+ **/*.yml
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ alphabetical
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ ${jacoco-maven-plugin.version}
+
+
+ pre-unit-tests
+
+ prepare-agent
+
+
+
+ ${project.testresult.directory}/coverage/jacoco/jacoco.exec
+
+
+
+
+ post-unit-test
+ test
+
+ report
+
+
+ ${project.testresult.directory}/coverage/jacoco/jacoco.exec
+ ${project.testresult.directory}/coverage/jacoco
+
+
+
+
+
+ org.sonarsource.scanner.maven
+ sonar-maven-plugin
+ ${sonar-maven-plugin.version}
+
+
+ org.liquibase
+ liquibase-maven-plugin
+ ${liquibase.version}
+
+ src/main/resources/config/liquibase/master.xml
+ src/main/resources/config/liquibase/changelog/${maven.build.timestamp}_changelog.xml
+ org.h2.Driver
+ jdbc:h2:file:./target/h2db/db/dealerapp
+
+ dealerapp
+
+ hibernate:spring:com.dealer.app.domain?dialect=org.hibernate.dialect.H2Dialect&hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy&hibernate.implicit_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
+ true
+ debug
+
+
+
+ org.javassist
+ javassist
+ ${javassist.version}
+
+
+ org.liquibase.ext
+ liquibase-hibernate5
+ ${liquibase-hibernate5.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+ ${project.parent.version}
+
+
+ javax.validation
+ validation-api
+ ${validation-api.version}
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+ true
+
+
+
+
+ com.spotify
+ docker-maven-plugin
+ ${docker-maven-plugin.version}
+
+ dealerapp
+ src/main/docker
+
+
+ /
+ ${project.build.directory}
+ ${project.build.finalName}.war
+
+
+
+
+
+
+
+
+
+
+ org.eclipse.m2e
+ lifecycle-mapping
+ 1.0.0
+
+
+
+
+
+ org.jacoco
+
+ jacoco-maven-plugin
+
+
+ ${jacoco-maven-plugin.version}
+
+
+ prepare-agent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ no-liquibase
+
+ ,no-liquibase
+
+
+
+ swagger
+
+ ,swagger
+
+
+
+ dev
+
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-starter-undertow
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
+
+
+
+
+
+
+ DEBUG
+
+ dev${profile.no-liquibase}
+
+
+
+ prod
+
+
+ org.springframework.boot
+ spring-boot-starter-undertow
+
+
+
+
+
+ maven-clean-plugin
+
+
+
+ target/www/
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+
+
+
+
+ build-info
+
+
+
+
+
+
+
+
+ INFO
+
+ prod${profile.swagger}${profile.no-liquibase}
+
+
+
+
+ cc
+
+
+ org.springframework.boot
+ spring-boot-starter-undertow
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
+ src/main/webapp/
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+ true
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ default-compile
+ none
+
+
+ default-testCompile
+ none
+
+
+
+
+ net.alchim31.maven
+ scala-maven-plugin
+ ${scala-maven-plugin.version}
+
+
+ compile
+ compile
+
+ add-source
+ compile
+
+
+
+ test-compile
+ test-compile
+
+ add-source
+ testCompile
+
+
+
+
+ incremental
+ true
+ ${scala.version}
+
+
+
+
+
+
+ DEBUG
+
+ dev,swagger
+
+
+
+
+ graphite
+
+
+ io.dropwizard.metrics
+ metrics-graphite
+
+
+
+
+
+ prometheus
+
+
+ io.prometheus
+ simpleclient
+ ${prometheus-simpleclient.version}
+
+
+ io.prometheus
+ simpleclient_servlet
+ ${prometheus-simpleclient.version}
+
+
+ io.prometheus
+ simpleclient_dropwizard
+ ${prometheus-simpleclient.version}
+
+
+
+
+
+ IDE
+
+
+ org.mapstruct
+ mapstruct-processor
+ ${mapstruct.version}
+
+
+
+
+
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/docker/Dockerfile b/jhipster/jhipster-microservice/dealer-app/src/main/docker/Dockerfile
new file mode 100644
index 0000000000..cdef3a17e4
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/docker/Dockerfile
@@ -0,0 +1,13 @@
+FROM openjdk:8-jre-alpine
+
+ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \
+ JHIPSTER_SLEEP=0
+
+# add directly the war
+ADD *.war /app.war
+
+VOLUME /tmp
+EXPOSE 8082 5701/udp
+CMD echo "The application will start in ${JHIPSTER_SLEEP}s..." && \
+ sleep ${JHIPSTER_SLEEP} && \
+ java -Djava.security.egd=file:/dev/./urandom -jar /app.war
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/docker/app.yml b/jhipster/jhipster-microservice/dealer-app/src/main/docker/app.yml
new file mode 100644
index 0000000000..85a816052e
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/docker/app.yml
@@ -0,0 +1,19 @@
+version: '2'
+services:
+ dealerapp-app:
+ image: dealerapp
+ environment:
+ - SPRING_PROFILES_ACTIVE=prod,swagger
+ - SPRING_CLOUD_CONFIG_URI=http://admin:$${jhipster.registry.password}@jhipster-registry:8761/config
+ - SPRING_DATASOURCE_URL=jdbc:mysql://dealerapp-mysql:3306/dealerapp?useUnicode=true&characterEncoding=utf8&useSSL=false
+ - JHIPSTER_SLEEP=10 # gives time for the database to boot before the application
+ dealerapp-mysql:
+ extends:
+ file: mysql.yml
+ service: dealerapp-mysql
+ jhipster-registry:
+ extends:
+ file: jhipster-registry.yml
+ service: jhipster-registry
+ environment:
+ - SPRING_CLOUD_CONFIG_SERVER_NATIVE_SEARCH_LOCATIONS=file:./central-config/docker-config/
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/docker/central-server-config/README.md b/jhipster/jhipster-microservice/dealer-app/src/main/docker/central-server-config/README.md
new file mode 100644
index 0000000000..022a152863
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/docker/central-server-config/README.md
@@ -0,0 +1,7 @@
+# Central configuration sources details
+
+The JHipster-Registry will use the following directories as its configuration source :
+- localhost-config : when running the registry in docker with the jhipster-registry.yml docker-compose file
+- docker-config : when running the registry and the app both in docker with the app.yml docker-compose file
+
+For more info, refer to http://jhipster.github.io/microservices-architecture/#registry_app_configuration
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/docker/central-server-config/docker-config/application.yml b/jhipster/jhipster-microservice/dealer-app/src/main/docker/central-server-config/docker-config/application.yml
new file mode 100644
index 0000000000..f11d367241
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/docker/central-server-config/docker-config/application.yml
@@ -0,0 +1,15 @@
+# Common configuration shared between all applications
+configserver:
+ name: Docker JHipster Registry
+ status: Connected to the JHipster Registry running in Docker
+
+jhipster:
+ security:
+ authentication:
+ jwt:
+ secret: my-secret-token-to-change-in-production
+
+eureka:
+ client:
+ serviceUrl:
+ defaultZone: http://admin:${jhipster.registry.password}@jhipster-registry:8761/eureka/
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/docker/central-server-config/localhost-config/application.yml b/jhipster/jhipster-microservice/dealer-app/src/main/docker/central-server-config/localhost-config/application.yml
new file mode 100644
index 0000000000..052a6d0535
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/docker/central-server-config/localhost-config/application.yml
@@ -0,0 +1,15 @@
+# Common configuration shared between all applications
+configserver:
+ name: Docker JHipster Registry
+ status: Connected to the JHipster Registry running in Docker
+
+jhipster:
+ security:
+ authentication:
+ jwt:
+ secret: my-secret-token-to-change-in-production
+
+eureka:
+ client:
+ serviceUrl:
+ defaultZone: http://admin:${jhipster.registry.password}@localhost:8761/eureka/
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/docker/jhipster-registry.yml b/jhipster/jhipster-microservice/dealer-app/src/main/docker/jhipster-registry.yml
new file mode 100644
index 0000000000..58feb685d4
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/docker/jhipster-registry.yml
@@ -0,0 +1,18 @@
+version: '2'
+services:
+ jhipster-registry:
+ image: jhipster/jhipster-registry:v2.5.8
+ volumes:
+ - ./central-server-config:/central-config
+ # When run with the "dev" Spring profile, the JHipster Registry will
+ # read the config from the local filesystem (central-server-config directory)
+ # When run with the "prod" Spring profile, it will read the config from a git repository
+ # See http://jhipster.github.io/microservices-architecture/#registry_app_configuration
+ environment:
+ - SPRING_PROFILES_ACTIVE=dev
+ - SECURITY_USER_PASSWORD=admin
+ - SPRING_CLOUD_CONFIG_SERVER_NATIVE_SEARCH_LOCATIONS=file:./central-config/localhost-config/
+ # - GIT_URI=https://github.com/jhipster/jhipster-registry/
+ # - GIT_SEARCH_PATHS=central-config
+ ports:
+ - 8761:8761
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/docker/mysql.yml b/jhipster/jhipster-microservice/dealer-app/src/main/docker/mysql.yml
new file mode 100644
index 0000000000..866f39f947
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/docker/mysql.yml
@@ -0,0 +1,13 @@
+version: '2'
+services:
+ dealerapp-mysql:
+ image: mysql:5.7.13
+ # volumes:
+ # - ~/volumes/jhipster/dealerapp/mysql/:/var/lib/mysql/
+ environment:
+ - MYSQL_USER=root
+ - MYSQL_ALLOW_EMPTY_PASSWORD=yes
+ - MYSQL_DATABASE=dealerapp
+ ports:
+ - 3306:3306
+ command: mysqld --lower_case_table_names=1 --skip-ssl --character_set_server=utf8
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/docker/sonar.yml b/jhipster/jhipster-microservice/dealer-app/src/main/docker/sonar.yml
new file mode 100644
index 0000000000..0ed7462f28
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/docker/sonar.yml
@@ -0,0 +1,7 @@
+version: '2'
+services:
+ dealerapp-sonar:
+ image: sonarqube:6.2-alpine
+ ports:
+ - 9000:9000
+ - 9092:9092
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/ApplicationWebXml.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/ApplicationWebXml.java
new file mode 100644
index 0000000000..2321d72c70
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/ApplicationWebXml.java
@@ -0,0 +1,21 @@
+package com.dealer.app;
+
+import com.dealer.app.config.DefaultProfileUtil;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.support.SpringBootServletInitializer;
+
+/**
+ * This is a helper Java class that provides an alternative to creating a web.xml.
+ * This will be invoked only when the application is deployed to a servlet container like Tomcat, JBoss etc.
+ */
+public class ApplicationWebXml extends SpringBootServletInitializer {
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ /**
+ * set a default to use when no profile is configured.
+ */
+ DefaultProfileUtil.addDefaultProfile(application.application());
+ return application.sources(DealerappApp.class);
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/DealerappApp.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/DealerappApp.java
new file mode 100644
index 0000000000..72075d8bfe
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/DealerappApp.java
@@ -0,0 +1,91 @@
+package com.dealer.app;
+
+import com.dealer.app.config.ApplicationProperties;
+import com.dealer.app.config.DefaultProfileUtil;
+
+import io.github.jhipster.config.JHipsterConstants;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.actuate.autoconfigure.*;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.core.env.Environment;
+
+import javax.annotation.PostConstruct;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.Collection;
+
+@ComponentScan
+@EnableAutoConfiguration(exclude = {MetricFilterAutoConfiguration.class, MetricRepositoryAutoConfiguration.class})
+@EnableConfigurationProperties({LiquibaseProperties.class, ApplicationProperties.class})
+@EnableDiscoveryClient
+public class DealerappApp {
+
+ private static final Logger log = LoggerFactory.getLogger(DealerappApp.class);
+
+ private final Environment env;
+
+ public DealerappApp(Environment env) {
+ this.env = env;
+ }
+
+ /**
+ * Initializes dealerapp.
+ *
+ * Spring profiles can be configured with a program arguments --spring.profiles.active=your-active-profile
+ *
+ * You can find more information on how profiles work with JHipster on http://jhipster.github.io/profiles/.
+ */
+ @PostConstruct
+ public void initApplication() {
+ Collection activeProfiles = Arrays.asList(env.getActiveProfiles());
+ if (activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) && activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_PRODUCTION)) {
+ log.error("You have misconfigured your application! It should not run " +
+ "with both the 'dev' and 'prod' profiles at the same time.");
+ }
+ if (activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) && activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_CLOUD)) {
+ log.error("You have misconfigured your application! It should not" +
+ "run with both the 'dev' and 'cloud' profiles at the same time.");
+ }
+ }
+
+ /**
+ * Main method, used to run the application.
+ *
+ * @param args the command line arguments
+ * @throws UnknownHostException if the local host name could not be resolved into an address
+ */
+ public static void main(String[] args) throws UnknownHostException {
+ SpringApplication app = new SpringApplication(DealerappApp.class);
+ DefaultProfileUtil.addDefaultProfile(app);
+ Environment env = app.run(args).getEnvironment();
+ String protocol = "http";
+ if (env.getProperty("server.ssl.key-store") != null) {
+ protocol = "https";
+ }
+ log.info("\n----------------------------------------------------------\n\t" +
+ "Application '{}' is running! Access URLs:\n\t" +
+ "Local: \t\t{}://localhost:{}\n\t" +
+ "External: \t{}://{}:{}\n\t" +
+ "Profile(s): \t{}\n----------------------------------------------------------",
+ env.getProperty("spring.application.name"),
+ protocol,
+ env.getProperty("server.port"),
+ protocol,
+ InetAddress.getLocalHost().getHostAddress(),
+ env.getProperty("server.port"),
+ env.getActiveProfiles());
+
+ String configServerStatus = env.getProperty("configserver.status");
+ log.info("\n----------------------------------------------------------\n\t" +
+ "Config Server: \t{}\n----------------------------------------------------------",
+ configServerStatus == null ? "Not found or not setup for this application" : configServerStatus);
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/aop/logging/LoggingAspect.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/aop/logging/LoggingAspect.java
new file mode 100644
index 0000000000..a7364157c9
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/aop/logging/LoggingAspect.java
@@ -0,0 +1,79 @@
+package com.dealer.app.aop.logging;
+
+import io.github.jhipster.config.JHipsterConstants;
+
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.env.Environment;
+
+import java.util.Arrays;
+
+/**
+ * Aspect for logging execution of service and repository Spring components.
+ *
+ * By default, it only runs with the "dev" profile.
+ */
+@Aspect
+public class LoggingAspect {
+
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+ private final Environment env;
+
+ public LoggingAspect(Environment env) {
+ this.env = env;
+ }
+
+ /**
+ * Pointcut that matches all repositories, services and Web REST endpoints.
+ */
+ @Pointcut("within(com.dealer.app.repository..*) || within(com.dealer.app.service..*) || within(com.dealer.app.web.rest..*)")
+ public void loggingPointcut() {
+ // Method is empty as this is just a Pointcut, the implementations are in the advices.
+ }
+
+ /**
+ * Advice that logs methods throwing exceptions.
+ */
+ @AfterThrowing(pointcut = "loggingPointcut()", throwing = "e")
+ public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
+ if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
+ log.error("Exception in {}.{}() with cause = \'{}\' and exception = \'{}\'", joinPoint.getSignature().getDeclaringTypeName(),
+ joinPoint.getSignature().getName(), e.getCause() != null? e.getCause() : "NULL", e.getMessage(), e);
+
+ } else {
+ log.error("Exception in {}.{}() with cause = {}", joinPoint.getSignature().getDeclaringTypeName(),
+ joinPoint.getSignature().getName(), e.getCause() != null? e.getCause() : "NULL");
+ }
+ }
+
+ /**
+ * Advice that logs when a method is entered and exited.
+ */
+ @Around("loggingPointcut()")
+ public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
+ if (log.isDebugEnabled()) {
+ log.debug("Enter: {}.{}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
+ joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
+ }
+ try {
+ Object result = joinPoint.proceed();
+ if (log.isDebugEnabled()) {
+ log.debug("Exit: {}.{}() with result = {}", joinPoint.getSignature().getDeclaringTypeName(),
+ joinPoint.getSignature().getName(), result);
+ }
+ return result;
+ } catch (IllegalArgumentException e) {
+ log.error("Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()),
+ joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
+
+ throw e;
+ }
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/ApplicationProperties.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/ApplicationProperties.java
new file mode 100644
index 0000000000..dc11fa63fe
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/ApplicationProperties.java
@@ -0,0 +1,15 @@
+package com.dealer.app.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * Properties specific to JHipster.
+ *
+ *
+ * Properties are configured in the application.yml file.
+ *
+ */
+@ConfigurationProperties(prefix = "application", ignoreUnknownFields = false)
+public class ApplicationProperties {
+
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/AsyncConfiguration.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/AsyncConfiguration.java
new file mode 100644
index 0000000000..3b6de121fd
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/AsyncConfiguration.java
@@ -0,0 +1,46 @@
+package com.dealer.app.config;
+
+import io.github.jhipster.async.ExceptionHandlingAsyncTaskExecutor;
+import io.github.jhipster.config.JHipsterProperties;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
+import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.*;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+
+@Configuration
+@EnableAsync
+@EnableScheduling
+public class AsyncConfiguration implements AsyncConfigurer {
+
+ private final Logger log = LoggerFactory.getLogger(AsyncConfiguration.class);
+
+ private final JHipsterProperties jHipsterProperties;
+
+ public AsyncConfiguration(JHipsterProperties jHipsterProperties) {
+ this.jHipsterProperties = jHipsterProperties;
+ }
+
+ @Override
+ @Bean(name = "taskExecutor")
+ public Executor getAsyncExecutor() {
+ log.debug("Creating Async Task Executor");
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ executor.setCorePoolSize(jHipsterProperties.getAsync().getCorePoolSize());
+ executor.setMaxPoolSize(jHipsterProperties.getAsync().getMaxPoolSize());
+ executor.setQueueCapacity(jHipsterProperties.getAsync().getQueueCapacity());
+ executor.setThreadNamePrefix("dealerapp-Executor-");
+ return new ExceptionHandlingAsyncTaskExecutor(executor);
+ }
+
+ @Override
+ public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
+ return new SimpleAsyncUncaughtExceptionHandler();
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/CacheConfiguration.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/CacheConfiguration.java
new file mode 100644
index 0000000000..6626dea1a2
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/CacheConfiguration.java
@@ -0,0 +1,134 @@
+package com.dealer.app.config;
+
+import io.github.jhipster.config.JHipsterConstants;
+import io.github.jhipster.config.JHipsterProperties;
+
+import com.hazelcast.config.Config;
+import com.hazelcast.core.HazelcastInstance;
+import com.hazelcast.core.Hazelcast;
+import com.hazelcast.config.MapConfig;
+import com.hazelcast.config.EvictionPolicy;
+import com.hazelcast.config.MaxSizeConfig;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.web.ServerProperties;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.cloud.client.discovery.DiscoveryClient;
+import org.springframework.context.annotation.*;
+import org.springframework.core.env.Environment;
+
+import javax.annotation.PreDestroy;
+
+@Configuration
+@EnableCaching
+@AutoConfigureAfter(value = { MetricsConfiguration.class })
+@AutoConfigureBefore(value = { WebConfigurer.class, DatabaseConfiguration.class })
+public class CacheConfiguration {
+
+ private final Logger log = LoggerFactory.getLogger(CacheConfiguration.class);
+
+ private final Environment env;
+
+ private final DiscoveryClient discoveryClient;
+
+ private final ServerProperties serverProperties;
+
+ public CacheConfiguration(Environment env, DiscoveryClient discoveryClient, ServerProperties serverProperties) {
+ this.env = env;
+ this.discoveryClient = discoveryClient;
+ this.serverProperties = serverProperties;
+ }
+
+ @PreDestroy
+ public void destroy() {
+ log.info("Closing Cache Manager");
+ Hazelcast.shutdownAll();
+ }
+
+ @Bean
+ public CacheManager cacheManager(HazelcastInstance hazelcastInstance) {
+ log.debug("Starting HazelcastCacheManager");
+ CacheManager cacheManager = new com.hazelcast.spring.cache.HazelcastCacheManager(hazelcastInstance);
+ return cacheManager;
+ }
+
+ @Bean
+ public HazelcastInstance hazelcastInstance(JHipsterProperties jHipsterProperties) {
+ log.debug("Configuring Hazelcast");
+ Config config = new Config();
+ config.setInstanceName("dealerapp");
+ // The serviceId is by default the application's name, see Spring Boot's eureka.instance.appname property
+ String serviceId = discoveryClient.getLocalServiceInstance().getServiceId();
+ log.debug("Configuring Hazelcast clustering for instanceId: {}", serviceId);
+
+ // In development, everything goes through 127.0.0.1, with a different port
+ if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
+ log.debug("Application is running with the \"dev\" profile, Hazelcast " +
+ "cluster will only work with localhost instances");
+
+ System.setProperty("hazelcast.local.localAddress", "127.0.0.1");
+ config.getNetworkConfig().setPort(serverProperties.getPort() + 5701);
+ config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false);
+ config.getNetworkConfig().getJoin().getTcpIpConfig().setEnabled(true);
+ for (ServiceInstance instance : discoveryClient.getInstances(serviceId)) {
+ String clusterMember = "127.0.0.1:" + (instance.getPort() + 5701);
+ log.debug("Adding Hazelcast (dev) cluster member " + clusterMember);
+ config.getNetworkConfig().getJoin().getTcpIpConfig().addMember(clusterMember);
+ }
+ } else { // Production configuration, one host per instance all using port 5701
+ config.getNetworkConfig().setPort(5701);
+ config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false);
+ config.getNetworkConfig().getJoin().getTcpIpConfig().setEnabled(true);
+ for (ServiceInstance instance : discoveryClient.getInstances(serviceId)) {
+ String clusterMember = instance.getHost() + ":5701";
+ log.debug("Adding Hazelcast (prod) cluster member " + clusterMember);
+ config.getNetworkConfig().getJoin().getTcpIpConfig().addMember(clusterMember);
+ }
+ }
+ config.getMapConfigs().put("default", initializeDefaultMapConfig());
+ config.getMapConfigs().put("com.dealer.app.domain.*", initializeDomainMapConfig(jHipsterProperties));
+ return Hazelcast.newHazelcastInstance(config);
+ }
+
+ private MapConfig initializeDefaultMapConfig() {
+ MapConfig mapConfig = new MapConfig();
+
+ /*
+ Number of backups. If 1 is set as the backup-count for example,
+ then all entries of the map will be copied to another JVM for
+ fail-safety. Valid numbers are 0 (no backup), 1, 2, 3.
+ */
+ mapConfig.setBackupCount(0);
+
+ /*
+ Valid values are:
+ NONE (no eviction),
+ LRU (Least Recently Used),
+ LFU (Least Frequently Used).
+ NONE is the default.
+ */
+ mapConfig.setEvictionPolicy(EvictionPolicy.LRU);
+
+ /*
+ Maximum size of the map. When max size is reached,
+ map is evicted based on the policy defined.
+ Any integer between 0 and Integer.MAX_VALUE. 0 means
+ Integer.MAX_VALUE. Default is 0.
+ */
+ mapConfig.setMaxSizeConfig(new MaxSizeConfig(0, MaxSizeConfig.MaxSizePolicy.USED_HEAP_SIZE));
+
+ return mapConfig;
+ }
+
+ private MapConfig initializeDomainMapConfig(JHipsterProperties jHipsterProperties) {
+ MapConfig mapConfig = new MapConfig();
+ mapConfig.setTimeToLiveSeconds(jHipsterProperties.getCache().getHazelcast().getTimeToLiveSeconds());
+ return mapConfig;
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/CloudDatabaseConfiguration.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/CloudDatabaseConfiguration.java
new file mode 100644
index 0000000000..2a64314685
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/CloudDatabaseConfiguration.java
@@ -0,0 +1,24 @@
+package com.dealer.app.config;
+
+import io.github.jhipster.config.JHipsterConstants;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cache.CacheManager;
+import org.springframework.cloud.config.java.AbstractCloudConfig;
+import org.springframework.context.annotation.*;
+
+import javax.sql.DataSource;
+
+@Configuration
+@Profile(JHipsterConstants.SPRING_PROFILE_CLOUD)
+public class CloudDatabaseConfiguration extends AbstractCloudConfig {
+
+ private final Logger log = LoggerFactory.getLogger(CloudDatabaseConfiguration.class);
+
+ @Bean
+ public DataSource dataSource(CacheManager cacheManager) {
+ log.info("Configuring JDBC datasource from a cloud provider");
+ return connectionFactory().dataSource();
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/Constants.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/Constants.java
new file mode 100644
index 0000000000..0d2098b836
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/Constants.java
@@ -0,0 +1,16 @@
+package com.dealer.app.config;
+
+/**
+ * Application constants.
+ */
+public final class Constants {
+
+ //Regex for acceptable logins
+ public static final String LOGIN_REGEX = "^[_'.@A-Za-z0-9-]*$";
+
+ public static final String SYSTEM_ACCOUNT = "system";
+ public static final String ANONYMOUS_USER = "anonymoususer";
+
+ private Constants() {
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/DatabaseConfiguration.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/DatabaseConfiguration.java
new file mode 100644
index 0000000000..04fced065b
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/DatabaseConfiguration.java
@@ -0,0 +1,75 @@
+package com.dealer.app.config;
+
+import io.github.jhipster.config.JHipsterConstants;
+import io.github.jhipster.config.liquibase.AsyncSpringLiquibase;
+
+import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
+import liquibase.integration.spring.SpringLiquibase;
+import org.h2.tools.Server;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.core.env.Environment;
+import org.springframework.core.task.TaskExecutor;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import javax.sql.DataSource;
+import java.sql.SQLException;
+
+@Configuration
+@EnableJpaRepositories("com.dealer.app.repository")
+@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
+@EnableTransactionManagement
+public class DatabaseConfiguration {
+
+ private final Logger log = LoggerFactory.getLogger(DatabaseConfiguration.class);
+
+ private final Environment env;
+
+ public DatabaseConfiguration(Environment env) {
+ this.env = env;
+ }
+
+ /**
+ * Open the TCP port for the H2 database, so it is available remotely.
+ *
+ * @return the H2 database TCP server
+ * @throws SQLException if the server failed to start
+ */
+ @Bean(initMethod = "start", destroyMethod = "stop")
+ @Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)
+ public Server h2TCPServer() throws SQLException {
+ return Server.createTcpServer("-tcp","-tcpAllowOthers");
+ }
+
+ @Bean
+ public SpringLiquibase liquibase(@Qualifier("taskExecutor") TaskExecutor taskExecutor,
+ DataSource dataSource, LiquibaseProperties liquibaseProperties) {
+
+ // Use liquibase.integration.spring.SpringLiquibase if you don't want Liquibase to start asynchronously
+ SpringLiquibase liquibase = new AsyncSpringLiquibase(taskExecutor, env);
+ liquibase.setDataSource(dataSource);
+ liquibase.setChangeLog("classpath:config/liquibase/master.xml");
+ liquibase.setContexts(liquibaseProperties.getContexts());
+ liquibase.setDefaultSchema(liquibaseProperties.getDefaultSchema());
+ liquibase.setDropFirst(liquibaseProperties.isDropFirst());
+ if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_NO_LIQUIBASE)) {
+ liquibase.setShouldRun(false);
+ } else {
+ liquibase.setShouldRun(liquibaseProperties.isEnabled());
+ log.debug("Configuring Liquibase");
+ }
+ return liquibase;
+ }
+
+ @Bean
+ public Hibernate5Module hibernate5Module() {
+ return new Hibernate5Module();
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/DateTimeFormatConfiguration.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/DateTimeFormatConfiguration.java
new file mode 100644
index 0000000000..cca6e4ca04
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/DateTimeFormatConfiguration.java
@@ -0,0 +1,17 @@
+package com.dealer.app.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.format.FormatterRegistry;
+import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+
+@Configuration
+public class DateTimeFormatConfiguration extends WebMvcConfigurerAdapter {
+
+ @Override
+ public void addFormatters(FormatterRegistry registry) {
+ DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
+ registrar.setUseIsoFormat(true);
+ registrar.registerFormatters(registry);
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/DefaultProfileUtil.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/DefaultProfileUtil.java
new file mode 100644
index 0000000000..c914c96954
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/DefaultProfileUtil.java
@@ -0,0 +1,48 @@
+package com.dealer.app.config;
+
+import io.github.jhipster.config.JHipsterConstants;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.core.env.Environment;
+
+import java.util.*;
+
+/**
+ * Utility class to load a Spring profile to be used as default
+ * when there is no spring.profiles.active set in the environment or as command line argument.
+ * If the value is not available in application.yml then dev profile will be used as default.
+ */
+public final class DefaultProfileUtil {
+
+ private static final String SPRING_PROFILE_DEFAULT = "spring.profiles.default";
+
+ private DefaultProfileUtil() {
+ }
+
+ /**
+ * Set a default to use when no profile is configured.
+ *
+ * @param app the Spring application
+ */
+ public static void addDefaultProfile(SpringApplication app) {
+ Map defProperties = new HashMap<>();
+ /*
+ * The default profile to use when no other profiles are defined
+ * This cannot be set in the application.yml file.
+ * See https://github.com/spring-projects/spring-boot/issues/1219
+ */
+ defProperties.put(SPRING_PROFILE_DEFAULT, JHipsterConstants.SPRING_PROFILE_DEVELOPMENT);
+ app.setDefaultProperties(defProperties);
+ }
+
+ /**
+ * Get the profiles that are applied else get default profiles.
+ */
+ public static String[] getActiveProfiles(Environment env) {
+ String[] profiles = env.getActiveProfiles();
+ if (profiles.length == 0) {
+ return env.getDefaultProfiles();
+ }
+ return profiles;
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/LocaleConfiguration.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/LocaleConfiguration.java
new file mode 100644
index 0000000000..6416813b26
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/LocaleConfiguration.java
@@ -0,0 +1,35 @@
+package com.dealer.app.config;
+
+import io.github.jhipster.config.locale.AngularCookieLocaleResolver;
+
+import org.springframework.context.EnvironmentAware;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+import org.springframework.web.servlet.LocaleResolver;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
+
+@Configuration
+public class LocaleConfiguration extends WebMvcConfigurerAdapter implements EnvironmentAware {
+
+ @Override
+ public void setEnvironment(Environment environment) {
+ // unused
+ }
+
+ @Bean(name = "localeResolver")
+ public LocaleResolver localeResolver() {
+ AngularCookieLocaleResolver cookieLocaleResolver = new AngularCookieLocaleResolver();
+ cookieLocaleResolver.setCookieName("NG_TRANSLATE_LANG_KEY");
+ return cookieLocaleResolver;
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
+ localeChangeInterceptor.setParamName("language");
+ registry.addInterceptor(localeChangeInterceptor);
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/LoggingAspectConfiguration.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/LoggingAspectConfiguration.java
new file mode 100644
index 0000000000..b530771a85
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/LoggingAspectConfiguration.java
@@ -0,0 +1,19 @@
+package com.dealer.app.config;
+
+import com.dealer.app.aop.logging.LoggingAspect;
+
+import io.github.jhipster.config.JHipsterConstants;
+
+import org.springframework.context.annotation.*;
+import org.springframework.core.env.Environment;
+
+@Configuration
+@EnableAspectJAutoProxy
+public class LoggingAspectConfiguration {
+
+ @Bean
+ @Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)
+ public LoggingAspect loggingAspect(Environment env) {
+ return new LoggingAspect(env);
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/LoggingConfiguration.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/LoggingConfiguration.java
new file mode 100644
index 0000000000..d7ad0602c4
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/LoggingConfiguration.java
@@ -0,0 +1,113 @@
+package com.dealer.app.config;
+
+import io.github.jhipster.config.JHipsterProperties;
+
+import ch.qos.logback.classic.AsyncAppender;
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.spi.LoggerContextListener;
+import ch.qos.logback.core.spi.ContextAwareBase;
+import net.logstash.logback.appender.LogstashSocketAppender;
+import net.logstash.logback.stacktrace.ShortenedThrowableConverter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class LoggingConfiguration {
+
+ private final Logger log = LoggerFactory.getLogger(LoggingConfiguration.class);
+
+ private LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
+
+ @Value("${spring.application.name}")
+ private String appName;
+
+ @Value("${server.port}")
+ private String serverPort;
+
+ @Value("${eureka.instance.instanceId}")
+ private String instanceId;
+
+ private final JHipsterProperties jHipsterProperties;
+
+ public LoggingConfiguration(JHipsterProperties jHipsterProperties) {
+ this.jHipsterProperties = jHipsterProperties;
+ if (jHipsterProperties.getLogging().getLogstash().isEnabled()) {
+ addLogstashAppender(context);
+
+ // Add context listener
+ LogbackLoggerContextListener loggerContextListener = new LogbackLoggerContextListener();
+ loggerContextListener.setContext(context);
+ context.addListener(loggerContextListener);
+ }
+ }
+
+ public void addLogstashAppender(LoggerContext context) {
+ log.info("Initializing Logstash logging");
+
+ LogstashSocketAppender logstashAppender = new LogstashSocketAppender();
+ logstashAppender.setName("LOGSTASH");
+ logstashAppender.setContext(context);
+ String customFields = "{\"app_name\":\"" + appName + "\",\"app_port\":\"" + serverPort + "\"," +
+ "\"instance_id\":\"" + instanceId + "\"}";
+
+ // Set the Logstash appender config from JHipster properties
+ logstashAppender.setSyslogHost(jHipsterProperties.getLogging().getLogstash().getHost());
+ logstashAppender.setPort(jHipsterProperties.getLogging().getLogstash().getPort());
+ logstashAppender.setCustomFields(customFields);
+
+ // Limit the maximum length of the forwarded stacktrace so that it won't exceed the 8KB UDP limit of logstash
+ ShortenedThrowableConverter throwableConverter = new ShortenedThrowableConverter();
+ throwableConverter.setMaxLength(7500);
+ throwableConverter.setRootCauseFirst(true);
+ logstashAppender.setThrowableConverter(throwableConverter);
+
+ logstashAppender.start();
+
+ // Wrap the appender in an Async appender for performance
+ AsyncAppender asyncLogstashAppender = new AsyncAppender();
+ asyncLogstashAppender.setContext(context);
+ asyncLogstashAppender.setName("ASYNC_LOGSTASH");
+ asyncLogstashAppender.setQueueSize(jHipsterProperties.getLogging().getLogstash().getQueueSize());
+ asyncLogstashAppender.addAppender(logstashAppender);
+ asyncLogstashAppender.start();
+
+ context.getLogger("ROOT").addAppender(asyncLogstashAppender);
+ }
+
+ /**
+ * Logback configuration is achieved by configuration file and API.
+ * When configuration file change is detected, the configuration is reset.
+ * This listener ensures that the programmatic configuration is also re-applied after reset.
+ */
+ class LogbackLoggerContextListener extends ContextAwareBase implements LoggerContextListener {
+
+ @Override
+ public boolean isResetResistant() {
+ return true;
+ }
+
+ @Override
+ public void onStart(LoggerContext context) {
+ addLogstashAppender(context);
+ }
+
+ @Override
+ public void onReset(LoggerContext context) {
+ addLogstashAppender(context);
+ }
+
+ @Override
+ public void onStop(LoggerContext context) {
+ // Nothing to do.
+ }
+
+ @Override
+ public void onLevelChange(ch.qos.logback.classic.Logger logger, Level level) {
+ // Nothing to do.
+ }
+ }
+
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/MetricsConfiguration.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/MetricsConfiguration.java
new file mode 100644
index 0000000000..54b8f2af32
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/MetricsConfiguration.java
@@ -0,0 +1,113 @@
+package com.dealer.app.config;
+
+import io.github.jhipster.config.JHipsterProperties;
+import io.github.jhipster.config.metrics.SpectatorLogMetricWriter;
+
+import com.netflix.spectator.api.Registry;
+import org.springframework.boot.actuate.autoconfigure.ExportMetricReader;
+import org.springframework.boot.actuate.autoconfigure.ExportMetricWriter;
+import org.springframework.boot.actuate.metrics.writer.MetricWriter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.cloud.netflix.metrics.spectator.SpectatorMetricReader;
+
+import com.codahale.metrics.JmxReporter;
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.Slf4jReporter;
+import com.codahale.metrics.health.HealthCheckRegistry;
+import com.codahale.metrics.jvm.*;
+import com.ryantenney.metrics.spring.config.annotation.EnableMetrics;
+import com.ryantenney.metrics.spring.config.annotation.MetricsConfigurerAdapter;
+import com.zaxxer.hikari.HikariDataSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.*;
+
+import javax.annotation.PostConstruct;
+import java.lang.management.ManagementFactory;
+import java.util.concurrent.TimeUnit;
+
+@Configuration
+@EnableMetrics(proxyTargetClass = true)
+public class MetricsConfiguration extends MetricsConfigurerAdapter {
+
+ private static final String PROP_METRIC_REG_JVM_MEMORY = "jvm.memory";
+ private static final String PROP_METRIC_REG_JVM_GARBAGE = "jvm.garbage";
+ private static final String PROP_METRIC_REG_JVM_THREADS = "jvm.threads";
+ private static final String PROP_METRIC_REG_JVM_FILES = "jvm.files";
+ private static final String PROP_METRIC_REG_JVM_BUFFERS = "jvm.buffers";
+ private final Logger log = LoggerFactory.getLogger(MetricsConfiguration.class);
+
+ private MetricRegistry metricRegistry = new MetricRegistry();
+
+ private HealthCheckRegistry healthCheckRegistry = new HealthCheckRegistry();
+
+ private final JHipsterProperties jHipsterProperties;
+
+ private HikariDataSource hikariDataSource;
+
+ public MetricsConfiguration(JHipsterProperties jHipsterProperties) {
+ this.jHipsterProperties = jHipsterProperties;
+ }
+
+ @Autowired(required = false)
+ public void setHikariDataSource(HikariDataSource hikariDataSource) {
+ this.hikariDataSource = hikariDataSource;
+ }
+
+ @Override
+ @Bean
+ public MetricRegistry getMetricRegistry() {
+ return metricRegistry;
+ }
+
+ @Override
+ @Bean
+ public HealthCheckRegistry getHealthCheckRegistry() {
+ return healthCheckRegistry;
+ }
+
+ @PostConstruct
+ public void init() {
+ log.debug("Registering JVM gauges");
+ metricRegistry.register(PROP_METRIC_REG_JVM_MEMORY, new MemoryUsageGaugeSet());
+ metricRegistry.register(PROP_METRIC_REG_JVM_GARBAGE, new GarbageCollectorMetricSet());
+ metricRegistry.register(PROP_METRIC_REG_JVM_THREADS, new ThreadStatesGaugeSet());
+ metricRegistry.register(PROP_METRIC_REG_JVM_FILES, new FileDescriptorRatioGauge());
+ metricRegistry.register(PROP_METRIC_REG_JVM_BUFFERS, new BufferPoolMetricSet(ManagementFactory.getPlatformMBeanServer()));
+ if (hikariDataSource != null) {
+ log.debug("Monitoring the datasource");
+ hikariDataSource.setMetricRegistry(metricRegistry);
+ }
+ if (jHipsterProperties.getMetrics().getJmx().isEnabled()) {
+ log.debug("Initializing Metrics JMX reporting");
+ JmxReporter jmxReporter = JmxReporter.forRegistry(metricRegistry).build();
+ jmxReporter.start();
+ }
+ if (jHipsterProperties.getMetrics().getLogs().isEnabled()) {
+ log.info("Initializing Metrics Log reporting");
+ final Slf4jReporter reporter = Slf4jReporter.forRegistry(metricRegistry)
+ .outputTo(LoggerFactory.getLogger("metrics"))
+ .convertRatesTo(TimeUnit.SECONDS)
+ .convertDurationsTo(TimeUnit.MILLISECONDS)
+ .build();
+ reporter.start(jHipsterProperties.getMetrics().getLogs().getReportFrequency(), TimeUnit.SECONDS);
+ }
+ }
+
+ /* Spectator metrics log reporting */
+ @Bean
+ @ConditionalOnProperty("jhipster.logging.spectator-metrics.enabled")
+ @ExportMetricReader
+ public SpectatorMetricReader SpectatorMetricReader(Registry registry) {
+ log.info("Initializing Spectator Metrics Log reporting");
+ return new SpectatorMetricReader(registry);
+ }
+
+ @Bean
+ @ConditionalOnProperty("jhipster.logging.spectator-metrics.enabled")
+ @ExportMetricWriter
+ MetricWriter metricWriter() {
+ return new SpectatorLogMetricWriter();
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/MicroserviceSecurityConfiguration.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/MicroserviceSecurityConfiguration.java
new file mode 100644
index 0000000000..86a109e91f
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/MicroserviceSecurityConfiguration.java
@@ -0,0 +1,71 @@
+package com.dealer.app.config;
+
+import com.dealer.app.security.AuthoritiesConstants;
+import com.dealer.app.security.jwt.JWTConfigurer;
+import com.dealer.app.security.jwt.TokenProvider;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.data.repository.query.SecurityEvaluationContextExtension;
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
+public class MicroserviceSecurityConfiguration extends WebSecurityConfigurerAdapter {
+
+ private final TokenProvider tokenProvider;
+
+ public MicroserviceSecurityConfiguration(TokenProvider tokenProvider) {
+ this.tokenProvider = tokenProvider;
+ }
+
+ @Override
+ public void configure(WebSecurity web) throws Exception {
+ web.ignoring()
+ .antMatchers(HttpMethod.OPTIONS, "/**")
+ .antMatchers("/app/**/*.{js,html}")
+ .antMatchers("/bower_components/**")
+ .antMatchers("/i18n/**")
+ .antMatchers("/content/**")
+ .antMatchers("/swagger-ui/index.html")
+ .antMatchers("/test/**")
+ .antMatchers("/h2-console/**");
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http
+ .csrf()
+ .disable()
+ .headers()
+ .frameOptions()
+ .disable()
+ .and()
+ .sessionManagement()
+ .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ .and()
+ .authorizeRequests()
+ .antMatchers("/api/**").authenticated()
+ .antMatchers("/management/health").permitAll()
+ .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
+ .antMatchers("/swagger-resources/configuration/ui").permitAll()
+ .and()
+ .apply(securityConfigurerAdapter());
+ }
+
+ private JWTConfigurer securityConfigurerAdapter() {
+ return new JWTConfigurer(tokenProvider);
+ }
+
+ @Bean
+ public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
+ return new SecurityEvaluationContextExtension();
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/ThymeleafConfiguration.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/ThymeleafConfiguration.java
new file mode 100644
index 0000000000..5bc92dd86d
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/ThymeleafConfiguration.java
@@ -0,0 +1,26 @@
+package com.dealer.app.config;
+
+import org.apache.commons.lang3.CharEncoding;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.*;
+import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
+
+@Configuration
+public class ThymeleafConfiguration {
+
+ @SuppressWarnings("unused")
+ private final Logger log = LoggerFactory.getLogger(ThymeleafConfiguration.class);
+
+ @Bean
+ @Description("Thymeleaf template resolver serving HTML 5 emails")
+ public ClassLoaderTemplateResolver emailTemplateResolver() {
+ ClassLoaderTemplateResolver emailTemplateResolver = new ClassLoaderTemplateResolver();
+ emailTemplateResolver.setPrefix("mails/");
+ emailTemplateResolver.setSuffix(".html");
+ emailTemplateResolver.setTemplateMode("HTML5");
+ emailTemplateResolver.setCharacterEncoding(CharEncoding.UTF_8);
+ emailTemplateResolver.setOrder(1);
+ return emailTemplateResolver;
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/WebConfigurer.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/WebConfigurer.java
new file mode 100644
index 0000000000..f34caa57d7
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/WebConfigurer.java
@@ -0,0 +1,144 @@
+package com.dealer.app.config;
+
+import io.github.jhipster.config.JHipsterConstants;
+import io.github.jhipster.config.JHipsterProperties;
+
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.servlet.InstrumentedFilter;
+import com.codahale.metrics.servlets.MetricsServlet;
+import com.hazelcast.core.HazelcastInstance;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.embedded.*;
+import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory;
+import io.undertow.UndertowOptions;
+import org.springframework.boot.web.servlet.ServletContextInitializer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+import java.util.*;
+import javax.servlet.*;
+
+/**
+ * Configuration of web application with Servlet 3.0 APIs.
+ */
+@Configuration
+public class WebConfigurer implements ServletContextInitializer, EmbeddedServletContainerCustomizer {
+
+ private final Logger log = LoggerFactory.getLogger(WebConfigurer.class);
+
+ private final Environment env;
+
+ private final JHipsterProperties jHipsterProperties;
+
+ private final HazelcastInstance hazelcastInstance;
+
+ private MetricRegistry metricRegistry;
+
+ public WebConfigurer(Environment env, JHipsterProperties jHipsterProperties, HazelcastInstance hazelcastInstance) {
+
+ this.env = env;
+ this.jHipsterProperties = jHipsterProperties;
+ this.hazelcastInstance = hazelcastInstance;
+ }
+
+ @Override
+ public void onStartup(ServletContext servletContext) throws ServletException {
+ if (env.getActiveProfiles().length != 0) {
+ log.info("Web application configuration, using profiles: {}", (Object[]) env.getActiveProfiles());
+ }
+ EnumSet disps = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.ASYNC);
+ initMetrics(servletContext, disps);
+ if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
+ initH2Console(servletContext);
+ }
+ log.info("Web application fully configured");
+ }
+
+ /**
+ * Customize the Servlet engine: Mime types, the document root, the cache.
+ */
+ @Override
+ public void customize(ConfigurableEmbeddedServletContainer container) {
+ MimeMappings mappings = new MimeMappings(MimeMappings.DEFAULT);
+ // IE issue, see https://github.com/jhipster/generator-jhipster/pull/711
+ mappings.add("html", "text/html;charset=utf-8");
+ // CloudFoundry issue, see https://github.com/cloudfoundry/gorouter/issues/64
+ mappings.add("json", "text/html;charset=utf-8");
+ container.setMimeMappings(mappings);
+
+ /*
+ * Enable HTTP/2 for Undertow - https://twitter.com/ankinson/status/829256167700492288
+ * HTTP/2 requires HTTPS, so HTTP requests will fallback to HTTP/1.1.
+ * See the JHipsterProperties class and your application-*.yml configuration files
+ * for more information.
+ */
+ if (jHipsterProperties.getHttp().getVersion().equals(JHipsterProperties.Http.Version.V_2_0) &&
+ container instanceof UndertowEmbeddedServletContainerFactory) {
+
+ ((UndertowEmbeddedServletContainerFactory) container)
+ .addBuilderCustomizers(builder ->
+ builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true));
+ }
+ }
+
+ /**
+ * Initializes Metrics.
+ */
+ private void initMetrics(ServletContext servletContext, EnumSet disps) {
+ log.debug("Initializing Metrics registries");
+ servletContext.setAttribute(InstrumentedFilter.REGISTRY_ATTRIBUTE,
+ metricRegistry);
+ servletContext.setAttribute(MetricsServlet.METRICS_REGISTRY,
+ metricRegistry);
+
+ log.debug("Registering Metrics Filter");
+ FilterRegistration.Dynamic metricsFilter = servletContext.addFilter("webappMetricsFilter",
+ new InstrumentedFilter());
+
+ metricsFilter.addMappingForUrlPatterns(disps, true, "/*");
+ metricsFilter.setAsyncSupported(true);
+
+ log.debug("Registering Metrics Servlet");
+ ServletRegistration.Dynamic metricsAdminServlet =
+ servletContext.addServlet("metricsServlet", new MetricsServlet());
+
+ metricsAdminServlet.addMapping("/management/metrics/*");
+ metricsAdminServlet.setAsyncSupported(true);
+ metricsAdminServlet.setLoadOnStartup(2);
+ }
+
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ CorsConfiguration config = jHipsterProperties.getCors();
+ if (config.getAllowedOrigins() != null && !config.getAllowedOrigins().isEmpty()) {
+ log.debug("Registering CORS filter");
+ source.registerCorsConfiguration("/api/**", config);
+ source.registerCorsConfiguration("/v2/api-docs", config);
+ }
+ return new CorsFilter(source);
+ }
+
+ /**
+ * Initializes H2 console.
+ */
+ private void initH2Console(ServletContext servletContext) {
+ log.debug("Initialize H2 console");
+ ServletRegistration.Dynamic h2ConsoleServlet = servletContext.addServlet("H2Console", new org.h2.server.web.WebServlet());
+ h2ConsoleServlet.addMapping("/h2-console/*");
+ h2ConsoleServlet.setInitParameter("-properties", "src/main/resources/");
+ h2ConsoleServlet.setLoadOnStartup(1);
+ }
+
+ @Autowired(required = false)
+ public void setMetricRegistry(MetricRegistry metricRegistry) {
+ this.metricRegistry = metricRegistry;
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/audit/AuditEventConverter.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/audit/AuditEventConverter.java
new file mode 100644
index 0000000000..6e04a2556f
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/audit/AuditEventConverter.java
@@ -0,0 +1,91 @@
+package com.dealer.app.config.audit;
+
+import com.dealer.app.domain.PersistentAuditEvent;
+
+import org.springframework.boot.actuate.audit.AuditEvent;
+import org.springframework.security.web.authentication.WebAuthenticationDetails;
+import org.springframework.stereotype.Component;
+
+import java.time.Instant;
+import java.time.ZoneId;
+import java.util.*;
+
+@Component
+public class AuditEventConverter {
+
+ /**
+ * Convert a list of PersistentAuditEvent to a list of AuditEvent
+ *
+ * @param persistentAuditEvents the list to convert
+ * @return the converted list.
+ */
+ public List convertToAuditEvent(Iterable persistentAuditEvents) {
+ if (persistentAuditEvents == null) {
+ return Collections.emptyList();
+ }
+ List auditEvents = new ArrayList<>();
+ for (PersistentAuditEvent persistentAuditEvent : persistentAuditEvents) {
+ auditEvents.add(convertToAuditEvent(persistentAuditEvent));
+ }
+ return auditEvents;
+ }
+
+ /**
+ * Convert a PersistentAuditEvent to an AuditEvent
+ *
+ * @param persistentAuditEvent the event to convert
+ * @return the converted list.
+ */
+ public AuditEvent convertToAuditEvent(PersistentAuditEvent persistentAuditEvent) {
+ Instant instant = persistentAuditEvent.getAuditEventDate().atZone(ZoneId.systemDefault()).toInstant();
+ return new AuditEvent(Date.from(instant), persistentAuditEvent.getPrincipal(),
+ persistentAuditEvent.getAuditEventType(), convertDataToObjects(persistentAuditEvent.getData()));
+ }
+
+ /**
+ * Internal conversion. This is needed to support the current SpringBoot actuator AuditEventRepository interface
+ *
+ * @param data the data to convert
+ * @return a map of String, Object
+ */
+ public Map convertDataToObjects(Map data) {
+ Map results = new HashMap<>();
+
+ if (data != null) {
+ for (Map.Entry entry : data.entrySet()) {
+ results.put(entry.getKey(), entry.getValue());
+ }
+ }
+ return results;
+ }
+
+ /**
+ * Internal conversion. This method will allow to save additional data.
+ * By default, it will save the object as string
+ *
+ * @param data the data to convert
+ * @return a map of String, String
+ */
+ public Map convertDataToStrings(Map data) {
+ Map results = new HashMap<>();
+
+ if (data != null) {
+ for (Map.Entry entry : data.entrySet()) {
+ Object object = entry.getValue();
+
+ // Extract the data that will be saved.
+ if (object instanceof WebAuthenticationDetails) {
+ WebAuthenticationDetails authenticationDetails = (WebAuthenticationDetails) object;
+ results.put("remoteAddress", authenticationDetails.getRemoteAddress());
+ results.put("sessionId", authenticationDetails.getSessionId());
+ } else if (object != null) {
+ results.put(entry.getKey(), object.toString());
+ } else {
+ results.put(entry.getKey(), "null");
+ }
+ }
+ }
+
+ return results;
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/audit/package-info.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/audit/package-info.java
new file mode 100644
index 0000000000..fb44326371
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/audit/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Audit specific code.
+ */
+package com.dealer.app.config.audit;
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/package-info.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/package-info.java
new file mode 100644
index 0000000000..bb4cb44cbf
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/config/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Spring Framework configuration files.
+ */
+package com.dealer.app.config;
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/domain/AbstractAuditingEntity.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/domain/AbstractAuditingEntity.java
new file mode 100644
index 0000000000..1bfb1025cc
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/domain/AbstractAuditingEntity.java
@@ -0,0 +1,80 @@
+package com.dealer.app.domain;
+
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import org.hibernate.envers.Audited;
+import org.springframework.data.annotation.CreatedBy;
+import org.springframework.data.annotation.CreatedDate;
+import org.springframework.data.annotation.LastModifiedBy;
+import org.springframework.data.annotation.LastModifiedDate;
+
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+import java.time.ZonedDateTime;
+import javax.persistence.Column;
+import javax.persistence.EntityListeners;
+import javax.persistence.MappedSuperclass;
+
+/**
+ * Base abstract class for entities which will hold definitions for created, last modified by and created,
+ * last modified by date.
+ */
+@MappedSuperclass
+@Audited
+@EntityListeners(AuditingEntityListener.class)
+public abstract class AbstractAuditingEntity implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @CreatedBy
+ @Column(name = "created_by", nullable = false, length = 50, updatable = false)
+ @JsonIgnore
+ private String createdBy;
+
+ @CreatedDate
+ @Column(name = "created_date", nullable = false)
+ @JsonIgnore
+ private ZonedDateTime createdDate = ZonedDateTime.now();
+
+ @LastModifiedBy
+ @Column(name = "last_modified_by", length = 50)
+ @JsonIgnore
+ private String lastModifiedBy;
+
+ @LastModifiedDate
+ @Column(name = "last_modified_date")
+ @JsonIgnore
+ private ZonedDateTime lastModifiedDate = ZonedDateTime.now();
+
+ public String getCreatedBy() {
+ return createdBy;
+ }
+
+ public void setCreatedBy(String createdBy) {
+ this.createdBy = createdBy;
+ }
+
+ public ZonedDateTime getCreatedDate() {
+ return createdDate;
+ }
+
+ public void setCreatedDate(ZonedDateTime createdDate) {
+ this.createdDate = createdDate;
+ }
+
+ public String getLastModifiedBy() {
+ return lastModifiedBy;
+ }
+
+ public void setLastModifiedBy(String lastModifiedBy) {
+ this.lastModifiedBy = lastModifiedBy;
+ }
+
+ public ZonedDateTime getLastModifiedDate() {
+ return lastModifiedDate;
+ }
+
+ public void setLastModifiedDate(ZonedDateTime lastModifiedDate) {
+ this.lastModifiedDate = lastModifiedDate;
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/domain/Dealer.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/domain/Dealer.java
new file mode 100644
index 0000000000..10c967a093
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/domain/Dealer.java
@@ -0,0 +1,92 @@
+package com.dealer.app.domain;
+
+import org.hibernate.annotations.Cache;
+import org.hibernate.annotations.CacheConcurrencyStrategy;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * A Dealer.
+ */
+@Entity
+@Table(name = "dealer")
+@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
+public class Dealer implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(name = "name")
+ private String name;
+
+ @Column(name = "address")
+ private String address;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Dealer name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public Dealer address(String address) {
+ this.address = address;
+ return this;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Dealer dealer = (Dealer) o;
+ if (dealer.id == null || id == null) {
+ return false;
+ }
+ return Objects.equals(id, dealer.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(id);
+ }
+
+ @Override
+ public String toString() {
+ return "Dealer{" +
+ "id=" + id +
+ ", name='" + name + "'" +
+ ", address='" + address + "'" +
+ '}';
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/domain/PersistentAuditEvent.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/domain/PersistentAuditEvent.java
new file mode 100644
index 0000000000..a5c02428a5
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/domain/PersistentAuditEvent.java
@@ -0,0 +1,78 @@
+package com.dealer.app.domain;
+
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import javax.persistence.*;
+import javax.validation.constraints.NotNull;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Persist AuditEvent managed by the Spring Boot actuator
+ * @see org.springframework.boot.actuate.audit.AuditEvent
+ */
+@Entity
+@Table(name = "jhi_persistent_audit_event")
+public class PersistentAuditEvent implements Serializable {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "event_id")
+ private Long id;
+
+ @NotNull
+ @Column(nullable = false)
+ private String principal;
+
+ @Column(name = "event_date")
+ private LocalDateTime auditEventDate;
+ @Column(name = "event_type")
+ private String auditEventType;
+
+ @ElementCollection
+ @MapKeyColumn(name = "name")
+ @Column(name = "value")
+ @CollectionTable(name = "jhi_persistent_audit_evt_data", joinColumns=@JoinColumn(name="event_id"))
+ private Map data = new HashMap<>();
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getPrincipal() {
+ return principal;
+ }
+
+ public void setPrincipal(String principal) {
+ this.principal = principal;
+ }
+
+ public LocalDateTime getAuditEventDate() {
+ return auditEventDate;
+ }
+
+ public void setAuditEventDate(LocalDateTime auditEventDate) {
+ this.auditEventDate = auditEventDate;
+ }
+
+ public String getAuditEventType() {
+ return auditEventType;
+ }
+
+ public void setAuditEventType(String auditEventType) {
+ this.auditEventType = auditEventType;
+ }
+
+ public Map getData() {
+ return data;
+ }
+
+ public void setData(Map data) {
+ this.data = data;
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/domain/package-info.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/domain/package-info.java
new file mode 100644
index 0000000000..0651edd7cc
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/domain/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * JPA domain objects.
+ */
+package com.dealer.app.domain;
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/repository/DealerRepository.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/repository/DealerRepository.java
new file mode 100644
index 0000000000..ff77d228a9
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/repository/DealerRepository.java
@@ -0,0 +1,15 @@
+package com.dealer.app.repository;
+
+import com.dealer.app.domain.Dealer;
+
+import org.springframework.data.jpa.repository.*;
+
+import java.util.List;
+
+/**
+ * Spring Data JPA repository for the Dealer entity.
+ */
+@SuppressWarnings("unused")
+public interface DealerRepository extends JpaRepository {
+
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/repository/package-info.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/repository/package-info.java
new file mode 100644
index 0000000000..93be9f265d
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/repository/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Spring Data JPA repositories.
+ */
+package com.dealer.app.repository;
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/security/AuthoritiesConstants.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/security/AuthoritiesConstants.java
new file mode 100644
index 0000000000..c4ade99d0e
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/security/AuthoritiesConstants.java
@@ -0,0 +1,16 @@
+package com.dealer.app.security;
+
+/**
+ * Constants for Spring Security authorities.
+ */
+public final class AuthoritiesConstants {
+
+ public static final String ADMIN = "ROLE_ADMIN";
+
+ public static final String USER = "ROLE_USER";
+
+ public static final String ANONYMOUS = "ROLE_ANONYMOUS";
+
+ private AuthoritiesConstants() {
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/security/SecurityUtils.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/security/SecurityUtils.java
new file mode 100644
index 0000000000..1b3c1e5c90
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/security/SecurityUtils.java
@@ -0,0 +1,68 @@
+package com.dealer.app.security;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+
+/**
+ * Utility class for Spring Security.
+ */
+public final class SecurityUtils {
+
+ private SecurityUtils() {
+ }
+
+ /**
+ * Get the login of the current user.
+ *
+ * @return the login of the current user
+ */
+ public static String getCurrentUserLogin() {
+ SecurityContext securityContext = SecurityContextHolder.getContext();
+ Authentication authentication = securityContext.getAuthentication();
+ String userName = null;
+ if (authentication != null) {
+ if (authentication.getPrincipal() instanceof UserDetails) {
+ UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal();
+ userName = springSecurityUser.getUsername();
+ } else if (authentication.getPrincipal() instanceof String) {
+ userName = (String) authentication.getPrincipal();
+ }
+ }
+ return userName;
+ }
+
+ /**
+ * Check if a user is authenticated.
+ *
+ * @return true if the user is authenticated, false otherwise
+ */
+ public static boolean isAuthenticated() {
+ SecurityContext securityContext = SecurityContextHolder.getContext();
+ Authentication authentication = securityContext.getAuthentication();
+ if (authentication != null) {
+ return authentication.getAuthorities().stream()
+ .noneMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(AuthoritiesConstants.ANONYMOUS));
+ }
+ return false;
+ }
+
+ /**
+ * If the current user has a specific authority (security role).
+ *
+ *
The name of this method comes from the isUserInRole() method in the Servlet API
+ *
+ * @param authority the authority to check
+ * @return true if the current user has the authority, false otherwise
+ */
+ public static boolean isCurrentUserInRole(String authority) {
+ SecurityContext securityContext = SecurityContextHolder.getContext();
+ Authentication authentication = securityContext.getAuthentication();
+ if (authentication != null) {
+ return authentication.getAuthorities().stream()
+ .anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(authority));
+ }
+ return false;
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/security/SpringSecurityAuditorAware.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/security/SpringSecurityAuditorAware.java
new file mode 100644
index 0000000000..72e518b1bc
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/security/SpringSecurityAuditorAware.java
@@ -0,0 +1,19 @@
+package com.dealer.app.security;
+
+import com.dealer.app.config.Constants;
+
+import org.springframework.data.domain.AuditorAware;
+import org.springframework.stereotype.Component;
+
+/**
+ * Implementation of AuditorAware based on Spring Security.
+ */
+@Component
+public class SpringSecurityAuditorAware implements AuditorAware {
+
+ @Override
+ public String getCurrentAuditor() {
+ String userName = SecurityUtils.getCurrentUserLogin();
+ return userName != null ? userName : Constants.SYSTEM_ACCOUNT;
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/security/jwt/JWTConfigurer.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/security/jwt/JWTConfigurer.java
new file mode 100644
index 0000000000..0f7b3cf164
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/security/jwt/JWTConfigurer.java
@@ -0,0 +1,23 @@
+package com.dealer.app.security.jwt;
+
+import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.web.DefaultSecurityFilterChain;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+public class JWTConfigurer extends SecurityConfigurerAdapter {
+
+ public static final String AUTHORIZATION_HEADER = "Authorization";
+
+ private TokenProvider tokenProvider;
+
+ public JWTConfigurer(TokenProvider tokenProvider) {
+ this.tokenProvider = tokenProvider;
+ }
+
+ @Override
+ public void configure(HttpSecurity http) throws Exception {
+ JWTFilter customFilter = new JWTFilter(tokenProvider);
+ http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/security/jwt/JWTFilter.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/security/jwt/JWTFilter.java
new file mode 100644
index 0000000000..55e22bd10a
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/security/jwt/JWTFilter.java
@@ -0,0 +1,58 @@
+package com.dealer.app.security.jwt;
+
+import java.io.IOException;
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.util.StringUtils;
+import org.springframework.web.filter.GenericFilterBean;
+
+import io.jsonwebtoken.ExpiredJwtException;
+
+/**
+ * Filters incoming requests and installs a Spring Security principal if a header corresponding to a valid user is
+ * found.
+ */
+public class JWTFilter extends GenericFilterBean {
+
+ private final Logger log = LoggerFactory.getLogger(JWTFilter.class);
+
+ private TokenProvider tokenProvider;
+
+ public JWTFilter(TokenProvider tokenProvider) {
+ this.tokenProvider = tokenProvider;
+ }
+
+ @Override
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
+ throws IOException, ServletException {
+ try {
+ HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
+ String jwt = resolveToken(httpServletRequest);
+ if (StringUtils.hasText(jwt) && this.tokenProvider.validateToken(jwt)) {
+ Authentication authentication = this.tokenProvider.getAuthentication(jwt);
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ }
+ filterChain.doFilter(servletRequest, servletResponse);
+ } catch (ExpiredJwtException eje) {
+ log.info("Security exception for user {} - {}",
+ eje.getClaims().getSubject(), eje.getMessage());
+
+ log.trace("Security exception trace: {}", eje);
+ ((HttpServletResponse) servletResponse).setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ }
+ }
+
+ private String resolveToken(HttpServletRequest request){
+ String bearerToken = request.getHeader(JWTConfigurer.AUTHORIZATION_HEADER);
+ if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
+ return bearerToken.substring(7, bearerToken.length());
+ }
+ return null;
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/security/jwt/TokenProvider.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/security/jwt/TokenProvider.java
new file mode 100644
index 0000000000..47a5bf75af
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/security/jwt/TokenProvider.java
@@ -0,0 +1,109 @@
+package com.dealer.app.security.jwt;
+
+import io.github.jhipster.config.JHipsterProperties;
+
+import java.util.*;
+import java.util.stream.Collectors;
+import javax.annotation.PostConstruct;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.stereotype.Component;
+
+import io.jsonwebtoken.*;
+
+@Component
+public class TokenProvider {
+
+ private final Logger log = LoggerFactory.getLogger(TokenProvider.class);
+
+ private static final String AUTHORITIES_KEY = "auth";
+
+ private String secretKey;
+
+ private long tokenValidityInMilliseconds;
+
+ private long tokenValidityInMillisecondsForRememberMe;
+
+ private final JHipsterProperties jHipsterProperties;
+
+ public TokenProvider(JHipsterProperties jHipsterProperties) {
+ this.jHipsterProperties = jHipsterProperties;
+ }
+
+ @PostConstruct
+ public void init() {
+ this.secretKey =
+ jHipsterProperties.getSecurity().getAuthentication().getJwt().getSecret();
+
+ this.tokenValidityInMilliseconds =
+ 1000 * jHipsterProperties.getSecurity().getAuthentication().getJwt().getTokenValidityInSeconds();
+ this.tokenValidityInMillisecondsForRememberMe =
+ 1000 * jHipsterProperties.getSecurity().getAuthentication().getJwt().getTokenValidityInSecondsForRememberMe();
+ }
+
+ public String createToken(Authentication authentication, Boolean rememberMe) {
+ String authorities = authentication.getAuthorities().stream()
+ .map(GrantedAuthority::getAuthority)
+ .collect(Collectors.joining(","));
+
+ long now = (new Date()).getTime();
+ Date validity;
+ if (rememberMe) {
+ validity = new Date(now + this.tokenValidityInMillisecondsForRememberMe);
+ } else {
+ validity = new Date(now + this.tokenValidityInMilliseconds);
+ }
+
+ return Jwts.builder()
+ .setSubject(authentication.getName())
+ .claim(AUTHORITIES_KEY, authorities)
+ .signWith(SignatureAlgorithm.HS512, secretKey)
+ .setExpiration(validity)
+ .compact();
+ }
+
+ public Authentication getAuthentication(String token) {
+ Claims claims = Jwts.parser()
+ .setSigningKey(secretKey)
+ .parseClaimsJws(token)
+ .getBody();
+
+ Collection extends GrantedAuthority> authorities =
+ Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(","))
+ .map(SimpleGrantedAuthority::new)
+ .collect(Collectors.toList());
+
+ User principal = new User(claims.getSubject(), "", authorities);
+
+ return new UsernamePasswordAuthenticationToken(principal, "", authorities);
+ }
+
+ public boolean validateToken(String authToken) {
+ try {
+ Jwts.parser().setSigningKey(secretKey).parseClaimsJws(authToken);
+ return true;
+ } catch (SignatureException e) {
+ log.info("Invalid JWT signature.");
+ log.trace("Invalid JWT signature trace: {}", e);
+ } catch (MalformedJwtException e) {
+ log.info("Invalid JWT token.");
+ log.trace("Invalid JWT token trace: {}", e);
+ } catch (ExpiredJwtException e) {
+ log.info("Expired JWT token.");
+ log.trace("Expired JWT token trace: {}", e);
+ } catch (UnsupportedJwtException e) {
+ log.info("Unsupported JWT token.");
+ log.trace("Unsupported JWT token trace: {}", e);
+ } catch (IllegalArgumentException e) {
+ log.info("JWT token compact of handler are invalid.");
+ log.trace("JWT token compact of handler are invalid trace: {}", e);
+ }
+ return false;
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/service/package-info.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/service/package-info.java
new file mode 100644
index 0000000000..b6795f34a3
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/service/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Service layer beans.
+ */
+package com.dealer.app.service;
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/DealerResource.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/DealerResource.java
new file mode 100644
index 0000000000..bd49b3d179
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/DealerResource.java
@@ -0,0 +1,128 @@
+package com.dealer.app.web.rest;
+
+import com.codahale.metrics.annotation.Timed;
+import com.dealer.app.domain.Dealer;
+
+import com.dealer.app.repository.DealerRepository;
+import com.dealer.app.web.rest.util.HeaderUtil;
+import com.dealer.app.web.rest.util.PaginationUtil;
+import io.swagger.annotations.ApiParam;
+import io.github.jhipster.web.util.ResponseUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * REST controller for managing Dealer.
+ */
+@RestController
+@RequestMapping("/api")
+public class DealerResource {
+
+ private final Logger log = LoggerFactory.getLogger(DealerResource.class);
+
+ private static final String ENTITY_NAME = "dealer";
+
+ private final DealerRepository dealerRepository;
+
+ public DealerResource(DealerRepository dealerRepository) {
+ this.dealerRepository = dealerRepository;
+ }
+
+ /**
+ * POST /dealers : Create a new dealer.
+ *
+ * @param dealer the dealer to create
+ * @return the ResponseEntity with status 201 (Created) and with body the new dealer, or with status 400 (Bad Request) if the dealer has already an ID
+ * @throws URISyntaxException if the Location URI syntax is incorrect
+ */
+ @PostMapping("/dealers")
+ @Timed
+ public ResponseEntity createDealer(@RequestBody Dealer dealer) throws URISyntaxException {
+ log.debug("REST request to save Dealer : {}", dealer);
+ if (dealer.getId() != null) {
+ return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert(ENTITY_NAME, "idexists", "A new dealer cannot already have an ID")).body(null);
+ }
+ Dealer result = dealerRepository.save(dealer);
+ return ResponseEntity.created(new URI("/api/dealers/" + result.getId()))
+ .headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString()))
+ .body(result);
+ }
+
+ /**
+ * PUT /dealers : Updates an existing dealer.
+ *
+ * @param dealer the dealer to update
+ * @return the ResponseEntity with status 200 (OK) and with body the updated dealer,
+ * or with status 400 (Bad Request) if the dealer is not valid,
+ * or with status 500 (Internal Server Error) if the dealer couldnt be updated
+ * @throws URISyntaxException if the Location URI syntax is incorrect
+ */
+ @PutMapping("/dealers")
+ @Timed
+ public ResponseEntity updateDealer(@RequestBody Dealer dealer) throws URISyntaxException {
+ log.debug("REST request to update Dealer : {}", dealer);
+ if (dealer.getId() == null) {
+ return createDealer(dealer);
+ }
+ Dealer result = dealerRepository.save(dealer);
+ return ResponseEntity.ok()
+ .headers(HeaderUtil.createEntityUpdateAlert(ENTITY_NAME, dealer.getId().toString()))
+ .body(result);
+ }
+
+ /**
+ * GET /dealers : get all the dealers.
+ *
+ * @param pageable the pagination information
+ * @return the ResponseEntity with status 200 (OK) and the list of dealers in body
+ * @throws URISyntaxException if there is an error to generate the pagination HTTP headers
+ */
+ @GetMapping("/dealers")
+ @Timed
+ public ResponseEntity> getAllDealers(@ApiParam Pageable pageable) {
+ log.debug("REST request to get a page of Dealers");
+ Page page = dealerRepository.findAll(pageable);
+ HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/dealers");
+ return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
+ }
+
+ /**
+ * GET /dealers/:id : get the "id" dealer.
+ *
+ * @param id the id of the dealer to retrieve
+ * @return the ResponseEntity with status 200 (OK) and with body the dealer, or with status 404 (Not Found)
+ */
+ @GetMapping("/dealers/{id}")
+ @Timed
+ public ResponseEntity getDealer(@PathVariable Long id) {
+ log.debug("REST request to get Dealer : {}", id);
+ Dealer dealer = dealerRepository.findOne(id);
+ return ResponseUtil.wrapOrNotFound(Optional.ofNullable(dealer));
+ }
+
+ /**
+ * DELETE /dealers/:id : delete the "id" dealer.
+ *
+ * @param id the id of the dealer to delete
+ * @return the ResponseEntity with status 200 (OK)
+ */
+ @DeleteMapping("/dealers/{id}")
+ @Timed
+ public ResponseEntity deleteDealer(@PathVariable Long id) {
+ log.debug("REST request to delete Dealer : {}", id);
+ dealerRepository.delete(id);
+ return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert(ENTITY_NAME, id.toString())).build();
+ }
+
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/LogsResource.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/LogsResource.java
new file mode 100644
index 0000000000..844fdfe7bb
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/LogsResource.java
@@ -0,0 +1,39 @@
+package com.dealer.app.web.rest;
+
+import com.dealer.app.web.rest.vm.LoggerVM;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.LoggerContext;
+import com.codahale.metrics.annotation.Timed;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Controller for view and managing Log Level at runtime.
+ */
+@RestController
+@RequestMapping("/management")
+public class LogsResource {
+
+ @GetMapping("/logs")
+ @Timed
+ public List getList() {
+ LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
+ return context.getLoggerList()
+ .stream()
+ .map(LoggerVM::new)
+ .collect(Collectors.toList());
+ }
+
+ @PutMapping("/logs")
+ @ResponseStatus(HttpStatus.NO_CONTENT)
+ @Timed
+ public void changeLevel(@RequestBody LoggerVM jsonLogger) {
+ LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
+ context.getLogger(jsonLogger.getName()).setLevel(Level.valueOf(jsonLogger.getLevel()));
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/ProfileInfoResource.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/ProfileInfoResource.java
new file mode 100644
index 0000000000..4c2d37b3ff
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/ProfileInfoResource.java
@@ -0,0 +1,69 @@
+package com.dealer.app.web.rest;
+
+import com.dealer.app.config.DefaultProfileUtil;
+
+import io.github.jhipster.config.JHipsterProperties;
+
+import org.springframework.core.env.Environment;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Resource to return information about the currently running Spring profiles.
+ */
+@RestController
+@RequestMapping("/api")
+public class ProfileInfoResource {
+
+ private final Environment env;
+
+ private final JHipsterProperties jHipsterProperties;
+
+ public ProfileInfoResource(Environment env, JHipsterProperties jHipsterProperties) {
+ this.env = env;
+ this.jHipsterProperties = jHipsterProperties;
+ }
+
+ @GetMapping("/profile-info")
+ public ProfileInfoVM getActiveProfiles() {
+ String[] activeProfiles = DefaultProfileUtil.getActiveProfiles(env);
+ return new ProfileInfoVM(activeProfiles, getRibbonEnv(activeProfiles));
+ }
+
+ private String getRibbonEnv(String[] activeProfiles) {
+ String[] displayOnActiveProfiles = jHipsterProperties.getRibbon().getDisplayOnActiveProfiles();
+ if (displayOnActiveProfiles == null) {
+ return null;
+ }
+ List ribbonProfiles = new ArrayList<>(Arrays.asList(displayOnActiveProfiles));
+ List springBootProfiles = Arrays.asList(activeProfiles);
+ ribbonProfiles.retainAll(springBootProfiles);
+ if (!ribbonProfiles.isEmpty()) {
+ return ribbonProfiles.get(0);
+ }
+ return null;
+ }
+
+ class ProfileInfoVM {
+
+ private String[] activeProfiles;
+
+ private String ribbonEnv;
+
+ ProfileInfoVM(String[] activeProfiles, String ribbonEnv) {
+ this.activeProfiles = activeProfiles;
+ this.ribbonEnv = ribbonEnv;
+ }
+
+ public String[] getActiveProfiles() {
+ return activeProfiles;
+ }
+
+ public String getRibbonEnv() {
+ return ribbonEnv;
+ }
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/errors/CustomParameterizedException.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/errors/CustomParameterizedException.java
new file mode 100644
index 0000000000..3897d94eba
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/errors/CustomParameterizedException.java
@@ -0,0 +1,34 @@
+package com.dealer.app.web.rest.errors;
+
+/**
+ * Custom, parameterized exception, which can be translated on the client side.
+ * For example:
+ *
+ *
+ * throw new CustomParameterizedException("myCustomError", "hello", "world");
+ *
+ *
+ * Can be translated with:
+ *
+ *
+ * "error.myCustomError" : "The server says {{params[0]}} to {{params[1]}}"
+ *
+ */
+public class CustomParameterizedException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String message;
+ private final String[] params;
+
+ public CustomParameterizedException(String message, String... params) {
+ super(message);
+ this.message = message;
+ this.params = params;
+ }
+
+ public ParameterizedErrorVM getErrorVM() {
+ return new ParameterizedErrorVM(message, params);
+ }
+
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/errors/ErrorConstants.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/errors/ErrorConstants.java
new file mode 100644
index 0000000000..4ace18012e
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/errors/ErrorConstants.java
@@ -0,0 +1,14 @@
+package com.dealer.app.web.rest.errors;
+
+public final class ErrorConstants {
+
+ public static final String ERR_CONCURRENCY_FAILURE = "error.concurrencyFailure";
+ public static final String ERR_ACCESS_DENIED = "error.accessDenied";
+ public static final String ERR_VALIDATION = "error.validation";
+ public static final String ERR_METHOD_NOT_SUPPORTED = "error.methodNotSupported";
+ public static final String ERR_INTERNAL_SERVER_ERROR = "error.internalServerError";
+
+ private ErrorConstants() {
+ }
+
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/errors/ErrorVM.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/errors/ErrorVM.java
new file mode 100644
index 0000000000..4f242f21e8
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/errors/ErrorVM.java
@@ -0,0 +1,52 @@
+package com.dealer.app.web.rest.errors;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * View Model for transferring error message with a list of field errors.
+ */
+public class ErrorVM implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String message;
+ private final String description;
+
+ private List fieldErrors;
+
+ public ErrorVM(String message) {
+ this(message, null);
+ }
+
+ public ErrorVM(String message, String description) {
+ this.message = message;
+ this.description = description;
+ }
+
+ public ErrorVM(String message, String description, List fieldErrors) {
+ this.message = message;
+ this.description = description;
+ this.fieldErrors = fieldErrors;
+ }
+
+ public void add(String objectName, String field, String message) {
+ if (fieldErrors == null) {
+ fieldErrors = new ArrayList<>();
+ }
+ fieldErrors.add(new FieldErrorVM(objectName, field, message));
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public List getFieldErrors() {
+ return fieldErrors;
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/errors/ExceptionTranslator.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/errors/ExceptionTranslator.java
new file mode 100644
index 0000000000..17b1dc6c62
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/errors/ExceptionTranslator.java
@@ -0,0 +1,85 @@
+package com.dealer.app.web.rest.errors;
+
+import java.util.List;
+
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.dao.ConcurrencyFailureException;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.ResponseEntity.BodyBuilder;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.FieldError;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * Controller advice to translate the server side exceptions to client-friendly json structures.
+ */
+@ControllerAdvice
+public class ExceptionTranslator {
+
+ @ExceptionHandler(ConcurrencyFailureException.class)
+ @ResponseStatus(HttpStatus.CONFLICT)
+ @ResponseBody
+ public ErrorVM processConcurrencyError(ConcurrencyFailureException ex) {
+ return new ErrorVM(ErrorConstants.ERR_CONCURRENCY_FAILURE);
+ }
+
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ResponseBody
+ public ErrorVM processValidationError(MethodArgumentNotValidException ex) {
+ BindingResult result = ex.getBindingResult();
+ List fieldErrors = result.getFieldErrors();
+
+ return processFieldErrors(fieldErrors);
+ }
+
+ @ExceptionHandler(CustomParameterizedException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ResponseBody
+ public ParameterizedErrorVM processParameterizedValidationError(CustomParameterizedException ex) {
+ return ex.getErrorVM();
+ }
+
+ @ExceptionHandler(AccessDeniedException.class)
+ @ResponseStatus(HttpStatus.FORBIDDEN)
+ @ResponseBody
+ public ErrorVM processAccessDeniedException(AccessDeniedException e) {
+ return new ErrorVM(ErrorConstants.ERR_ACCESS_DENIED, e.getMessage());
+ }
+
+ private ErrorVM processFieldErrors(List fieldErrors) {
+ ErrorVM dto = new ErrorVM(ErrorConstants.ERR_VALIDATION);
+
+ for (FieldError fieldError : fieldErrors) {
+ dto.add(fieldError.getObjectName(), fieldError.getField(), fieldError.getCode());
+ }
+
+ return dto;
+ }
+
+ @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
+ @ResponseBody
+ @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
+ public ErrorVM processMethodNotSupportedException(HttpRequestMethodNotSupportedException exception) {
+ return new ErrorVM(ErrorConstants.ERR_METHOD_NOT_SUPPORTED, exception.getMessage());
+ }
+
+ @ExceptionHandler(Exception.class)
+ public ResponseEntity processRuntimeException(Exception ex) {
+ BodyBuilder builder;
+ ErrorVM errorVM;
+ ResponseStatus responseStatus = AnnotationUtils.findAnnotation(ex.getClass(), ResponseStatus.class);
+ if (responseStatus != null) {
+ builder = ResponseEntity.status(responseStatus.value());
+ errorVM = new ErrorVM("error." + responseStatus.value().value(), responseStatus.reason());
+ } else {
+ builder = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR);
+ errorVM = new ErrorVM(ErrorConstants.ERR_INTERNAL_SERVER_ERROR, "Internal server error");
+ }
+ return builder.body(errorVM);
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/errors/FieldErrorVM.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/errors/FieldErrorVM.java
new file mode 100644
index 0000000000..036e358f41
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/errors/FieldErrorVM.java
@@ -0,0 +1,33 @@
+package com.dealer.app.web.rest.errors;
+
+import java.io.Serializable;
+
+public class FieldErrorVM implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String objectName;
+
+ private final String field;
+
+ private final String message;
+
+ public FieldErrorVM(String dto, String field, String message) {
+ this.objectName = dto;
+ this.field = field;
+ this.message = message;
+ }
+
+ public String getObjectName() {
+ return objectName;
+ }
+
+ public String getField() {
+ return field;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/errors/ParameterizedErrorVM.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/errors/ParameterizedErrorVM.java
new file mode 100644
index 0000000000..7b0d4f23fa
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/errors/ParameterizedErrorVM.java
@@ -0,0 +1,27 @@
+package com.dealer.app.web.rest.errors;
+
+import java.io.Serializable;
+
+/**
+ * View Model for sending a parameterized error message.
+ */
+public class ParameterizedErrorVM implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ private final String message;
+ private final String[] params;
+
+ public ParameterizedErrorVM(String message, String... params) {
+ this.message = message;
+ this.params = params;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public String[] getParams() {
+ return params;
+ }
+
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/package-info.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/package-info.java
new file mode 100644
index 0000000000..20c6b71ccc
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Spring MVC REST controllers.
+ */
+package com.dealer.app.web.rest;
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/util/HeaderUtil.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/util/HeaderUtil.java
new file mode 100644
index 0000000000..63efc36663
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/util/HeaderUtil.java
@@ -0,0 +1,43 @@
+package com.dealer.app.web.rest.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpHeaders;
+
+/**
+ * Utility class for HTTP headers creation.
+ */
+public final class HeaderUtil {
+
+ private static final Logger log = LoggerFactory.getLogger(HeaderUtil.class);
+
+ private HeaderUtil() {
+ }
+
+ public static HttpHeaders createAlert(String message, String param) {
+ HttpHeaders headers = new HttpHeaders();
+ headers.add("X-dealerappApp-alert", message);
+ headers.add("X-dealerappApp-params", param);
+ return headers;
+ }
+
+ public static HttpHeaders createEntityCreationAlert(String entityName, String param) {
+ return createAlert("A new " + entityName + " is created with identifier " + param, param);
+ }
+
+ public static HttpHeaders createEntityUpdateAlert(String entityName, String param) {
+ return createAlert("A " + entityName + " is updated with identifier " + param, param);
+ }
+
+ public static HttpHeaders createEntityDeletionAlert(String entityName, String param) {
+ return createAlert("A " + entityName + " is deleted with identifier " + param, param);
+ }
+
+ public static HttpHeaders createFailureAlert(String entityName, String errorKey, String defaultMessage) {
+ log.error("Entity creation failed, {}", defaultMessage);
+ HttpHeaders headers = new HttpHeaders();
+ headers.add("X-dealerappApp-error", defaultMessage);
+ headers.add("X-dealerappApp-params", entityName);
+ return headers;
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/util/PaginationUtil.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/util/PaginationUtil.java
new file mode 100644
index 0000000000..39b7eae434
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/util/PaginationUtil.java
@@ -0,0 +1,47 @@
+package com.dealer.app.web.rest.util;
+
+import org.springframework.data.domain.Page;
+import org.springframework.http.HttpHeaders;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import java.net.URISyntaxException;
+
+/**
+ * Utility class for handling pagination.
+ *
+ *
+ * Pagination uses the same principles as the Github API,
+ * and follow RFC 5988 (Link header).
+ */
+public final class PaginationUtil {
+
+ private PaginationUtil() {
+ }
+
+ public static HttpHeaders generatePaginationHttpHeaders(Page page, String baseUrl) {
+
+ HttpHeaders headers = new HttpHeaders();
+ headers.add("X-Total-Count", "" + Long.toString(page.getTotalElements()));
+ String link = "";
+ if ((page.getNumber() + 1) < page.getTotalPages()) {
+ link = "<" + generateUri(baseUrl, page.getNumber() + 1, page.getSize()) + ">; rel=\"next\",";
+ }
+ // prev link
+ if ((page.getNumber()) > 0) {
+ link += "<" + generateUri(baseUrl, page.getNumber() - 1, page.getSize()) + ">; rel=\"prev\",";
+ }
+ // last and first link
+ int lastPage = 0;
+ if (page.getTotalPages() > 0) {
+ lastPage = page.getTotalPages() - 1;
+ }
+ link += "<" + generateUri(baseUrl, lastPage, page.getSize()) + ">; rel=\"last\",";
+ link += "<" + generateUri(baseUrl, 0, page.getSize()) + ">; rel=\"first\"";
+ headers.add(HttpHeaders.LINK, link);
+ return headers;
+ }
+
+ private static String generateUri(String baseUrl, int page, int size) {
+ return UriComponentsBuilder.fromUriString(baseUrl).queryParam("page", page).queryParam("size", size).toUriString();
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/vm/LoggerVM.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/vm/LoggerVM.java
new file mode 100644
index 0000000000..82afc8c883
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/vm/LoggerVM.java
@@ -0,0 +1,48 @@
+package com.dealer.app.web.rest.vm;
+
+import ch.qos.logback.classic.Logger;
+import com.fasterxml.jackson.annotation.JsonCreator;
+
+/**
+ * View Model object for storing a Logback logger.
+ */
+public class LoggerVM {
+
+ private String name;
+
+ private String level;
+
+ public LoggerVM(Logger logger) {
+ this.name = logger.getName();
+ this.level = logger.getEffectiveLevel().toString();
+ }
+
+ @JsonCreator
+ public LoggerVM() {
+ // Empty public constructor used by Jackson.
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getLevel() {
+ return level;
+ }
+
+ public void setLevel(String level) {
+ this.level = level;
+ }
+
+ @Override
+ public String toString() {
+ return "LoggerVM{" +
+ "name='" + name + '\'' +
+ ", level='" + level + '\'' +
+ '}';
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/vm/package-info.java b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/vm/package-info.java
new file mode 100644
index 0000000000..563901498e
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/java/com/dealer/app/web/rest/vm/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * View Models used by Spring MVC REST controllers.
+ */
+package com.dealer.app.web.rest.vm;
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/resources/.h2.server.properties b/jhipster/jhipster-microservice/dealer-app/src/main/resources/.h2.server.properties
new file mode 100644
index 0000000000..8d8f192ac0
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/resources/.h2.server.properties
@@ -0,0 +1,5 @@
+#H2 Server Properties
+0=JHipster H2 (Disk)|org.h2.Driver|jdbc\:h2\:file\:./target/h2db/db/dealerapp|dealerapp
+webAllowOthers=true
+webPort=8082
+webSSL=false
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/resources/banner.txt b/jhipster/jhipster-microservice/dealer-app/src/main/resources/banner.txt
new file mode 100644
index 0000000000..c3d8cf725d
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/resources/banner.txt
@@ -0,0 +1,10 @@
+
+ ${AnsiColor.GREEN} ██╗${AnsiColor.RED} ██╗ ██╗ ████████╗ ███████╗ ██████╗ ████████╗ ████████╗ ███████╗
+ ${AnsiColor.GREEN} ██║${AnsiColor.RED} ██║ ██║ ╚══██╔══╝ ██╔═══██╗ ██╔════╝ ╚══██╔══╝ ██╔═════╝ ██╔═══██╗
+ ${AnsiColor.GREEN} ██║${AnsiColor.RED} ████████║ ██║ ███████╔╝ ╚█████╗ ██║ ██████╗ ███████╔╝
+ ${AnsiColor.GREEN}██╗ ██║${AnsiColor.RED} ██╔═══██║ ██║ ██╔════╝ ╚═══██╗ ██║ ██╔═══╝ ██╔══██║
+ ${AnsiColor.GREEN}╚██████╔╝${AnsiColor.RED} ██║ ██║ ████████╗ ██║ ██████╔╝ ██║ ████████╗ ██║ ╚██╗
+ ${AnsiColor.GREEN} ╚═════╝ ${AnsiColor.RED} ╚═╝ ╚═╝ ╚═══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══════╝ ╚═╝ ╚═╝
+
+${AnsiColor.BRIGHT_BLUE}:: JHipster 🤓 :: Running Spring Boot ${spring-boot.version} ::
+:: http://jhipster.github.io ::${AnsiColor.DEFAULT}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/application-dev.yml b/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/application-dev.yml
new file mode 100644
index 0000000000..7231a7cfa9
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/application-dev.yml
@@ -0,0 +1,148 @@
+# ===================================================================
+# Spring Boot configuration for the "dev" profile.
+#
+# This configuration overrides the application.yml file.
+#
+# More information on profiles: https://jhipster.github.io/profiles/
+# More information on configuration properties: https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+# ===================================================================
+# Standard Spring Boot properties.
+# Full reference is available at:
+# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
+# ===================================================================
+
+eureka:
+ instance:
+ prefer-ip-address: true
+ client:
+ enabled: true
+ healthcheck:
+ enabled: true
+ registerWithEureka: true
+ fetchRegistry: true
+ serviceUrl:
+ defaultZone: http://admin:${jhipster.registry.password}@localhost:8761/eureka/
+
+spring:
+ profiles:
+ active: dev
+ include: swagger
+ devtools:
+ restart:
+ enabled: true
+ livereload:
+ enabled: false # we use gulp + BrowserSync for livereload
+ jackson:
+ serialization.indent_output: true
+ datasource:
+ type: com.zaxxer.hikari.HikariDataSource
+ url: jdbc:h2:file:./target/h2db/db/dealerapp;DB_CLOSE_DELAY=-1
+ username: dealerapp
+ password:
+ h2:
+ console:
+ enabled: false
+ jpa:
+ database-platform: io.github.jhipster.domain.util.FixedH2Dialect
+ database: H2
+ show-sql: true
+ properties:
+ hibernate.id.new_generator_mappings: true
+ hibernate.cache.use_second_level_cache: true
+ hibernate.cache.use_query_cache: false
+ hibernate.generate_statistics: true
+ hibernate.cache.region.factory_class: com.hazelcast.hibernate.HazelcastCacheRegionFactory
+ hibernate.cache.hazelcast.instance_name: dealerapp
+ hibernate.cache.use_minimal_puts: true
+ hibernate.cache.hazelcast.use_lite_member: true
+ mail:
+ host: localhost
+ port: 25
+ username:
+ password:
+ messages:
+ cache-seconds: 1
+ thymeleaf:
+ cache: false
+
+liquibase:
+ contexts: dev
+
+# ===================================================================
+# To enable SSL, generate a certificate using:
+# keytool -genkey -alias dealerapp -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650
+#
+# You can also use Let's Encrypt:
+# https://maximilian-boehm.com/hp2121/Create-a-Java-Keystore-JKS-from-Let-s-Encrypt-Certificates.htm
+#
+# Then, modify the server.ssl properties so your "server" configuration looks like:
+#
+# server:
+# port: 8443
+# ssl:
+# key-store: keystore.p12
+# key-store-password:
+# keyStoreType: PKCS12
+# keyAlias: dealerapp
+# ===================================================================
+server:
+ port: 8082
+
+# ===================================================================
+# JHipster specific properties
+#
+# Full reference is available at: https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+jhipster:
+ http:
+ version: V_1_1 # To use HTTP/2 you will need SSL support (see above the "server.ssl" configuration)
+ cache: # Cache configuration
+ hazelcast: # Hazelcast distributed cache
+ time-to-live-seconds: 3600
+ backup-count: 1
+ security:
+ authentication:
+ jwt:
+ secret: my-secret-token-to-change-in-production
+ # Token is valid 24 hours
+ token-validity-in-seconds: 86400
+ token-validity-in-seconds-for-remember-me: 2592000
+ mail: # specific JHipster mail property, for standard properties see MailProperties
+ from: dealerapp@localhost
+ base-url: http://127.0.0.1:8082
+ metrics: # DropWizard Metrics configuration, used by MetricsConfiguration
+ jmx.enabled: true
+ graphite: # Use the "graphite" Maven profile to have the Graphite dependencies
+ enabled: false
+ host: localhost
+ port: 2003
+ prefix: dealerapp
+ prometheus: # Use the "prometheus" Maven profile to have the Prometheus dependencies
+ enabled: false
+ endpoint: /prometheusMetrics
+ logs: # Reports Dropwizard metrics in the logs
+ enabled: false
+ reportFrequency: 60 # in seconds
+ logging:
+ logstash: # Forward logs to logstash over a socket, used by LoggingConfiguration
+ enabled: false
+ host: localhost
+ port: 5000
+ queue-size: 512
+ spectator-metrics: # Reports Spectator Circuit Breaker metrics in the logs
+ enabled: false
+ # edit spring.metrics.export.delay-millis to set report frequency
+
+# ===================================================================
+# Application specific properties
+# Add your own application properties here, see the ApplicationProperties class
+# to have type-safe configuration, like in the JHipsterProperties above
+#
+# More documentation is available at:
+# https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+application:
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/application-prod.yml b/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/application-prod.yml
new file mode 100644
index 0000000000..8c14e671ea
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/application-prod.yml
@@ -0,0 +1,150 @@
+# ===================================================================
+# Spring Boot configuration for the "prod" profile.
+#
+# This configuration overrides the application.yml file.
+#
+# More information on profiles: https://jhipster.github.io/profiles/
+# More information on configuration properties: https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+# ===================================================================
+# Standard Spring Boot properties.
+# Full reference is available at:
+# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
+# ===================================================================
+
+eureka:
+ instance:
+ prefer-ip-address: true
+ client:
+ enabled: true
+ healthcheck:
+ enabled: true
+ registerWithEureka: true
+ fetchRegistry: true
+ serviceUrl:
+ defaultZone: http://admin:${jhipster.registry.password}@localhost:8761/eureka/
+
+spring:
+ devtools:
+ restart:
+ enabled: false
+ livereload:
+ enabled: false
+ datasource:
+ type: com.zaxxer.hikari.HikariDataSource
+ url: jdbc:mysql://localhost:3306/dealerapp?useUnicode=true&characterEncoding=utf8&useSSL=false
+ username: root
+ password:
+ hikari:
+ data-source-properties:
+ cachePrepStmts: true
+ prepStmtCacheSize: 250
+ prepStmtCacheSqlLimit: 2048
+ useServerPrepStmts: true
+ jpa:
+ database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
+ database: MYSQL
+ show-sql: false
+ properties:
+ hibernate.id.new_generator_mappings: true
+ hibernate.cache.use_second_level_cache: true
+ hibernate.cache.use_query_cache: false
+ hibernate.generate_statistics: false
+ hibernate.cache.region.factory_class: com.hazelcast.hibernate.HazelcastCacheRegionFactory
+ hibernate.cache.hazelcast.instance_name: dealerapp
+ hibernate.cache.use_minimal_puts: true
+ hibernate.cache.hazelcast.use_lite_member: true
+ mail:
+ host: localhost
+ port: 25
+ username:
+ password:
+ thymeleaf:
+ cache: true
+
+liquibase:
+ contexts: prod
+
+# ===================================================================
+# To enable SSL, generate a certificate using:
+# keytool -genkey -alias dealerapp -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650
+#
+# You can also use Let's Encrypt:
+# https://maximilian-boehm.com/hp2121/Create-a-Java-Keystore-JKS-from-Let-s-Encrypt-Certificates.htm
+#
+# Then, modify the server.ssl properties so your "server" configuration looks like:
+#
+# server:
+# port: 443
+# ssl:
+# key-store: keystore.p12
+# key-store-password:
+# keyStoreType: PKCS12
+# keyAlias: dealerapp
+# ===================================================================
+server:
+ port: 8082
+ compression:
+ enabled: true
+ mime-types: text/html,text/xml,text/plain,text/css, application/javascript, application/json
+ min-response-size: 1024
+
+# ===================================================================
+# JHipster specific properties
+#
+# Full reference is available at: https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+jhipster:
+ http:
+ version: V_1_1 # To use HTTP/2 you will need SSL support (see above the "server.ssl" configuration)
+ cache: # Used by the CachingHttpHeadersFilter
+ timeToLiveInDays: 1461
+ cache: # Cache configuration
+ hazelcast: # Hazelcast distributed cache
+ time-to-live-seconds: 3600
+ backup-count: 1
+ security:
+ authentication:
+ jwt:
+ secret: d4c73e937677223a85c7fcebae7a6ce0c48c3b01
+ # Token is valid 24 hours
+ token-validity-in-seconds: 86400
+ token-validity-in-seconds-for-remember-me: 2592000
+ mail: # specific JHipster mail property, for standard properties see MailProperties
+ from: dealerapp@localhost
+ base-url: http://my-server-url-to-change # Modify according to your server's URL
+ metrics: # DropWizard Metrics configuration, used by MetricsConfiguration
+ jmx.enabled: true
+ graphite:
+ enabled: false
+ host: localhost
+ port: 2003
+ prefix: dealerapp
+ prometheus:
+ enabled: false
+ endpoint: /prometheusMetrics
+ logs: # Reports Dropwizard metrics in the logs
+ enabled: false
+ reportFrequency: 60 # in seconds
+ logging:
+ logstash: # Forward logs to logstash over a socket, used by LoggingConfiguration
+ enabled: false
+ host: localhost
+ port: 5000
+ queue-size: 512
+ spectator-metrics: # Reports Spectator Circuit Breaker metrics in the logs
+ enabled: false
+ # edit spring.metrics.export.delay-millis to set report frequency
+
+# ===================================================================
+# Application specific properties
+# Add your own application properties here, see the ApplicationProperties class
+# to have type-safe configuration, like in the JHipsterProperties above
+#
+# More documentation is available at:
+# https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+application:
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/application.yml b/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/application.yml
new file mode 100644
index 0000000000..8c77dfd2f3
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/application.yml
@@ -0,0 +1,119 @@
+# ===================================================================
+# Spring Boot configuration.
+#
+# This configuration will be overriden by the Spring profile you use,
+# for example application-dev.yml if you use the "dev" profile.
+#
+# More information on profiles: https://jhipster.github.io/profiles/
+# More information on configuration properties: https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+# ===================================================================
+# Standard Spring Boot properties.
+# Full reference is available at:
+# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
+# ===================================================================
+
+eureka:
+ instance:
+ appname: dealerapp
+ instanceId: dealerapp:${spring.application.instance_id:${random.value}}
+ statusPageUrlPath: ${management.context-path}/info
+ healthCheckUrlPath: ${management.context-path}/health
+ metadata-map:
+ profile: ${spring.profiles.active}
+ version: ${info.project.version}
+ribbon:
+ eureka:
+ enabled: true
+# See https://github.com/Netflix/Hystrix/wiki/Configuration
+#hystrix:
+# command:
+# default:
+# execution:
+# isolation:
+# thread:
+# timeoutInMilliseconds: 10000
+
+management:
+ security:
+ roles: ADMIN
+ context-path: /management
+ health:
+ mail:
+ enabled: false # When using the MailService, configure an SMTP server and set this to true
+spring:
+ application:
+ name: dealerapp
+ jackson:
+ serialization.write_dates_as_timestamps: false
+ jpa:
+ open-in-view: false
+ hibernate:
+ ddl-auto: none
+ naming:
+ physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
+ implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
+ messages:
+ basename: i18n/messages
+ mvc:
+ favicon:
+ enabled: false
+ thymeleaf:
+ mode: XHTML
+
+security:
+ basic:
+ enabled: false
+
+server:
+ session:
+ cookie:
+ http-only: true
+
+
+# ===================================================================
+# JHipster specific properties
+#
+# Full reference is available at: https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+jhipster:
+ async:
+ core-pool-size: 2
+ max-pool-size: 50
+ queue-capacity: 10000
+ # By default CORS is disabled. Uncomment to enable.
+ #cors:
+ #allowed-origins: "*"
+ #allowed-methods: GET, PUT, POST, DELETE, OPTIONS
+ #allowed-headers: "*"
+ #exposed-headers:
+ #allow-credentials: true
+ #max-age: 1800
+ mail:
+ from: dealerapp@localhost
+ swagger:
+ default-include-pattern: /api/.*
+ title: dealerapp API
+ description: dealerapp API documentation
+ version: 0.0.1
+ terms-of-service-url:
+ contact-name:
+ contact-url:
+ contact-email:
+ license:
+ license-url:
+ ribbon:
+ display-on-active-profiles: dev
+
+# ===================================================================
+# Application specific properties
+# Add your own application properties here, see the ApplicationProperties class
+# to have type-safe configuration, like in the JHipsterProperties above
+#
+# More documentation is available at:
+# https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+application:
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/bootstrap-prod.yml b/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/bootstrap-prod.yml
new file mode 100644
index 0000000000..5c7ed3cc2c
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/bootstrap-prod.yml
@@ -0,0 +1,22 @@
+# ===================================================================
+# Spring Cloud Config bootstrap configuration for the "prod" profile
+# ===================================================================
+
+spring:
+ cloud:
+ config:
+ fail-fast: true
+ retry:
+ initial-interval: 1000
+ max-interval: 2000
+ max-attempts: 100
+ uri: http://admin:${jhipster.registry.password}@localhost:8761/config
+ # name of the config server's property source (file.yml) that we want to use
+ name: dealerapp
+ profile: prod # profile(s) of the property source
+ label: master # toggle to switch to a different version of the configuration as stored in git
+ # it can be set to any label, branch or commit of the config source git repository
+
+jhipster:
+ registry:
+ password: admin
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/bootstrap.yml b/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/bootstrap.yml
new file mode 100644
index 0000000000..c9528d6c90
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/bootstrap.yml
@@ -0,0 +1,30 @@
+# ===================================================================
+# Spring Cloud Config bootstrap configuration for the "dev" profile
+# In prod profile, properties will be overwriten by the ones defined in bootstrap-prod.yml
+# ===================================================================
+
+jhipster:
+ registry:
+ password: admin
+
+spring:
+ application:
+ name: dealerapp
+ profiles:
+ # The commented value for `active` can be replaced with valid Spring profiles to load.
+ # Otherwise, it will be filled in by maven when building the WAR file
+ # Either way, it can be overridden by `--spring.profiles.active` value passed in the commandline or `-Dspring.profiles.active` set in `JAVA_OPTS`
+ active: #spring.profiles.active#
+ cloud:
+ config:
+ fail-fast: true
+ uri: http://admin:${jhipster.registry.password}@localhost:8761/config
+ # name of the config server's property source (file.yml) that we want to use
+ name: dealerapp
+ profile: dev # profile(s) of the property source
+ label: master # toggle to switch to a different version of the configuration as stored in git
+ # it can be set to any label, branch or commit of the config source git repository
+
+info:
+ project:
+ version: #project.version#
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/liquibase/changelog/00000000000000_initial_schema.xml b/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/liquibase/changelog/00000000000000_initial_schema.xml
new file mode 100644
index 0000000000..2a1ee4d6bf
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/liquibase/changelog/00000000000000_initial_schema.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/liquibase/changelog/20170503044952_added_entity_Dealer.xml b/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/liquibase/changelog/20170503044952_added_entity_Dealer.xml
new file mode 100644
index 0000000000..128e46a24e
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/liquibase/changelog/20170503044952_added_entity_Dealer.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/liquibase/master.xml b/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/liquibase/master.xml
new file mode 100644
index 0000000000..121f0ad396
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/resources/config/liquibase/master.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/resources/i18n/messages.properties b/jhipster/jhipster-microservice/dealer-app/src/main/resources/i18n/messages.properties
new file mode 100644
index 0000000000..a26917e0cc
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/resources/i18n/messages.properties
@@ -0,0 +1,22 @@
+# Error page
+error.title=Your request cannot be processed
+error.subtitle=Sorry, an error has occurred.
+error.status=Status:
+error.message=Message:
+
+# Activation e-mail
+email.activation.title=dealerapp account activation
+email.activation.greeting=Dear {0}
+email.activation.text1=Your dealerapp account has been created, please click on the URL below to activate it:
+email.activation.text2=Regards,
+email.signature=dealerapp Team.
+
+# Creation email
+email.creation.text1=Your dealerapp account has been created, please click on the URL below to access it:
+
+# Reset e-mail
+email.reset.title=dealerapp password reset
+email.reset.greeting=Dear {0}
+email.reset.text1=For your dealerapp account a password reset was requested, please click on the URL below to reset it:
+email.reset.text2=Regards,
+
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/resources/logback-spring.xml b/jhipster/jhipster-microservice/dealer-app/src/main/resources/logback-spring.xml
new file mode 100644
index 0000000000..2ae9944ae0
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/resources/logback-spring.xml
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
diff --git a/jhipster/jhipster-microservice/dealer-app/src/main/resources/templates/error.html b/jhipster/jhipster-microservice/dealer-app/src/main/resources/templates/error.html
new file mode 100644
index 0000000000..774b080d6c
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/main/resources/templates/error.html
@@ -0,0 +1,162 @@
+
+
+
+
+ Your request cannot be processed
+
+
+
+
+
Your request cannot be processed :(
+
+
Sorry, an error has occurred.
+
+ Status: ()
+
+ Message:
+
+
+
+
+
+
+
diff --git a/jhipster/jhipster-microservice/dealer-app/src/test/java/com/dealer/app/web/rest/DealerResourceIntTest.java b/jhipster/jhipster-microservice/dealer-app/src/test/java/com/dealer/app/web/rest/DealerResourceIntTest.java
new file mode 100644
index 0000000000..7778a2783e
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/test/java/com/dealer/app/web/rest/DealerResourceIntTest.java
@@ -0,0 +1,235 @@
+package com.dealer.app.web.rest;
+
+import com.dealer.app.DealerappApp;
+
+import com.dealer.app.domain.Dealer;
+import com.dealer.app.repository.DealerRepository;
+import com.dealer.app.web.rest.errors.ExceptionTranslator;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.persistence.EntityManager;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.Matchers.hasItem;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
+
+/**
+ * Test class for the DealerResource REST controller.
+ *
+ * @see DealerResource
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = DealerappApp.class)
+public class DealerResourceIntTest {
+
+ private static final String DEFAULT_NAME = "AAAAAAAAAA";
+ private static final String UPDATED_NAME = "BBBBBBBBBB";
+
+ private static final String DEFAULT_ADDRESS = "AAAAAAAAAA";
+ private static final String UPDATED_ADDRESS = "BBBBBBBBBB";
+
+ @Autowired
+ private DealerRepository dealerRepository;
+
+ @Autowired
+ private MappingJackson2HttpMessageConverter jacksonMessageConverter;
+
+ @Autowired
+ private PageableHandlerMethodArgumentResolver pageableArgumentResolver;
+
+ @Autowired
+ private ExceptionTranslator exceptionTranslator;
+
+ @Autowired
+ private EntityManager em;
+
+ private MockMvc restDealerMockMvc;
+
+ private Dealer dealer;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ DealerResource dealerResource = new DealerResource(dealerRepository);
+ this.restDealerMockMvc = MockMvcBuilders.standaloneSetup(dealerResource)
+ .setCustomArgumentResolvers(pageableArgumentResolver)
+ .setControllerAdvice(exceptionTranslator)
+ .setMessageConverters(jacksonMessageConverter).build();
+ }
+
+ /**
+ * Create an entity for this test.
+ *
+ * This is a static method, as tests for other entities might also need it,
+ * if they test an entity which requires the current entity.
+ */
+ public static Dealer createEntity(EntityManager em) {
+ Dealer dealer = new Dealer()
+ .name(DEFAULT_NAME)
+ .address(DEFAULT_ADDRESS);
+ return dealer;
+ }
+
+ @Before
+ public void initTest() {
+ dealer = createEntity(em);
+ }
+
+ @Test
+ @Transactional
+ public void createDealer() throws Exception {
+ int databaseSizeBeforeCreate = dealerRepository.findAll().size();
+
+ // Create the Dealer
+ restDealerMockMvc.perform(post("/api/dealers")
+ .contentType(TestUtil.APPLICATION_JSON_UTF8)
+ .content(TestUtil.convertObjectToJsonBytes(dealer)))
+ .andExpect(status().isCreated());
+
+ // Validate the Dealer in the database
+ List dealerList = dealerRepository.findAll();
+ assertThat(dealerList).hasSize(databaseSizeBeforeCreate + 1);
+ Dealer testDealer = dealerList.get(dealerList.size() - 1);
+ assertThat(testDealer.getName()).isEqualTo(DEFAULT_NAME);
+ assertThat(testDealer.getAddress()).isEqualTo(DEFAULT_ADDRESS);
+ }
+
+ @Test
+ @Transactional
+ public void createDealerWithExistingId() throws Exception {
+ int databaseSizeBeforeCreate = dealerRepository.findAll().size();
+
+ // Create the Dealer with an existing ID
+ dealer.setId(1L);
+
+ // An entity with an existing ID cannot be created, so this API call must fail
+ restDealerMockMvc.perform(post("/api/dealers")
+ .contentType(TestUtil.APPLICATION_JSON_UTF8)
+ .content(TestUtil.convertObjectToJsonBytes(dealer)))
+ .andExpect(status().isBadRequest());
+
+ // Validate the Alice in the database
+ List dealerList = dealerRepository.findAll();
+ assertThat(dealerList).hasSize(databaseSizeBeforeCreate);
+ }
+
+ @Test
+ @Transactional
+ public void getAllDealers() throws Exception {
+ // Initialize the database
+ dealerRepository.saveAndFlush(dealer);
+
+ // Get all the dealerList
+ restDealerMockMvc.perform(get("/api/dealers?sort=id,desc"))
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
+ .andExpect(jsonPath("$.[*].id").value(hasItem(dealer.getId().intValue())))
+ .andExpect(jsonPath("$.[*].name").value(hasItem(DEFAULT_NAME.toString())))
+ .andExpect(jsonPath("$.[*].address").value(hasItem(DEFAULT_ADDRESS.toString())));
+ }
+
+ @Test
+ @Transactional
+ public void getDealer() throws Exception {
+ // Initialize the database
+ dealerRepository.saveAndFlush(dealer);
+
+ // Get the dealer
+ restDealerMockMvc.perform(get("/api/dealers/{id}", dealer.getId()))
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
+ .andExpect(jsonPath("$.id").value(dealer.getId().intValue()))
+ .andExpect(jsonPath("$.name").value(DEFAULT_NAME.toString()))
+ .andExpect(jsonPath("$.address").value(DEFAULT_ADDRESS.toString()));
+ }
+
+ @Test
+ @Transactional
+ public void getNonExistingDealer() throws Exception {
+ // Get the dealer
+ restDealerMockMvc.perform(get("/api/dealers/{id}", Long.MAX_VALUE))
+ .andExpect(status().isNotFound());
+ }
+
+ @Test
+ @Transactional
+ public void updateDealer() throws Exception {
+ // Initialize the database
+ dealerRepository.saveAndFlush(dealer);
+ int databaseSizeBeforeUpdate = dealerRepository.findAll().size();
+
+ // Update the dealer
+ Dealer updatedDealer = dealerRepository.findOne(dealer.getId());
+ updatedDealer
+ .name(UPDATED_NAME)
+ .address(UPDATED_ADDRESS);
+
+ restDealerMockMvc.perform(put("/api/dealers")
+ .contentType(TestUtil.APPLICATION_JSON_UTF8)
+ .content(TestUtil.convertObjectToJsonBytes(updatedDealer)))
+ .andExpect(status().isOk());
+
+ // Validate the Dealer in the database
+ List dealerList = dealerRepository.findAll();
+ assertThat(dealerList).hasSize(databaseSizeBeforeUpdate);
+ Dealer testDealer = dealerList.get(dealerList.size() - 1);
+ assertThat(testDealer.getName()).isEqualTo(UPDATED_NAME);
+ assertThat(testDealer.getAddress()).isEqualTo(UPDATED_ADDRESS);
+ }
+
+ @Test
+ @Transactional
+ public void updateNonExistingDealer() throws Exception {
+ int databaseSizeBeforeUpdate = dealerRepository.findAll().size();
+
+ // Create the Dealer
+
+ // If the entity doesn't have an ID, it will be created instead of just being updated
+ restDealerMockMvc.perform(put("/api/dealers")
+ .contentType(TestUtil.APPLICATION_JSON_UTF8)
+ .content(TestUtil.convertObjectToJsonBytes(dealer)))
+ .andExpect(status().isCreated());
+
+ // Validate the Dealer in the database
+ List dealerList = dealerRepository.findAll();
+ assertThat(dealerList).hasSize(databaseSizeBeforeUpdate + 1);
+ }
+
+ @Test
+ @Transactional
+ public void deleteDealer() throws Exception {
+ // Initialize the database
+ dealerRepository.saveAndFlush(dealer);
+ int databaseSizeBeforeDelete = dealerRepository.findAll().size();
+
+ // Get the dealer
+ restDealerMockMvc.perform(delete("/api/dealers/{id}", dealer.getId())
+ .accept(TestUtil.APPLICATION_JSON_UTF8))
+ .andExpect(status().isOk());
+
+ // Validate the database is empty
+ List dealerList = dealerRepository.findAll();
+ assertThat(dealerList).hasSize(databaseSizeBeforeDelete - 1);
+ }
+
+ @Test
+ @Transactional
+ public void equalsVerifier() throws Exception {
+ TestUtil.equalsVerifier(Dealer.class);
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/test/java/com/dealer/app/web/rest/TestUtil.java b/jhipster/jhipster-microservice/dealer-app/src/test/java/com/dealer/app/web/rest/TestUtil.java
new file mode 100644
index 0000000000..7a51b3380d
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/test/java/com/dealer/app/web/rest/TestUtil.java
@@ -0,0 +1,120 @@
+package com.dealer.app.web.rest;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.http.MediaType;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeParseException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Utility class for testing REST controllers.
+ */
+public class TestUtil {
+
+ /** MediaType for JSON UTF8 */
+ public static final MediaType APPLICATION_JSON_UTF8 = new MediaType(
+ MediaType.APPLICATION_JSON.getType(),
+ MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8"));
+
+ /**
+ * Convert an object to JSON byte array.
+ *
+ * @param object
+ * the object to convert
+ * @return the JSON byte array
+ * @throws IOException
+ */
+ public static byte[] convertObjectToJsonBytes(Object object)
+ throws IOException {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+
+ JavaTimeModule module = new JavaTimeModule();
+ mapper.registerModule(module);
+
+ return mapper.writeValueAsBytes(object);
+ }
+
+ /**
+ * Create a byte array with a specific size filled with specified data.
+ *
+ * @param size the size of the byte array
+ * @param data the data to put in the byte array
+ * @return the JSON byte array
+ */
+ public static byte[] createByteArray(int size, String data) {
+ byte[] byteArray = new byte[size];
+ for (int i = 0; i < size; i++) {
+ byteArray[i] = Byte.parseByte(data, 2);
+ }
+ return byteArray;
+ }
+
+ /**
+ * A matcher that tests that the examined string represents the same instant as the reference datetime.
+ */
+ public static class ZonedDateTimeMatcher extends TypeSafeDiagnosingMatcher {
+
+ private final ZonedDateTime date;
+
+ public ZonedDateTimeMatcher(ZonedDateTime date) {
+ this.date = date;
+ }
+
+ @Override
+ protected boolean matchesSafely(String item, Description mismatchDescription) {
+ try {
+ if (!date.isEqual(ZonedDateTime.parse(item))) {
+ mismatchDescription.appendText("was ").appendValue(item);
+ return false;
+ }
+ return true;
+ } catch (DateTimeParseException e) {
+ mismatchDescription.appendText("was ").appendValue(item)
+ .appendText(", which could not be parsed as a ZonedDateTime");
+ return false;
+ }
+
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("a String representing the same Instant as ").appendValue(date);
+ }
+ }
+
+ /**
+ * Creates a matcher that matches when the examined string reprensents the same instant as the reference datetime
+ * @param date the reference datetime against which the examined string is checked
+ */
+ public static ZonedDateTimeMatcher sameInstant(ZonedDateTime date) {
+ return new ZonedDateTimeMatcher(date);
+ }
+
+ /**
+ * Verifies the equals/hashcode contract on the domain object.
+ */
+ public static void equalsVerifier(Class clazz) throws Exception {
+ Object domainObject1 = clazz.getConstructor().newInstance();
+ assertThat(domainObject1.toString()).isNotNull();
+ assertThat(domainObject1).isEqualTo(domainObject1);
+ assertThat(domainObject1.hashCode()).isEqualTo(domainObject1.hashCode());
+ // Test with an instance of another class
+ Object testOtherObject = new Object();
+ assertThat(domainObject1).isNotEqualTo(testOtherObject);
+ // Test with an instance of the same class
+ Object domainObject2 = clazz.getConstructor().newInstance();
+ assertThat(domainObject1).isNotEqualTo(domainObject2);
+ // HashCodes are equals because the objects are not persisted yet
+ assertThat(domainObject1.hashCode()).isEqualTo(domainObject2.hashCode());
+ }
+}
diff --git a/jhipster/jhipster-microservice/dealer-app/src/test/resources/config/application.yml b/jhipster/jhipster-microservice/dealer-app/src/test/resources/config/application.yml
new file mode 100644
index 0000000000..8959533002
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/test/resources/config/application.yml
@@ -0,0 +1,102 @@
+# ===================================================================
+# Spring Boot configuration.
+#
+# This configuration is used for unit/integration tests.
+#
+# More information on profiles: https://jhipster.github.io/profiles/
+# More information on configuration properties: https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+# ===================================================================
+# Standard Spring Boot properties.
+# Full reference is available at:
+# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
+# ===================================================================
+
+eureka:
+ client:
+ enabled: false
+ instance:
+ appname: dealerapp
+ instanceId: dealerapp:${spring.application.instance_id:${random.value}}
+
+spring:
+ application:
+ name: dealerapp
+ jackson:
+ serialization.write_dates_as_timestamps: false
+ cache:
+ type: none
+ datasource:
+ type: com.zaxxer.hikari.HikariDataSource
+ url: jdbc:h2:mem:dealerapp;DB_CLOSE_DELAY=-1
+ name:
+ username:
+ password:
+ jpa:
+ database-platform: io.github.jhipster.domain.util.FixedH2Dialect
+ database: H2
+ open-in-view: false
+ show-sql: true
+ hibernate:
+ ddl-auto: none
+ naming:
+ physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
+ implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
+ properties:
+ hibernate.id.new_generator_mappings: true
+ hibernate.cache.use_second_level_cache: false
+ hibernate.cache.use_query_cache: false
+ hibernate.generate_statistics: true
+ hibernate.hbm2ddl.auto: validate
+ mail:
+ host: localhost
+ messages:
+ basename: i18n/messages
+ mvc:
+ favicon:
+ enabled: false
+ thymeleaf:
+ mode: XHTML
+
+liquibase:
+ contexts: test
+
+security:
+ basic:
+ enabled: false
+
+server:
+ port: 10344
+ address: localhost
+
+# ===================================================================
+# JHipster specific properties
+#
+# Full reference is available at: https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+jhipster:
+ async:
+ core-pool-size: 2
+ max-pool-size: 50
+ queue-capacity: 10000
+ security:
+ authentication:
+ jwt:
+ secret: d4c73e937677223a85c7fcebae7a6ce0c48c3b01
+ # Token is valid 24 hours
+ token-validity-in-seconds: 86400
+ metrics: # DropWizard Metrics configuration, used by MetricsConfiguration
+ jmx.enabled: true
+
+# ===================================================================
+# Application specific properties
+# Add your own application properties here, see the ApplicationProperties class
+# to have type-safe configuration, like in the JHipsterProperties above
+#
+# More documentation is available at:
+# https://jhipster.github.io/common-application-properties/
+# ===================================================================
+
+application:
diff --git a/jhipster/jhipster-microservice/dealer-app/src/test/resources/config/bootstrap.yml b/jhipster/jhipster-microservice/dealer-app/src/test/resources/config/bootstrap.yml
new file mode 100644
index 0000000000..11cd6af21c
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/test/resources/config/bootstrap.yml
@@ -0,0 +1,4 @@
+spring:
+ cloud:
+ config:
+ enabled: false
diff --git a/jhipster/jhipster-microservice/dealer-app/src/test/resources/logback-test.xml b/jhipster/jhipster-microservice/dealer-app/src/test/resources/logback-test.xml
new file mode 100644
index 0000000000..83efcf9b13
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/src/test/resources/logback-test.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jhipster/jhipster-microservice/dealer-app/yarn.lock b/jhipster/jhipster-microservice/dealer-app/yarn.lock
new file mode 100644
index 0000000000..4333a516f1
--- /dev/null
+++ b/jhipster/jhipster-microservice/dealer-app/yarn.lock
@@ -0,0 +1,2439 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+abbrev@1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f"
+
+acorn-jsx@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b"
+ dependencies:
+ acorn "^3.0.4"
+
+acorn@^3.0.4:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
+
+ajv@^4.9.1:
+ version "4.11.8"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
+ dependencies:
+ co "^4.6.0"
+ json-stable-stringify "^1.0.1"
+
+amdefine@>=0.0.4:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
+
+ansi-escapes@^1.1.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
+
+ansi-regex@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+
+ansi-styles@^2.0.0, ansi-styles@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+
+ansi@^0.3.0, ansi@~0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/ansi/-/ansi-0.3.1.tgz#0c42d4fb17160d5a9af1e484bace1c66922c1b21"
+
+are-we-there-yet@~1.1.2:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d"
+ dependencies:
+ delegates "^1.0.0"
+ readable-stream "^2.0.6"
+
+argparse@^1.0.7:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86"
+ dependencies:
+ sprintf-js "~1.0.2"
+
+array-differ@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031"
+
+array-find-index@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
+
+array-union@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
+ dependencies:
+ array-uniq "^1.0.1"
+
+array-uniq@^1.0.0, array-uniq@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
+
+arrify@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
+
+asn1@~0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86"
+
+assert-plus@1.0.0, assert-plus@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
+
+assert-plus@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234"
+
+ast-query@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ast-query/-/ast-query-2.0.0.tgz#3588e79ad8de07ce50df1e781cc2bda1fd69a453"
+ dependencies:
+ acorn-jsx "^3.0.1"
+ class-extend "^0.1.1"
+ escodegen-wallaby "^1.6.7"
+ lodash "^4.6.1"
+ traverse "^0.6.6"
+
+async@^1.0.0, async@^1.4.2:
+ version "1.5.2"
+ resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
+
+async@^2.0.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/async/-/async-2.4.0.tgz#4990200f18ea5b837c2cc4f8c031a6985c385611"
+ dependencies:
+ lodash "^4.14.0"
+
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+
+aws-sign2@~0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f"
+
+aws4@^1.2.1:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
+
+balanced-match@^0.4.1:
+ version "0.4.2"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
+
+bcrypt-pbkdf@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d"
+ dependencies:
+ tweetnacl "^0.14.3"
+
+bin-version-check@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/bin-version-check/-/bin-version-check-2.1.0.tgz#e4e5df290b9069f7d111324031efc13fdd11a5b0"
+ dependencies:
+ bin-version "^1.0.0"
+ minimist "^1.1.0"
+ semver "^4.0.3"
+ semver-truncate "^1.0.0"
+
+bin-version@^1.0.0:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/bin-version/-/bin-version-1.0.4.tgz#9eb498ee6fd76f7ab9a7c160436f89579435d78e"
+ dependencies:
+ find-versions "^1.0.0"
+
+"binaryextensions@1 || 2":
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-2.0.0.tgz#e597d1a7a6a3558a2d1c7241a16c99965e6aa40f"
+
+boolbase@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
+
+boom@2.x.x:
+ version "2.10.1"
+ resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f"
+ dependencies:
+ hoek "2.x.x"
+
+boxen@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/boxen/-/boxen-0.3.1.tgz#a7d898243ae622f7abb6bb604d740a76c6a5461b"
+ dependencies:
+ chalk "^1.1.1"
+ filled-array "^1.0.0"
+ object-assign "^4.0.1"
+ repeating "^2.0.0"
+ string-width "^1.0.1"
+ widest-line "^1.0.0"
+
+brace-expansion@^1.0.0:
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59"
+ dependencies:
+ balanced-match "^0.4.1"
+ concat-map "0.0.1"
+
+buffer-shims@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51"
+
+builtin-modules@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
+
+camelcase-keys@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
+ dependencies:
+ camelcase "^2.0.0"
+ map-obj "^1.0.0"
+
+camelcase@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
+
+capture-stack-trace@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d"
+
+caseless@~0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
+
+chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+ dependencies:
+ ansi-styles "^2.2.1"
+ escape-string-regexp "^1.0.2"
+ has-ansi "^2.0.0"
+ strip-ansi "^3.0.0"
+ supports-color "^2.0.0"
+
+cheerio@0.22.0:
+ version "0.22.0"
+ resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e"
+ dependencies:
+ css-select "~1.2.0"
+ dom-serializer "~0.1.0"
+ entities "~1.1.1"
+ htmlparser2 "^3.9.1"
+ lodash.assignin "^4.0.9"
+ lodash.bind "^4.1.4"
+ lodash.defaults "^4.0.1"
+ lodash.filter "^4.4.0"
+ lodash.flatten "^4.2.0"
+ lodash.foreach "^4.3.0"
+ lodash.map "^4.4.0"
+ lodash.merge "^4.4.0"
+ lodash.pick "^4.2.1"
+ lodash.reduce "^4.4.0"
+ lodash.reject "^4.4.0"
+ lodash.some "^4.4.0"
+
+cheerio@^0.19.0:
+ version "0.19.0"
+ resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.19.0.tgz#772e7015f2ee29965096d71ea4175b75ab354925"
+ dependencies:
+ css-select "~1.0.0"
+ dom-serializer "~0.1.0"
+ entities "~1.1.1"
+ htmlparser2 "~3.8.1"
+ lodash "^3.2.0"
+
+class-extend@^0.1.0, class-extend@^0.1.1:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/class-extend/-/class-extend-0.1.2.tgz#8057a82b00f53f82a5d62c50ef8cffdec6fabc34"
+ dependencies:
+ object-assign "^2.0.0"
+
+cli-boxes@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143"
+
+cli-cursor@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987"
+ dependencies:
+ restore-cursor "^1.0.1"
+
+cli-list@^0.1.1:
+ version "0.1.8"
+ resolved "https://registry.yarnpkg.com/cli-list/-/cli-list-0.1.8.tgz#aee6d45c4c59bf80068bb968089fb06f1aeddc0a"
+
+cli-table@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23"
+ dependencies:
+ colors "1.0.3"
+
+cli-width@^1.0.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-1.1.1.tgz#a4d293ef67ebb7b88d4a4d42c0ccf00c4d1e366d"
+
+cli-width@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a"
+
+clone-regexp@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-1.0.0.tgz#eae0a2413f55c0942f818c229fefce845d7f3b1c"
+ dependencies:
+ is-regexp "^1.0.0"
+ is-supported-regexp-flag "^1.0.0"
+
+clone-stats@^0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1"
+
+clone@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.2.tgz#260b7a99ebb1edfe247538175f783243cb19d149"
+
+co@^4.6.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
+
+code-point-at@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
+
+colors@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
+
+combined-stream@^1.0.5, combined-stream@~1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009"
+ dependencies:
+ delayed-stream "~1.0.0"
+
+commondir@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+
+concat-stream@^1.4.7:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
+ dependencies:
+ inherits "^2.0.3"
+ readable-stream "^2.2.2"
+ typedarray "^0.0.6"
+
+config-chain@~1.1.8:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.11.tgz#aba09747dfbe4c3e70e766a6e41586e1859fc6f2"
+ dependencies:
+ ini "^1.3.4"
+ proto-list "~1.2.1"
+
+configstore@^1.0.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/configstore/-/configstore-1.4.0.tgz#c35781d0501d268c25c54b8b17f6240e8a4fb021"
+ dependencies:
+ graceful-fs "^4.1.2"
+ mkdirp "^0.5.0"
+ object-assign "^4.0.1"
+ os-tmpdir "^1.0.0"
+ osenv "^0.1.0"
+ uuid "^2.0.1"
+ write-file-atomic "^1.1.2"
+ xdg-basedir "^2.0.0"
+
+configstore@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/configstore/-/configstore-2.1.0.tgz#737a3a7036e9886102aa6099e47bb33ab1aba1a1"
+ dependencies:
+ dot-prop "^3.0.0"
+ graceful-fs "^4.1.2"
+ mkdirp "^0.5.0"
+ object-assign "^4.0.1"
+ os-tmpdir "^1.0.0"
+ osenv "^0.1.0"
+ uuid "^2.0.1"
+ write-file-atomic "^1.1.2"
+ xdg-basedir "^2.0.0"
+
+core-util-is@~1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
+
+create-error-class@^3.0.1:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6"
+ dependencies:
+ capture-stack-trace "^1.0.0"
+
+cross-spawn@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982"
+ dependencies:
+ lru-cache "^4.0.1"
+ which "^1.2.9"
+
+cross-spawn@^4.0.0:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41"
+ dependencies:
+ lru-cache "^4.0.1"
+ which "^1.2.9"
+
+cryptiles@2.x.x:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
+ dependencies:
+ boom "2.x.x"
+
+css-select@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.0.0.tgz#b1121ca51848dd264e2244d058cee254deeb44b0"
+ dependencies:
+ boolbase "~1.0.0"
+ css-what "1.0"
+ domutils "1.4"
+ nth-check "~1.0.0"
+
+css-select@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
+ dependencies:
+ boolbase "~1.0.0"
+ css-what "2.1"
+ domutils "1.5.1"
+ nth-check "~1.0.1"
+
+css-what@1.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/css-what/-/css-what-1.0.0.tgz#d7cc2df45180666f99d2b14462639469e00f736c"
+
+css-what@2.1:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd"
+
+currently-unhandled@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
+ dependencies:
+ array-find-index "^1.0.1"
+
+dargs@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/dargs/-/dargs-4.1.0.tgz#03a9dbb4b5c2f139bf14ae53f0b8a2a6a86f4e17"
+ dependencies:
+ number-is-nan "^1.0.0"
+
+dashdash@^1.12.0:
+ version "1.14.1"
+ resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
+ dependencies:
+ assert-plus "^1.0.0"
+
+dateformat@^1.0.11:
+ version "1.0.12"
+ resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9"
+ dependencies:
+ get-stdin "^4.0.1"
+ meow "^3.3.0"
+
+debug@^2.0.0, debug@^2.1.0, debug@^2.2.0:
+ version "2.6.6"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.6.tgz#a9fa6fbe9ca43cf1e79f73b75c0189cbb7d6db5a"
+ dependencies:
+ ms "0.7.3"
+
+decamelize@^1.0.0, decamelize@^1.1.2:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+
+deep-extend@^0.4.0, deep-extend@~0.4.0:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.1.tgz#efe4113d08085f4e6f9687759810f807469e2253"
+
+deep-is@~0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
+
+default-uid@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/default-uid/-/default-uid-1.0.0.tgz#fcefa9df9f5ac40c8916d912dd1fe1146aa3c59e"
+
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+
+delegates@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
+
+detect-conflict@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/detect-conflict/-/detect-conflict-1.0.1.tgz#088657a66a961c05019db7c4230883b1c6b4176e"
+
+detect-newline@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-1.0.3.tgz#e97b1003877d70c09af1af35bfadff168de4920d"
+ dependencies:
+ get-stdin "^4.0.1"
+ minimist "^1.1.0"
+
+diff@^2.1.2:
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/diff/-/diff-2.2.3.tgz#60eafd0d28ee906e4e8ff0a52c1229521033bf99"
+
+discontinuous-range@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a"
+
+dom-serializer@0, dom-serializer@~0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82"
+ dependencies:
+ domelementtype "~1.1.1"
+ entities "~1.1.1"
+
+domelementtype@1, domelementtype@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2"
+
+domelementtype@~1.1.1:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b"
+
+domhandler@2.3, domhandler@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.3.0.tgz#2de59a0822d5027fabff6f032c2b25a2a8abe738"
+ dependencies:
+ domelementtype "1"
+
+domutils@1.4:
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.4.3.tgz#0865513796c6b306031850e175516baf80b72a6f"
+ dependencies:
+ domelementtype "1"
+
+domutils@1.5, domutils@1.5.1, domutils@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf"
+ dependencies:
+ dom-serializer "0"
+ domelementtype "1"
+
+dot-prop@^2.0.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-2.4.0.tgz#848e28f7f1d50740c6747ab3cb07670462b6f89c"
+ dependencies:
+ is-obj "^1.0.0"
+
+dot-prop@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-3.0.0.tgz#1b708af094a49c9a0e7dbcad790aba539dac1177"
+ dependencies:
+ is-obj "^1.0.0"
+
+downgrade-root@^1.0.0:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/downgrade-root/-/downgrade-root-1.2.2.tgz#531319715b0e81ffcc22eb28478ba27643e12c6c"
+ dependencies:
+ default-uid "^1.0.0"
+ is-root "^1.0.0"
+
+duplexer2@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
+ dependencies:
+ readable-stream "^2.0.2"
+
+each-async@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/each-async/-/each-async-1.1.1.tgz#dee5229bdf0ab6ba2012a395e1b869abf8813473"
+ dependencies:
+ onetime "^1.0.0"
+ set-immediate-shim "^1.0.0"
+
+ecc-jsbn@~0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505"
+ dependencies:
+ jsbn "~0.1.0"
+
+editions@^1.1.1:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.3.tgz#0907101bdda20fac3cbe334c27cbd0688dc99a5b"
+
+ejs@2.5.6, ejs@^2.3.1:
+ version "2.5.6"
+ resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.6.tgz#479636bfa3fe3b1debd52087f0acb204b4f19c88"
+
+entities@1.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26"
+
+entities@^1.1.1, entities@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0"
+
+error-ex@^1.2.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc"
+ dependencies:
+ is-arrayish "^0.2.1"
+
+error@^7.0.2:
+ version "7.0.2"
+ resolved "https://registry.yarnpkg.com/error/-/error-7.0.2.tgz#a5f75fff4d9926126ddac0ea5dc38e689153cb02"
+ dependencies:
+ string-template "~0.2.1"
+ xtend "~4.0.0"
+
+escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+
+escodegen-wallaby@^1.6.7:
+ version "1.6.11"
+ resolved "https://registry.yarnpkg.com/escodegen-wallaby/-/escodegen-wallaby-1.6.11.tgz#39100cde743f9acdd24bd868db5a12fbacde6ed1"
+ dependencies:
+ esprima "^2.7.1"
+ estraverse "^1.9.1"
+ esutils "^2.0.2"
+ optionator "^0.8.1"
+ optionalDependencies:
+ source-map "~0.2.0"
+
+esprima@^2.7.1:
+ version "2.7.3"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
+
+esprima@^3.1.1:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
+
+estraverse@^1.9.1:
+ version "1.9.3"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44"
+
+esutils@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
+
+execall@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/execall/-/execall-1.0.0.tgz#73d0904e395b3cab0658b08d09ec25307f29bb73"
+ dependencies:
+ clone-regexp "^1.0.0"
+
+exit-hook@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8"
+
+extend@^3.0.0, extend@~3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
+
+external-editor@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-1.1.1.tgz#12d7b0db850f7ff7e7081baf4005700060c4600b"
+ dependencies:
+ extend "^3.0.0"
+ spawn-sync "^1.0.15"
+ tmp "^0.0.29"
+
+extsprintf@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550"
+
+fast-levenshtein@~2.0.4:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
+
+figures@^1.3.5:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
+ dependencies:
+ escape-string-regexp "^1.0.5"
+ object-assign "^4.1.0"
+
+filled-array@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/filled-array/-/filled-array-1.1.0.tgz#c3c4f6c663b923459a9aa29912d2d031f1507f84"
+
+find-up@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
+ dependencies:
+ path-exists "^2.0.0"
+ pinkie-promise "^2.0.0"
+
+find-versions@^1.0.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-1.2.1.tgz#cbde9f12e38575a0af1be1b9a2c5d5fd8f186b62"
+ dependencies:
+ array-uniq "^1.0.0"
+ get-stdin "^4.0.1"
+ meow "^3.5.0"
+ semver-regex "^1.0.0"
+
+first-chunk-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz#1bdecdb8e083c0664b91945581577a43a9f31d70"
+ dependencies:
+ readable-stream "^2.0.2"
+
+foreachasync@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/foreachasync/-/foreachasync-3.0.0.tgz#5502987dc8714be3392097f32e0071c9dee07cf6"
+
+forever-agent@~0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
+
+form-data@~2.1.1:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1"
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.5"
+ mime-types "^2.1.12"
+
+formatio@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9"
+ dependencies:
+ samsam "~1.1"
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+
+fullname@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/fullname/-/fullname-2.1.0.tgz#c46bf0f7c3f24fd5b3358d00e4a41380eef87350"
+ dependencies:
+ npmconf "^2.1.1"
+ pify "^2.2.0"
+ pinkie-promise "^2.0.0"
+
+gauge@~1.2.5:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/gauge/-/gauge-1.2.7.tgz#e9cec5483d3d4ee0ef44b60a7d99e4935e136d93"
+ dependencies:
+ ansi "^0.3.0"
+ has-unicode "^2.0.0"
+ lodash.pad "^4.1.0"
+ lodash.padend "^4.1.0"
+ lodash.padstart "^4.1.0"
+
+generator-jhipster@4.0.8:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/generator-jhipster/-/generator-jhipster-4.0.8.tgz#9daff076cc628500726026fad6cfb0a8b55eb1b0"
+ dependencies:
+ chalk "1.1.3"
+ cheerio "0.22.0"
+ ejs "2.5.6"
+ glob "7.1.1"
+ html-wiring "1.2.0"
+ insight "0.8.4"
+ jhipster-core "1.2.8"
+ js-yaml "3.8.1"
+ lodash "4.17.4"
+ mkdirp "0.5.1"
+ pluralize "3.1.0"
+ randexp "0.4.4"
+ semver "5.3.0"
+ shelljs "0.7.6"
+ yeoman-generator "0.24.1"
+ yo "1.8.5"
+
+get-stdin@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
+
+getpass@^0.1.1:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
+ dependencies:
+ assert-plus "^1.0.0"
+
+gh-got@^2.2.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/gh-got/-/gh-got-2.4.0.tgz#aa51418911ca5e4f92437114cd1209383a4aa019"
+ dependencies:
+ got "^5.2.0"
+ object-assign "^4.0.1"
+ pinkie-promise "^2.0.0"
+
+github-username@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/github-username/-/github-username-2.1.0.tgz#200e5a104af42ba08a54096c708d4b6ec2fa256b"
+ dependencies:
+ gh-got "^2.2.0"
+ meow "^3.5.0"
+
+glob@7.1.1, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.0.2"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+glob@^6.0.1:
+ version "6.0.4"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22"
+ dependencies:
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "2 || 3"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+globby@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-4.1.0.tgz#080f54549ec1b82a6c60e631fc82e1211dbe95f8"
+ dependencies:
+ array-union "^1.0.1"
+ arrify "^1.0.0"
+ glob "^6.0.1"
+ object-assign "^4.0.1"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+
+got@^5.0.0, got@^5.2.0:
+ version "5.7.1"
+ resolved "https://registry.yarnpkg.com/got/-/got-5.7.1.tgz#5f81635a61e4a6589f180569ea4e381680a51f35"
+ dependencies:
+ create-error-class "^3.0.1"
+ duplexer2 "^0.1.4"
+ is-redirect "^1.0.0"
+ is-retry-allowed "^1.0.0"
+ is-stream "^1.0.0"
+ lowercase-keys "^1.0.0"
+ node-status-codes "^1.0.0"
+ object-assign "^4.0.1"
+ parse-json "^2.1.0"
+ pinkie-promise "^2.0.0"
+ read-all-stream "^3.0.0"
+ readable-stream "^2.0.5"
+ timed-out "^3.0.0"
+ unzip-response "^1.0.2"
+ url-parse-lax "^1.0.0"
+
+graceful-fs@^4.1.11, graceful-fs@^4.1.2:
+ version "4.1.11"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
+
+grouped-queue@^0.3.0:
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/grouped-queue/-/grouped-queue-0.3.3.tgz#c167d2a5319c5a0e0964ef6a25b7c2df8996c85c"
+ dependencies:
+ lodash "^4.17.2"
+
+gruntfile-editor@^1.0.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/gruntfile-editor/-/gruntfile-editor-1.2.1.tgz#366fc1f93cbf045813e1448aef1da9f18289d5eb"
+ dependencies:
+ ast-query "^2.0.0"
+ lodash "^4.6.1"
+
+har-schema@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
+
+har-validator@~4.2.1:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
+ dependencies:
+ ajv "^4.9.1"
+ har-schema "^1.0.5"
+
+has-ansi@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
+ dependencies:
+ ansi-regex "^2.0.0"
+
+has-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
+
+has-unicode@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
+
+hawk@~3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
+ dependencies:
+ boom "2.x.x"
+ cryptiles "2.x.x"
+ hoek "2.x.x"
+ sntp "1.x.x"
+
+hoek@2.x.x:
+ version "2.16.3"
+ resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
+
+hosted-git-info@^2.1.4:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.4.2.tgz#0076b9f46a270506ddbaaea56496897460612a67"
+
+html-wiring@1.2.0, html-wiring@^1.0.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/html-wiring/-/html-wiring-1.2.0.tgz#c5f90a776e0a27241dc6df9022c37186d0270f9e"
+ dependencies:
+ cheerio "^0.19.0"
+ detect-newline "^1.0.3"
+
+htmlparser2@^3.9.1:
+ version "3.9.2"
+ resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338"
+ dependencies:
+ domelementtype "^1.3.0"
+ domhandler "^2.3.0"
+ domutils "^1.5.1"
+ entities "^1.1.1"
+ inherits "^2.0.1"
+ readable-stream "^2.0.2"
+
+htmlparser2@~3.8.1:
+ version "3.8.3"
+ resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.8.3.tgz#996c28b191516a8be86501a7d79757e5c70c1068"
+ dependencies:
+ domelementtype "1"
+ domhandler "2.3"
+ domutils "1.5"
+ entities "1.0"
+ readable-stream "1.1"
+
+http-signature@~1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
+ dependencies:
+ assert-plus "^0.2.0"
+ jsprim "^1.2.2"
+ sshpk "^1.7.0"
+
+humanize-string@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/humanize-string/-/humanize-string-1.0.1.tgz#fce2d6c545efc25dea1f23235182c98da0180b42"
+ dependencies:
+ decamelize "^1.0.0"
+
+imurmurhash@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
+
+indent-string@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
+ dependencies:
+ repeating "^2.0.0"
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+
+inherits@2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
+
+ini@^1.2.0, ini@^1.3.4, ini@~1.3.0:
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e"
+
+inquirer@^0.10.0:
+ version "0.10.1"
+ resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.10.1.tgz#ea25e4ce69ca145e05c99e46dcfec05e4012594a"
+ dependencies:
+ ansi-escapes "^1.1.0"
+ ansi-regex "^2.0.0"
+ chalk "^1.0.0"
+ cli-cursor "^1.0.1"
+ cli-width "^1.0.1"
+ figures "^1.3.5"
+ lodash "^3.3.1"
+ readline2 "^1.0.1"
+ run-async "^0.1.0"
+ rx-lite "^3.1.2"
+ strip-ansi "^3.0.0"
+ through "^2.3.6"
+
+inquirer@^0.11.0:
+ version "0.11.4"
+ resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.11.4.tgz#81e3374e8361beaff2d97016206d359d0b32fa4d"
+ dependencies:
+ ansi-escapes "^1.1.0"
+ ansi-regex "^2.0.0"
+ chalk "^1.0.0"
+ cli-cursor "^1.0.1"
+ cli-width "^1.0.1"
+ figures "^1.3.5"
+ lodash "^3.3.1"
+ readline2 "^1.0.1"
+ run-async "^0.1.0"
+ rx-lite "^3.1.2"
+ string-width "^1.0.1"
+ strip-ansi "^3.0.0"
+ through "^2.3.6"
+
+inquirer@^1.0.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-1.2.3.tgz#4dec6f32f37ef7bb0b2ed3f1d1a5c3f545074918"
+ dependencies:
+ ansi-escapes "^1.1.0"
+ chalk "^1.0.0"
+ cli-cursor "^1.0.1"
+ cli-width "^2.0.0"
+ external-editor "^1.1.0"
+ figures "^1.3.5"
+ lodash "^4.3.0"
+ mute-stream "0.0.6"
+ pinkie-promise "^2.0.0"
+ run-async "^2.2.0"
+ rx "^4.1.0"
+ string-width "^1.0.1"
+ strip-ansi "^3.0.0"
+ through "^2.3.6"
+
+insight@0.8.4:
+ version "0.8.4"
+ resolved "https://registry.yarnpkg.com/insight/-/insight-0.8.4.tgz#671caf65b47c9fe8c3d1b3206cf45bb211b75884"
+ dependencies:
+ async "^1.4.2"
+ chalk "^1.0.0"
+ configstore "^1.0.0"
+ inquirer "^0.10.0"
+ lodash.debounce "^3.0.1"
+ object-assign "^4.0.1"
+ os-name "^1.0.0"
+ request "^2.74.0"
+ tough-cookie "^2.0.0"
+ uuid "^3.0.0"
+
+insight@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/insight/-/insight-0.7.0.tgz#061f9189835bd38a97a60c2b76ea0c6b30099ff6"
+ dependencies:
+ async "^1.4.2"
+ chalk "^1.0.0"
+ configstore "^1.0.0"
+ inquirer "^0.10.0"
+ lodash.debounce "^3.0.1"
+ object-assign "^4.0.1"
+ os-name "^1.0.0"
+ request "^2.40.0"
+ tough-cookie "^2.0.0"
+
+interpret@^1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90"
+
+is-arrayish@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
+
+is-builtin-module@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"
+ dependencies:
+ builtin-modules "^1.0.0"
+
+is-docker@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-1.1.0.tgz#f04374d4eee5310e9a8e113bf1495411e46176a1"
+
+is-finite@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
+ dependencies:
+ number-is-nan "^1.0.0"
+
+is-fullwidth-code-point@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
+ dependencies:
+ number-is-nan "^1.0.0"
+
+is-npm@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4"
+
+is-obj@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
+
+is-promise@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
+
+is-redirect@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24"
+
+is-regexp@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
+
+is-retry-allowed@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34"
+
+is-root@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-root/-/is-root-1.0.0.tgz#07b6c233bc394cd9d02ba15c966bd6660d6342d5"
+
+is-stream@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
+
+is-supported-regexp-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.0.tgz#8b520c85fae7a253382d4b02652e045576e13bb8"
+
+is-typedarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
+
+is-utf8@^0.2.0:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
+
+isarray@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
+
+isarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+
+isstream@~0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
+
+istextorbinary@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-2.1.0.tgz#dbed2a6f51be2f7475b68f89465811141b758874"
+ dependencies:
+ binaryextensions "1 || 2"
+ editions "^1.1.1"
+ textextensions "1 || 2"
+
+jhipster-core@1.2.8:
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/jhipster-core/-/jhipster-core-1.2.8.tgz#2211a468761a7132c5ddc7f101400e2fc57d5be4"
+ dependencies:
+ lodash "4.17.4"
+
+jodid25519@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967"
+ dependencies:
+ jsbn "~0.1.0"
+
+js-yaml@3.8.1:
+ version "3.8.1"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.1.tgz#782ba50200be7b9e5a8537001b7804db3ad02628"
+ dependencies:
+ argparse "^1.0.7"
+ esprima "^3.1.1"
+
+jsbn@~0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
+
+json-schema@0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
+
+json-stable-stringify@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
+ dependencies:
+ jsonify "~0.0.0"
+
+json-stringify-safe@~5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
+
+jsonify@~0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
+
+jsprim@^1.2.2:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.0.tgz#a3b87e40298d8c380552d8cc7628a0bb95a22918"
+ dependencies:
+ assert-plus "1.0.0"
+ extsprintf "1.0.2"
+ json-schema "0.2.3"
+ verror "1.3.6"
+
+latest-version@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-2.0.0.tgz#56f8d6139620847b8017f8f1f4d78e211324168b"
+ dependencies:
+ package-json "^2.0.0"
+
+levn@~0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
+ dependencies:
+ prelude-ls "~1.1.2"
+ type-check "~0.3.2"
+
+load-json-file@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
+ dependencies:
+ graceful-fs "^4.1.2"
+ parse-json "^2.2.0"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+ strip-bom "^2.0.0"
+
+lodash._getnative@^3.0.0:
+ version "3.9.1"
+ resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
+
+lodash.assignin@^4.0.9:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2"
+
+lodash.bind@^4.1.4:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35"
+
+lodash.debounce@^3.0.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-3.1.1.tgz#812211c378a94cc29d5aa4e3346cf0bfce3a7df5"
+ dependencies:
+ lodash._getnative "^3.0.0"
+
+lodash.defaults@^4.0.1:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
+
+lodash.filter@^4.4.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace"
+
+lodash.flatten@^4.2.0:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
+
+lodash.foreach@^4.3.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53"
+
+lodash.map@^4.4.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3"
+
+lodash.merge@^4.4.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.0.tgz#69884ba144ac33fe699737a6086deffadd0f89c5"
+
+lodash.pad@^4.1.0:
+ version "4.5.1"
+ resolved "https://registry.yarnpkg.com/lodash.pad/-/lodash.pad-4.5.1.tgz#4330949a833a7c8da22cc20f6a26c4d59debba70"
+
+lodash.padend@^4.1.0:
+ version "4.6.1"
+ resolved "https://registry.yarnpkg.com/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e"
+
+lodash.padstart@^4.1.0:
+ version "4.6.1"
+ resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b"
+
+lodash.pick@^4.2.1:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
+
+lodash.reduce@^4.4.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b"
+
+lodash.reject@^4.4.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415"
+
+lodash.some@^4.4.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d"
+
+lodash@4.17.4, lodash@^4.11.1, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.3.0, lodash@^4.6.1:
+ version "4.17.4"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
+
+lodash@^3.2.0, lodash@^3.3.1:
+ version "3.10.1"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
+
+log-symbols@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
+ dependencies:
+ chalk "^1.0.0"
+
+lolex@1.3.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31"
+
+loud-rejection@^1.0.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
+ dependencies:
+ currently-unhandled "^0.4.1"
+ signal-exit "^3.0.0"
+
+lowercase-keys@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306"
+
+lru-cache@^4.0.1:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e"
+ dependencies:
+ pseudomap "^1.0.1"
+ yallist "^2.0.0"
+
+map-obj@^1.0.0, map-obj@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
+
+mem-fs-editor@^2.0.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/mem-fs-editor/-/mem-fs-editor-2.3.0.tgz#42a0ae1f55e76fd03f09e7c7b15b6307bdf5cb13"
+ dependencies:
+ commondir "^1.0.1"
+ deep-extend "^0.4.0"
+ ejs "^2.3.1"
+ glob "^7.0.3"
+ globby "^4.0.0"
+ mkdirp "^0.5.0"
+ multimatch "^2.0.0"
+ rimraf "^2.2.8"
+ through2 "^2.0.0"
+ vinyl "^1.1.0"
+
+mem-fs@^1.1.0:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/mem-fs/-/mem-fs-1.1.3.tgz#b8ae8d2e3fcb6f5d3f9165c12d4551a065d989cc"
+ dependencies:
+ through2 "^2.0.0"
+ vinyl "^1.1.0"
+ vinyl-file "^2.0.0"
+
+meow@^3.0.0, meow@^3.3.0, meow@^3.5.0:
+ version "3.7.0"
+ resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
+ dependencies:
+ camelcase-keys "^2.0.0"
+ decamelize "^1.1.2"
+ loud-rejection "^1.0.0"
+ map-obj "^1.0.1"
+ minimist "^1.1.3"
+ normalize-package-data "^2.3.4"
+ object-assign "^4.0.1"
+ read-pkg-up "^1.0.1"
+ redent "^1.0.0"
+ trim-newlines "^1.0.0"
+
+mime-db@~1.27.0:
+ version "1.27.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1"
+
+mime-types@^2.1.12, mime-types@~2.1.7:
+ version "2.1.15"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed"
+ dependencies:
+ mime-db "~1.27.0"
+
+"minimatch@2 || 3", minimatch@3.0.x, minimatch@^3.0.0, minimatch@^3.0.2:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774"
+ dependencies:
+ brace-expansion "^1.0.0"
+
+minimist@0.0.8:
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
+
+minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
+
+mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1:
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
+ dependencies:
+ minimist "0.0.8"
+
+ms@0.7.3:
+ version "0.7.3"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff"
+
+multimatch@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b"
+ dependencies:
+ array-differ "^1.0.0"
+ array-union "^1.0.1"
+ arrify "^1.0.0"
+ minimatch "^3.0.0"
+
+mute-stream@0.0.5:
+ version "0.0.5"
+ resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0"
+
+mute-stream@0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.6.tgz#48962b19e169fd1dfc240b3f1e7317627bbc47db"
+
+node-status-codes@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/node-status-codes/-/node-status-codes-1.0.0.tgz#5ae5541d024645d32a58fcddc9ceecea7ae3ac2f"
+
+nopt@^3.0.0, nopt@~3.0.1:
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
+ dependencies:
+ abbrev "1"
+
+normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.8.tgz#d819eda2a9dedbd1ffa563ea4071d936782295bb"
+ dependencies:
+ hosted-git-info "^2.1.4"
+ is-builtin-module "^1.0.0"
+ semver "2 || 3 || 4 || 5"
+ validate-npm-package-license "^3.0.1"
+
+npm-keyword@^4.1.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/npm-keyword/-/npm-keyword-4.2.0.tgz#98ffebfdbb1336f27ef5fe1baca0dcacd0acf6c0"
+ dependencies:
+ got "^5.0.0"
+ object-assign "^4.0.1"
+ pinkie-promise "^2.0.0"
+ registry-url "^3.0.3"
+
+npmconf@^2.1.1:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/npmconf/-/npmconf-2.1.2.tgz#66606a4a736f1e77a059aa071a79c94ab781853a"
+ dependencies:
+ config-chain "~1.1.8"
+ inherits "~2.0.0"
+ ini "^1.2.0"
+ mkdirp "^0.5.0"
+ nopt "~3.0.1"
+ once "~1.3.0"
+ osenv "^0.1.0"
+ semver "2 || 3 || 4"
+ uid-number "0.0.5"
+
+npmlog@^2.0.3:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-2.0.4.tgz#98b52530f2514ca90d09ec5b22c8846722375692"
+ dependencies:
+ ansi "~0.3.1"
+ are-we-there-yet "~1.1.2"
+ gauge "~1.2.5"
+
+nth-check@~1.0.0, nth-check@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4"
+ dependencies:
+ boolbase "~1.0.0"
+
+number-is-nan@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
+
+oauth-sign@~0.8.1:
+ version "0.8.2"
+ resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
+
+object-assign@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-2.1.1.tgz#43c36e5d569ff8e4816c4efa8be02d26967c18aa"
+
+object-assign@^4.0.1, object-assign@^4.1.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
+
+object-values@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/object-values/-/object-values-1.0.0.tgz#72af839630119e5b98c3b02bb8c27e3237158105"
+
+once@^1.3.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ dependencies:
+ wrappy "1"
+
+once@~1.3.0:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20"
+ dependencies:
+ wrappy "1"
+
+onetime@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789"
+
+opn@^3.0.2:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/opn/-/opn-3.0.3.tgz#b6d99e7399f78d65c3baaffef1fb288e9b85243a"
+ dependencies:
+ object-assign "^4.0.1"
+
+optionator@^0.8.1:
+ version "0.8.2"
+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
+ dependencies:
+ deep-is "~0.1.3"
+ fast-levenshtein "~2.0.4"
+ levn "~0.3.0"
+ prelude-ls "~1.1.2"
+ type-check "~0.3.2"
+ wordwrap "~1.0.0"
+
+os-homedir@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
+
+os-name@^1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/os-name/-/os-name-1.0.3.tgz#1b379f64835af7c5a7f498b357cb95215c159edf"
+ dependencies:
+ osx-release "^1.0.0"
+ win-release "^1.0.0"
+
+os-shim@^0.1.2:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/os-shim/-/os-shim-0.1.3.tgz#6b62c3791cf7909ea35ed46e17658bb417cb3917"
+
+os-tmpdir@^1.0.0, os-tmpdir@~1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
+
+osenv@^0.1.0:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644"
+ dependencies:
+ os-homedir "^1.0.0"
+ os-tmpdir "^1.0.0"
+
+osx-release@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/osx-release/-/osx-release-1.1.0.tgz#f217911a28136949af1bf9308b241e2737d3cd6c"
+ dependencies:
+ minimist "^1.1.0"
+
+package-json@^2.0.0, package-json@^2.1.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/package-json/-/package-json-2.4.0.tgz#0d15bd67d1cbbddbb2ca222ff2edb86bcb31a8bb"
+ dependencies:
+ got "^5.0.0"
+ registry-auth-token "^3.0.1"
+ registry-url "^3.0.3"
+ semver "^5.1.0"
+
+pad-component@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/pad-component/-/pad-component-0.0.1.tgz#ad1f22ce1bf0fdc0d6ddd908af17f351a404b8ac"
+
+parse-help@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/parse-help/-/parse-help-0.1.1.tgz#2f4df942e77a5581bba9967c0c3f48e4c66d7dda"
+ dependencies:
+ execall "^1.0.0"
+
+parse-json@^2.1.0, parse-json@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
+ dependencies:
+ error-ex "^1.2.0"
+
+path-exists@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
+ dependencies:
+ pinkie-promise "^2.0.0"
+
+path-is-absolute@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+
+path-parse@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1"
+
+path-type@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
+ dependencies:
+ graceful-fs "^4.1.2"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+
+performance-now@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
+
+pify@^2.0.0, pify@^2.2.0, pify@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+
+pinkie-promise@^2.0.0, pinkie-promise@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
+ dependencies:
+ pinkie "^2.0.0"
+
+pinkie@^2.0.0:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
+
+pluralize@3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-3.1.0.tgz#84213d0a12356069daa84060c559242633161368"
+
+prelude-ls@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
+
+prepend-http@^1.0.1:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
+
+pretty-bytes@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-3.0.1.tgz#27d0008d778063a0b4811bb35c79f1bd5d5fbccf"
+ dependencies:
+ number-is-nan "^1.0.0"
+
+process-nextick-args@~1.0.6:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
+
+proto-list@~1.2.1:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
+
+pseudomap@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
+
+punycode@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
+
+qs@~6.4.0:
+ version "6.4.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
+
+randexp@0.4.4:
+ version "0.4.4"
+ resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.4.tgz#ba68265f4a9f9e85f5814d34e160291f939f168e"
+ dependencies:
+ discontinuous-range "1.0.0"
+ ret "~0.1.10"
+
+rc@^1.0.1, rc@^1.1.6:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95"
+ dependencies:
+ deep-extend "~0.4.0"
+ ini "~1.3.0"
+ minimist "^1.2.0"
+ strip-json-comments "~2.0.1"
+
+read-all-stream@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/read-all-stream/-/read-all-stream-3.1.0.tgz#35c3e177f2078ef789ee4bfafa4373074eaef4fa"
+ dependencies:
+ pinkie-promise "^2.0.0"
+ readable-stream "^2.0.0"
+
+read-chunk@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/read-chunk/-/read-chunk-1.0.1.tgz#5f68cab307e663f19993527d9b589cace4661194"
+
+read-pkg-up@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
+ dependencies:
+ find-up "^1.0.0"
+ read-pkg "^1.0.0"
+
+read-pkg@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
+ dependencies:
+ load-json-file "^1.0.0"
+ normalize-package-data "^2.3.2"
+ path-type "^1.0.0"
+
+readable-stream@1.1:
+ version "1.1.13"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e"
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.1"
+ isarray "0.0.1"
+ string_decoder "~0.10.x"
+
+readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2:
+ version "2.2.9"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.9.tgz#cf78ec6f4a6d1eb43d26488cac97f042e74b7fc8"
+ dependencies:
+ buffer-shims "~1.0.0"
+ core-util-is "~1.0.0"
+ inherits "~2.0.1"
+ isarray "~1.0.0"
+ process-nextick-args "~1.0.6"
+ string_decoder "~1.0.0"
+ util-deprecate "~1.0.1"
+
+readline2@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35"
+ dependencies:
+ code-point-at "^1.0.0"
+ is-fullwidth-code-point "^1.0.0"
+ mute-stream "0.0.5"
+
+rechoir@^0.6.2:
+ version "0.6.2"
+ resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
+ dependencies:
+ resolve "^1.1.6"
+
+redent@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
+ dependencies:
+ indent-string "^2.1.0"
+ strip-indent "^1.0.1"
+
+registry-auth-token@^3.0.1:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.1.tgz#fb0d3289ee0d9ada2cbb52af5dfe66cb070d3006"
+ dependencies:
+ rc "^1.1.6"
+ safe-buffer "^5.0.1"
+
+registry-url@^3.0.3:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942"
+ dependencies:
+ rc "^1.0.1"
+
+repeating@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
+ dependencies:
+ is-finite "^1.0.0"
+
+replace-ext@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924"
+
+request@^2.40.0, request@^2.74.0:
+ version "2.81.0"
+ resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
+ dependencies:
+ aws-sign2 "~0.6.0"
+ aws4 "^1.2.1"
+ caseless "~0.12.0"
+ combined-stream "~1.0.5"
+ extend "~3.0.0"
+ forever-agent "~0.6.1"
+ form-data "~2.1.1"
+ har-validator "~4.2.1"
+ hawk "~3.1.3"
+ http-signature "~1.1.0"
+ is-typedarray "~1.0.0"
+ isstream "~0.1.2"
+ json-stringify-safe "~5.0.1"
+ mime-types "~2.1.7"
+ oauth-sign "~0.8.1"
+ performance-now "^0.2.0"
+ qs "~6.4.0"
+ safe-buffer "^5.0.1"
+ stringstream "~0.0.4"
+ tough-cookie "~2.3.0"
+ tunnel-agent "^0.6.0"
+ uuid "^3.0.0"
+
+resolve@^1.1.6:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5"
+ dependencies:
+ path-parse "^1.0.5"
+
+restore-cursor@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
+ dependencies:
+ exit-hook "^1.0.0"
+ onetime "^1.0.0"
+
+ret@~0.1.10:
+ version "0.1.14"
+ resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.14.tgz#58c636837b12e161f8a380cf081c6a230fd1664e"
+
+rimraf@^2.2.0, rimraf@^2.2.8, rimraf@^2.4.4:
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d"
+ dependencies:
+ glob "^7.0.5"
+
+root-check@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/root-check/-/root-check-1.0.0.tgz#c52a794bf0db9fad567536e41898f0c9e0a86697"
+ dependencies:
+ downgrade-root "^1.0.0"
+ sudo-block "^1.1.0"
+
+run-async@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389"
+ dependencies:
+ once "^1.3.0"
+
+run-async@^2.0.0, run-async@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
+ dependencies:
+ is-promise "^2.1.0"
+
+rx-lite@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
+
+rx@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782"
+
+safe-buffer@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7"
+
+samsam@1.1.2, samsam@~1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567"
+
+semver-diff@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36"
+ dependencies:
+ semver "^5.0.3"
+
+semver-regex@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-1.0.0.tgz#92a4969065f9c70c694753d55248fc68f8f652c9"
+
+semver-truncate@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/semver-truncate/-/semver-truncate-1.1.2.tgz#57f41de69707a62709a7e0104ba2117109ea47e8"
+ dependencies:
+ semver "^5.3.0"
+
+"semver@2 || 3 || 4", semver@^4.0.3:
+ version "4.3.6"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da"
+
+"semver@2 || 3 || 4 || 5", semver@5.3.0, semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
+
+set-immediate-shim@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
+
+shelljs@0.7.6, shelljs@^0.7.0:
+ version "0.7.6"
+ resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.6.tgz#379cccfb56b91c8601e4793356eb5382924de9ad"
+ dependencies:
+ glob "^7.0.0"
+ interpret "^1.0.0"
+ rechoir "^0.6.2"
+
+signal-exit@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
+
+sinon@^1.17.2:
+ version "1.17.7"
+ resolved "https://registry.yarnpkg.com/sinon/-/sinon-1.17.7.tgz#4542a4f49ba0c45c05eb2e9dd9d203e2b8efe0bf"
+ dependencies:
+ formatio "1.1.1"
+ lolex "1.3.2"
+ samsam "1.1.2"
+ util ">=0.10.3 <1"
+
+slide@^1.1.5:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707"
+
+sntp@1.x.x:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198"
+ dependencies:
+ hoek "2.x.x"
+
+sort-on@^1.0.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/sort-on/-/sort-on-1.3.0.tgz#0dfd5b364b23df7f2acd86985daeb889e1a7c840"
+ dependencies:
+ arrify "^1.0.0"
+ dot-prop "^2.0.0"
+
+source-map@~0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d"
+ dependencies:
+ amdefine ">=0.0.4"
+
+spawn-sync@^1.0.15:
+ version "1.0.15"
+ resolved "https://registry.yarnpkg.com/spawn-sync/-/spawn-sync-1.0.15.tgz#b00799557eb7fb0c8376c29d44e8a1ea67e57476"
+ dependencies:
+ concat-stream "^1.4.7"
+ os-shim "^0.1.2"
+
+spdx-correct@~1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40"
+ dependencies:
+ spdx-license-ids "^1.0.2"
+
+spdx-expression-parse@~1.0.0:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c"
+
+spdx-license-ids@^1.0.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57"
+
+sprintf-js@^1.0.3, sprintf-js@~1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+
+sshpk@^1.7.0:
+ version "1.13.0"
+ resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.0.tgz#ff2a3e4fd04497555fed97b39a0fd82fafb3a33c"
+ dependencies:
+ asn1 "~0.2.3"
+ assert-plus "^1.0.0"
+ dashdash "^1.12.0"
+ getpass "^0.1.1"
+ optionalDependencies:
+ bcrypt-pbkdf "^1.0.0"
+ ecc-jsbn "~0.1.1"
+ jodid25519 "^1.0.0"
+ jsbn "~0.1.0"
+ tweetnacl "~0.14.0"
+
+string-length@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/string-length/-/string-length-1.0.1.tgz#56970fb1c38558e9e70b728bf3de269ac45adfac"
+ dependencies:
+ strip-ansi "^3.0.0"
+
+string-template@~0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add"
+
+string-width@^1.0.0, string-width@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
+ dependencies:
+ code-point-at "^1.0.0"
+ is-fullwidth-code-point "^1.0.0"
+ strip-ansi "^3.0.0"
+
+string_decoder@~0.10.x:
+ version "0.10.31"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
+
+string_decoder@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.0.tgz#f06f41157b664d86069f84bdbdc9b0d8ab281667"
+ dependencies:
+ buffer-shims "~1.0.0"
+
+stringstream@~0.0.4:
+ version "0.0.5"
+ resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
+
+strip-ansi@^3.0.0, strip-ansi@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+ dependencies:
+ ansi-regex "^2.0.0"
+
+strip-bom-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz#f87db5ef2613f6968aa545abfe1ec728b6a829ca"
+ dependencies:
+ first-chunk-stream "^2.0.0"
+ strip-bom "^2.0.0"
+
+strip-bom@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
+ dependencies:
+ is-utf8 "^0.2.0"
+
+strip-indent@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
+ dependencies:
+ get-stdin "^4.0.1"
+
+strip-json-comments@~2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
+
+sudo-block@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/sudo-block/-/sudo-block-1.2.0.tgz#cc539bf8191624d4f507d83eeb45b4cea27f3463"
+ dependencies:
+ chalk "^1.0.0"
+ is-docker "^1.0.0"
+ is-root "^1.0.0"
+
+supports-color@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+
+supports-color@^3.1.2:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
+ dependencies:
+ has-flag "^1.0.0"
+
+tabtab@^1.3.0:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/tabtab/-/tabtab-1.3.2.tgz#bb9c2ca6324f659fde7634c2caf3c096e1187ca7"
+ dependencies:
+ debug "^2.2.0"
+ inquirer "^1.0.2"
+ minimist "^1.2.0"
+ mkdirp "^0.5.1"
+ npmlog "^2.0.3"
+ object-assign "^4.1.0"
+
+taketalk@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/taketalk/-/taketalk-1.0.0.tgz#b4d4f0deed206ae7df775b129ea2ca6de52f26dd"
+ dependencies:
+ get-stdin "^4.0.1"
+ minimist "^1.1.0"
+
+text-table@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+
+"textextensions@1 || 2":
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-2.1.0.tgz#1be0dc2a0dc244d44be8a09af6a85afb93c4dbc3"
+
+through2@^2.0.0:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be"
+ dependencies:
+ readable-stream "^2.1.5"
+ xtend "~4.0.1"
+
+through@^2.3.6:
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+
+timed-out@^3.0.0:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-3.1.3.tgz#95860bfcc5c76c277f8f8326fd0f5b2e20eba217"
+
+titleize@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/titleize/-/titleize-1.0.0.tgz#7d350722061830ba6617631e0cfd3ea08398d95a"
+
+tmp@^0.0.29:
+ version "0.0.29"
+ resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.29.tgz#f25125ff0dd9da3ccb0c2dd371ee1288bb9128c0"
+ dependencies:
+ os-tmpdir "~1.0.1"
+
+tough-cookie@^2.0.0, tough-cookie@~2.3.0:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a"
+ dependencies:
+ punycode "^1.4.1"
+
+traverse@^0.6.6:
+ version "0.6.6"
+ resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137"
+
+trim-newlines@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
+
+tunnel-agent@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
+ dependencies:
+ safe-buffer "^5.0.1"
+
+tweetnacl@^0.14.3, tweetnacl@~0.14.0:
+ version "0.14.5"
+ resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
+
+twig@^0.8.2:
+ version "0.8.9"
+ resolved "https://registry.yarnpkg.com/twig/-/twig-0.8.9.tgz#b1594f002b684e5f029de3e54e87bec4f084b6c2"
+ dependencies:
+ minimatch "3.0.x"
+ walk "2.3.x"
+
+type-check@~0.3.2:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
+ dependencies:
+ prelude-ls "~1.1.2"
+
+typedarray@^0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
+
+uid-number@0.0.5:
+ version "0.0.5"
+ resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.5.tgz#5a3db23ef5dbd55b81fce0ec9a2ac6fccdebb81e"
+
+underscore.string@^3.0.3:
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.3.4.tgz#2c2a3f9f83e64762fdc45e6ceac65142864213db"
+ dependencies:
+ sprintf-js "^1.0.3"
+ util-deprecate "^1.0.2"
+
+untildify@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/untildify/-/untildify-2.1.0.tgz#17eb2807987f76952e9c0485fc311d06a826a2e0"
+ dependencies:
+ os-homedir "^1.0.0"
+
+unzip-response@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-1.0.2.tgz#b984f0877fc0a89c2c773cc1ef7b5b232b5b06fe"
+
+update-notifier@^0.6.0:
+ version "0.6.3"
+ resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-0.6.3.tgz#776dec8daa13e962a341e8a1d98354306b67ae08"
+ dependencies:
+ boxen "^0.3.1"
+ chalk "^1.0.0"
+ configstore "^2.0.0"
+ is-npm "^1.0.0"
+ latest-version "^2.0.0"
+ semver-diff "^2.0.0"
+
+url-parse-lax@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73"
+ dependencies:
+ prepend-http "^1.0.1"
+
+user-home@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f"
+ dependencies:
+ os-homedir "^1.0.0"
+
+util-deprecate@^1.0.2, util-deprecate@~1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+
+"util@>=0.10.3 <1":
+ version "0.10.3"
+ resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
+ dependencies:
+ inherits "2.0.1"
+
+uuid@^2.0.1:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a"
+
+uuid@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1"
+
+validate-npm-package-license@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"
+ dependencies:
+ spdx-correct "~1.0.0"
+ spdx-expression-parse "~1.0.0"
+
+verror@1.3.6:
+ version "1.3.6"
+ resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c"
+ dependencies:
+ extsprintf "1.0.2"
+
+vinyl-file@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/vinyl-file/-/vinyl-file-2.0.0.tgz#a7ebf5ffbefda1b7d18d140fcb07b223efb6751a"
+ dependencies:
+ graceful-fs "^4.1.2"
+ pify "^2.3.0"
+ pinkie-promise "^2.0.0"
+ strip-bom "^2.0.0"
+ strip-bom-stream "^2.0.0"
+ vinyl "^1.1.0"
+
+vinyl@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884"
+ dependencies:
+ clone "^1.0.0"
+ clone-stats "^0.0.1"
+ replace-ext "0.0.1"
+
+walk@2.3.x:
+ version "2.3.9"
+ resolved "https://registry.yarnpkg.com/walk/-/walk-2.3.9.tgz#31b4db6678f2ae01c39ea9fb8725a9031e558a7b"
+ dependencies:
+ foreachasync "^3.0.0"
+
+which@^1.2.9:
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5"
+ dependencies:
+ isexe "^2.0.0"
+
+widest-line@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-1.0.0.tgz#0c09c85c2a94683d0d7eaf8ee097d564bf0e105c"
+ dependencies:
+ string-width "^1.0.1"
+
+win-release@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/win-release/-/win-release-1.1.1.tgz#5fa55e02be7ca934edfc12665632e849b72e5209"
+ dependencies:
+ semver "^5.0.1"
+
+wordwrap@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
+
+wrap-ansi@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
+ dependencies:
+ string-width "^1.0.1"
+ strip-ansi "^3.0.1"
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+
+write-file-atomic@^1.1.2:
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f"
+ dependencies:
+ graceful-fs "^4.1.11"
+ imurmurhash "^0.1.4"
+ slide "^1.1.5"
+
+xdg-basedir@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-2.0.0.tgz#edbc903cc385fc04523d966a335504b5504d1bd2"
+ dependencies:
+ os-homedir "^1.0.0"
+
+xtend@~4.0.0, xtend@~4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
+
+yallist@^2.0.0:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
+
+yeoman-assert@^2.0.0:
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/yeoman-assert/-/yeoman-assert-2.2.3.tgz#a5682a83632c50ac0ee84173a5a10fd6f3206474"
+
+yeoman-character@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/yeoman-character/-/yeoman-character-1.1.0.tgz#90d4b5beaf92759086177015b2fdfa2e0684d7c7"
+ dependencies:
+ supports-color "^3.1.2"
+
+yeoman-doctor@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/yeoman-doctor/-/yeoman-doctor-2.1.0.tgz#94ab784896a64f53a9fac452d5e9133e2750a236"
+ dependencies:
+ bin-version-check "^2.1.0"
+ chalk "^1.0.0"
+ each-async "^1.1.1"
+ log-symbols "^1.0.1"
+ object-values "^1.0.0"
+ semver "^5.0.3"
+ twig "^0.8.2"
+ user-home "^2.0.0"
+
+yeoman-environment@^1.1.0, yeoman-environment@^1.5.2, yeoman-environment@^1.6.1:
+ version "1.6.6"
+ resolved "https://registry.yarnpkg.com/yeoman-environment/-/yeoman-environment-1.6.6.tgz#cd85fa67d156060e440d7807d7ef7cf0d2d1d671"
+ dependencies:
+ chalk "^1.0.0"
+ debug "^2.0.0"
+ diff "^2.1.2"
+ escape-string-regexp "^1.0.2"
+ globby "^4.0.0"
+ grouped-queue "^0.3.0"
+ inquirer "^1.0.2"
+ lodash "^4.11.1"
+ log-symbols "^1.0.1"
+ mem-fs "^1.1.0"
+ text-table "^0.2.0"
+ untildify "^2.0.0"
+
+yeoman-generator@0.24.1, yeoman-generator@^0.24.1:
+ version "0.24.1"
+ resolved "https://registry.yarnpkg.com/yeoman-generator/-/yeoman-generator-0.24.1.tgz#1ca74429d9c5c95db0b22859ec180a2599bc1f8e"
+ dependencies:
+ async "^2.0.0"
+ chalk "^1.0.0"
+ class-extend "^0.1.0"
+ cli-table "^0.3.1"
+ cross-spawn "^4.0.0"
+ dargs "^4.0.0"
+ dateformat "^1.0.11"
+ debug "^2.1.0"
+ detect-conflict "^1.0.0"
+ error "^7.0.2"
+ find-up "^1.0.0"
+ github-username "^2.0.0"
+ glob "^7.0.3"
+ gruntfile-editor "^1.0.0"
+ html-wiring "^1.0.0"
+ istextorbinary "^2.1.0"
+ lodash "^4.11.1"
+ mem-fs-editor "^2.0.0"
+ mkdirp "^0.5.0"
+ nopt "^3.0.0"
+ path-exists "^2.0.0"
+ path-is-absolute "^1.0.0"
+ pretty-bytes "^3.0.1"
+ read-chunk "^1.0.0"
+ read-pkg-up "^1.0.1"
+ rimraf "^2.2.0"
+ run-async "^2.0.0"
+ shelljs "^0.7.0"
+ text-table "^0.2.0"
+ through2 "^2.0.0"
+ underscore.string "^3.0.3"
+ user-home "^2.0.0"
+ yeoman-assert "^2.0.0"
+ yeoman-environment "^1.1.0"
+ yeoman-test "^1.0.0"
+ yeoman-welcome "^1.0.0"
+
+yeoman-test@^1.0.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/yeoman-test/-/yeoman-test-1.6.0.tgz#abff291733e16e8923d9eefc8691c632888bf948"
+ dependencies:
+ inquirer "^1.0.2"
+ lodash "^4.3.0"
+ mkdirp "^0.5.1"
+ pinkie-promise "^2.0.1"
+ rimraf "^2.4.4"
+ sinon "^1.17.2"
+ yeoman-environment "^1.5.2"
+ yeoman-generator "^0.24.1"
+
+yeoman-welcome@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/yeoman-welcome/-/yeoman-welcome-1.0.1.tgz#f6cf198fd4fba8a771672c26cdfb8a64795c84ec"
+ dependencies:
+ chalk "^1.0.0"
+
+yo@1.8.5:
+ version "1.8.5"
+ resolved "https://registry.yarnpkg.com/yo/-/yo-1.8.5.tgz#776ab9ec79a7882f8d4f7a9e10214fdab050d928"
+ dependencies:
+ async "^1.0.0"
+ chalk "^1.0.0"
+ cli-list "^0.1.1"
+ configstore "^1.0.0"
+ cross-spawn "^3.0.1"
+ figures "^1.3.5"
+ fullname "^2.0.0"
+ got "^5.0.0"
+ humanize-string "^1.0.0"
+ inquirer "^0.11.0"
+ insight "^0.7.0"
+ lodash "^3.2.0"
+ meow "^3.0.0"
+ npm-keyword "^4.1.0"
+ opn "^3.0.2"
+ package-json "^2.1.0"
+ parse-help "^0.1.1"
+ read-pkg-up "^1.0.1"
+ repeating "^2.0.0"
+ root-check "^1.0.0"
+ sort-on "^1.0.0"
+ string-length "^1.0.0"
+ tabtab "^1.3.0"
+ titleize "^1.0.0"
+ update-notifier "^0.6.0"
+ user-home "^2.0.0"
+ yeoman-character "^1.0.0"
+ yeoman-doctor "^2.0.0"
+ yeoman-environment "^1.6.1"
+ yosay "^1.0.0"
+
+yosay@^1.0.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/yosay/-/yosay-1.2.1.tgz#9466ef969830e85b474e267b50f7688693ed3b5b"
+ dependencies:
+ ansi-regex "^2.0.0"
+ ansi-styles "^2.0.0"
+ chalk "^1.0.0"
+ cli-boxes "^1.0.0"
+ pad-component "0.0.1"
+ repeating "^2.0.0"
+ string-width "^1.0.0"
+ strip-ansi "^3.0.0"
+ taketalk "^1.0.0"
+ wrap-ansi "^2.0.0"
diff --git a/jhipster/jhipster-microservice/gateway-app/.bowerrc b/jhipster/jhipster-microservice/gateway-app/.bowerrc
new file mode 100644
index 0000000000..ad10799262
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/.bowerrc
@@ -0,0 +1,3 @@
+{
+ "directory": "src/main/webapp/bower_components"
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/.editorconfig b/jhipster/jhipster-microservice/gateway-app/.editorconfig
new file mode 100644
index 0000000000..a03599dd04
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/.editorconfig
@@ -0,0 +1,24 @@
+# EditorConfig helps developers define and maintain consistent
+# coding styles between different editors and IDEs
+# editorconfig.org
+
+root = true
+
+[*]
+
+# Change these settings to your own preference
+indent_style = space
+indent_size = 4
+
+# We recommend you to keep these unchanged
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
+
+[{package,bower}.json]
+indent_style = space
+indent_size = 2
diff --git a/jhipster/jhipster-microservice/gateway-app/.eslintignore b/jhipster/jhipster-microservice/gateway-app/.eslintignore
new file mode 100644
index 0000000000..047e14a334
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/.eslintignore
@@ -0,0 +1,6 @@
+# more info here - http://eslint.org/docs/user-guide/configuring.html#ignoring-files-and-directories
+
+# node_modules ignored by default
+
+# ignore bower_components
+src/main/webapp/bower_components
diff --git a/jhipster/jhipster-microservice/gateway-app/.eslintrc.json b/jhipster/jhipster-microservice/gateway-app/.eslintrc.json
new file mode 100644
index 0000000000..50047b2bc0
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/.eslintrc.json
@@ -0,0 +1,29 @@
+// See: http://eslint.org/
+// See: https://www.npmjs.com/package/eslint-plugin-angular
+{
+ "extends": [
+ "eslint:recommended",
+ "angular"
+ ],
+ "env": {
+ "node": true,
+ "browser": true
+ },
+ // severity for a rule should be one of the following: 0 = off, 1 = warning, 2 = error
+ "rules": {
+ // coding style
+ "wrap-iife": [2, "inside"],
+ "eqeqeq": 2,
+ "no-use-before-define": [2, "nofunc"],
+ "no-unused-vars": [2, {"vars": "local", "args": "none"}],
+ "no-multi-str": 2,
+ "no-irregular-whitespace": 2,
+ "semi": [2, "always"],
+ "indent": 2,
+
+ // os/git options
+ // we want to run on all OSes
+ "linebreak-style": 0,
+ "eol-last": 2
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/.gitattributes b/jhipster/jhipster-microservice/gateway-app/.gitattributes
new file mode 100644
index 0000000000..2a13efa88f
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/.gitattributes
@@ -0,0 +1,22 @@
+# All text files should have the "lf" (Unix) line endings
+* text eol=lf
+
+# Explicitly declare text files you want to always be normalized and converted
+# to native line endings on checkout.
+*.java text
+*.js text
+*.css text
+*.html text
+
+# Denote all files that are truly binary and should not be modified.
+*.png binary
+*.jpg binary
+*.jar binary
+*.pdf binary
+*.eot binary
+*.ttf binary
+*.gzip binary
+*.gz binary
+*.ai binary
+*.eps binary
+*.swf binary
diff --git a/jhipster/jhipster-microservice/gateway-app/.gitignore b/jhipster/jhipster-microservice/gateway-app/.gitignore
new file mode 100644
index 0000000000..74b29e2042
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/.gitignore
@@ -0,0 +1,141 @@
+######################
+# Project Specific
+######################
+/target/www/**
+/src/test/javascript/coverage/
+/src/test/javascript/PhantomJS*/
+
+######################
+# Node
+######################
+/node/
+node_tmp/
+node_modules/
+npm-debug.log.*
+
+######################
+# SASS
+######################
+.sass-cache/
+
+######################
+# Eclipse
+######################
+*.pydevproject
+.project
+.metadata
+tmp/
+tmp/**/*
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.classpath
+.settings/
+.loadpath
+.factorypath
+/src/main/resources/rebel.xml
+
+# External tool builders
+.externalToolBuilders/**
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# CDT-specific
+.cproject
+
+# PDT-specific
+.buildpath
+
+######################
+# Intellij
+######################
+.idea/
+*.iml
+*.iws
+*.ipr
+*.ids
+*.orig
+
+######################
+# Visual Studio Code
+######################
+.vscode/
+
+######################
+# Maven
+######################
+/log/
+/target/
+
+######################
+# Gradle
+######################
+.gradle/
+/build/
+
+######################
+# Package Files
+######################
+*.jar
+*.war
+*.ear
+*.db
+
+######################
+# Windows
+######################
+# Windows image file caches
+Thumbs.db
+
+# Folder config file
+Desktop.ini
+
+######################
+# Mac OSX
+######################
+.DS_Store
+.svn
+
+# Thumbnails
+._*
+
+# Files that might appear on external disk
+.Spotlight-V100
+.Trashes
+
+######################
+# Directories
+######################
+/bin/
+/deploy/
+
+######################
+# Logs
+######################
+*.log
+
+######################
+# Others
+######################
+*.class
+*.*~
+*~
+.merge_file*
+
+######################
+# Gradle Wrapper
+######################
+!gradle/wrapper/gradle-wrapper.jar
+
+######################
+# Maven Wrapper
+######################
+!.mvn/wrapper/maven-wrapper.jar
+
+######################
+# ESLint
+######################
+.eslintcache
diff --git a/jhipster/jhipster-microservice/gateway-app/.jhipster/Car.json b/jhipster/jhipster-microservice/gateway-app/.jhipster/Car.json
new file mode 100644
index 0000000000..ceaef3cd63
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/.jhipster/Car.json
@@ -0,0 +1,25 @@
+{
+ "fluentMethods": true,
+ "relationships": [],
+ "fields": [
+ {
+ "fieldName": "make",
+ "fieldType": "String"
+ },
+ {
+ "fieldName": "brand",
+ "fieldType": "String"
+ },
+ {
+ "fieldName": "price",
+ "fieldType": "Double"
+ }
+ ],
+ "changelogDate": "20170503041524",
+ "dto": "no",
+ "service": "no",
+ "entityTableName": "car",
+ "pagination": "infinite-scroll",
+ "microserviceName": "carapp",
+ "searchEngine": false
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/.jhipster/Dealer.json b/jhipster/jhipster-microservice/gateway-app/.jhipster/Dealer.json
new file mode 100644
index 0000000000..e9b4a8112e
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/.jhipster/Dealer.json
@@ -0,0 +1,21 @@
+{
+ "fluentMethods": true,
+ "relationships": [],
+ "fields": [
+ {
+ "fieldName": "name",
+ "fieldType": "String"
+ },
+ {
+ "fieldName": "address",
+ "fieldType": "String"
+ }
+ ],
+ "changelogDate": "20170503044952",
+ "dto": "no",
+ "service": "no",
+ "entityTableName": "dealer",
+ "pagination": "infinite-scroll",
+ "microserviceName": "dealerapp",
+ "searchEngine": false
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/.mvn/wrapper/maven-wrapper.jar b/jhipster/jhipster-microservice/gateway-app/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000000..5fd4d5023f
Binary files /dev/null and b/jhipster/jhipster-microservice/gateway-app/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/jhipster/jhipster-microservice/gateway-app/.mvn/wrapper/maven-wrapper.properties b/jhipster/jhipster-microservice/gateway-app/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000000..c954cec91c
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip
diff --git a/jhipster/jhipster-microservice/gateway-app/.yo-rc.json b/jhipster/jhipster-microservice/gateway-app/.yo-rc.json
new file mode 100644
index 0000000000..c6e9540740
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/.yo-rc.json
@@ -0,0 +1,29 @@
+{
+ "generator-jhipster": {
+ "jhipsterVersion": "4.0.8",
+ "baseName": "gateway",
+ "packageName": "com.gateway",
+ "packageFolder": "com/gateway",
+ "serverPort": "8080",
+ "authenticationType": "jwt",
+ "hibernateCache": "hazelcast",
+ "clusteredHttpSession": false,
+ "websocket": false,
+ "databaseType": "sql",
+ "devDatabaseType": "h2Disk",
+ "prodDatabaseType": "mysql",
+ "searchEngine": false,
+ "messageBroker": false,
+ "serviceDiscoveryType": "eureka",
+ "buildTool": "maven",
+ "enableSocialSignIn": false,
+ "jwtSecretKey": "cd875958b5c9a8fa965803fd599da3c13abf1015",
+ "clientFramework": "angular1",
+ "useSass": false,
+ "clientPackageManager": "yarn",
+ "applicationType": "gateway",
+ "testFrameworks": [],
+ "jhiPrefix": "jhi",
+ "enableTranslation": false
+ }
+}
\ No newline at end of file
diff --git a/jhipster/jhipster-microservice/gateway-app/README.md b/jhipster/jhipster-microservice/gateway-app/README.md
new file mode 100644
index 0000000000..8b10a5934f
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/README.md
@@ -0,0 +1,116 @@
+# gateway
+This application was generated using JHipster 4.0.8, you can find documentation and help at [https://jhipster.github.io/documentation-archive/v4.0.8](https://jhipster.github.io/documentation-archive/v4.0.8).
+
+This is a "gateway" application intended to be part of a microservice architecture, please refer to the [Doing microservices with JHipster][] page of the documentation for more information.
+
+This application is configured for Service Discovery and Configuration with the JHipster-Registry. On launch, it will refuse to start if it is not able to connect to the JHipster-Registry at [http://localhost:8761](http://localhost:8761). For more information, read our documentation on [Service Discovery and Configuration with the JHipster-Registry][].
+
+## Development
+
+Before you can build this project, you must install and configure the following dependencies on your machine:
+
+1. [Node.js][]: We use Node to run a development web server and build the project.
+ Depending on your system, you can install Node either from source or as a pre-packaged bundle.
+2. [Yarn][]: We use Yarn to manage Node dependencies.
+ Depending on your system, you can install Yarn either from source or as a pre-packaged bundle.
+
+After installing Node, you should be able to run the following command to install development tools.
+You will only need to run this command when dependencies change in [package.json](package.json).
+
+ yarn install
+
+We use [Gulp][] as our build system. Install the Gulp command-line tool globally with:
+
+ yarn global add gulp-cli
+
+Run the following commands in two separate terminals to create a blissful development experience where your browser
+auto-refreshes when files change on your hard drive.
+
+ ./mvnw
+ gulp
+
+[Bower][] is used to manage CSS and JavaScript dependencies used in this application. You can upgrade dependencies by
+specifying a newer version in [bower.json](bower.json). You can also run `bower update` and `bower install` to manage dependencies.
+Add the `-h` flag on any command to see how you can use it. For example, `bower update -h`.
+
+For further instructions on how to develop with JHipster, have a look at [Using JHipster in development][].
+
+
+## Building for production
+
+To optimize the gateway application for production, run:
+
+ ./mvnw -Pprod clean package
+
+This will concatenate and minify the client CSS and JavaScript files. It will also modify `index.html` so it references these new files.
+To ensure everything worked, run:
+
+ java -jar target/*.war
+
+Then navigate to [http://localhost:8080](http://localhost:8080) in your browser.
+
+Refer to [Using JHipster in production][] for more details.
+
+## Testing
+
+To launch your application's tests, run:
+
+ ./mvnw clean test
+
+### Client tests
+
+Unit tests are run by [Karma][] and written with [Jasmine][]. They're located in [src/test/javascript/](src/test/javascript/) and can be run with:
+
+ gulp test
+
+
+
+For more information, refer to the [Running tests page][].
+
+## Using Docker to simplify development (optional)
+
+You can use Docker to improve your JHipster development experience. A number of docker-compose configuration are available in the [src/main/docker](src/main/docker) folder to launch required third party services.
+For example, to start a mysql database in a docker container, run:
+
+ docker-compose -f src/main/docker/mysql.yml up -d
+
+To stop it and remove the container, run:
+
+ docker-compose -f src/main/docker/mysql.yml down
+
+You can also fully dockerize your application and all the services that it depends on.
+To achieve this, first build a docker image of your app by running:
+
+ ./mvnw package -Pprod docker:build
+
+Then run:
+
+ docker-compose -f src/main/docker/app.yml up -d
+
+For more information refer to [Using Docker and Docker-Compose][], this page also contains information on the docker-compose sub-generator (`yo jhipster:docker-compose`), which is able to generate docker configurations for one or several JHipster applications.
+
+## Continuous Integration (optional)
+
+To configure CI for your project, run the ci-cd sub-generator (`yo jhipster:ci-cd`), this will let you generate configuration files for a number of Continuous Integration systems. Consult the [Setting up Continuous Integration][] page for more information.
+
+[JHipster Homepage and latest documentation]: https://jhipster.github.io
+[JHipster 4.0.8 archive]: https://jhipster.github.io/documentation-archive/v4.0.8
+[Doing microservices with JHipster]: https://jhipster.github.io/documentation-archive/v4.0.8/microservices-architecture/
+[Using JHipster in development]: https://jhipster.github.io/documentation-archive/v4.0.8/development/
+[Service Discovery and Configuration with the JHipster-Registry]: https://jhipster.github.io/documentation-archive/v4.0.8/microservices-architecture/#jhipster-registry
+[Using Docker and Docker-Compose]: https://jhipster.github.io/documentation-archive/v4.0.8/docker-compose
+[Using JHipster in production]: https://jhipster.github.io/documentation-archive/v4.0.8/production/
+[Running tests page]: https://jhipster.github.io/documentation-archive/v4.0.8/running-tests/
+[Setting up Continuous Integration]: https://jhipster.github.io/documentation-archive/v4.0.8/setting-up-ci/
+
+
+[Node.js]: https://nodejs.org/
+[Yarn]: https://yarnpkg.org/
+[Bower]: http://bower.io/
+[Gulp]: http://gulpjs.com/
+[BrowserSync]: http://www.browsersync.io/
+[Karma]: http://karma-runner.github.io/
+[Jasmine]: http://jasmine.github.io/2.0/introduction.html
+[Protractor]: https://angular.github.io/protractor/
+[Leaflet]: http://leafletjs.com/
+[DefinitelyTyped]: http://definitelytyped.org/
diff --git a/jhipster/jhipster-microservice/gateway-app/bower.json b/jhipster/jhipster-microservice/gateway-app/bower.json
new file mode 100644
index 0000000000..eedc9790c2
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/bower.json
@@ -0,0 +1,52 @@
+{
+ "version": "0.0.0",
+ "name": "gateway",
+ "appPath": "src/main/webapp/",
+ "testPath": "src/test/javascript/spec",
+ "dependencies": {
+ "angular": "1.5.8",
+ "angular-aria": "1.5.8",
+ "angular-bootstrap": "1.3.3",
+ "angular-cache-buster": "0.4.3",
+ "angular-cookies": "1.5.8",
+ "ngstorage": "0.3.10",
+ "angular-loading-bar": "0.9.0",
+ "angular-resource": "1.5.8",
+ "angular-sanitize": "1.5.8",
+ "angular-ui-router": "0.3.1",
+ "bootstrap": "3.3.7",
+ "bootstrap-ui-datetime-picker": "2.4.3",
+ "jquery": "3.1.0",
+ "json3": "3.3.2",
+ "messageformat": "0.3.1",
+ "modernizr": "3.3.1",
+ "ng-file-upload": "12.0.4",
+ "ngInfiniteScroll": "1.3.0",
+ "swagger-ui": "2.1.5"
+ },
+ "devDependencies": {
+ "angular-mocks": "1.5.8"
+ },
+ "overrides": {
+ "angular": {
+ "dependencies": {
+ "jquery": "3.1.0"
+ }
+ },
+ "angular-cache-buster": {
+ "dependencies": {
+ "angular": "1.5.8"
+ }
+ },
+ "bootstrap": {
+ "main": [
+ "dist/css/bootstrap.css"
+ ]
+ }
+ },
+ "resolutions": {
+ "angular": "1.5.8",
+ "angular-bootstrap": "2.0.0",
+ "jquery": "3.1.0"
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/gulp/build.js b/jhipster/jhipster-microservice/gateway-app/gulp/build.js
new file mode 100644
index 0000000000..ecb5c362ce
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/gulp/build.js
@@ -0,0 +1,51 @@
+'use strict';
+
+var fs = require('fs'),
+ gulp = require('gulp'),
+ lazypipe = require('lazypipe'),
+ footer = require('gulp-footer'),
+ sourcemaps = require('gulp-sourcemaps'),
+ rev = require('gulp-rev'),
+ htmlmin = require('gulp-htmlmin'),
+ ngAnnotate = require('gulp-ng-annotate'),
+ prefix = require('gulp-autoprefixer'),
+ cssnano = require('gulp-cssnano'),
+ uglify = require('gulp-uglify'),
+ useref = require("gulp-useref"),
+ revReplace = require("gulp-rev-replace"),
+ plumber = require('gulp-plumber'),
+ gulpIf = require('gulp-if'),
+ handleErrors = require('./handle-errors');
+
+var config = require('./config');
+
+var initTask = lazypipe()
+ .pipe(sourcemaps.init);
+var jsTask = lazypipe()
+ .pipe(ngAnnotate)
+ .pipe(uglify);
+var cssTask = lazypipe()
+ .pipe(prefix)
+ .pipe(cssnano);
+
+module.exports = function() {
+ var templates = fs.readFileSync(config.tmp + '/templates.js');
+ var manifest = gulp.src(config.revManifest);
+
+ return gulp.src([config.app + '**/*.html',
+ '!' + config.app + 'app/**/*.html',
+ '!' + config.app + 'swagger-ui/**/*',
+ '!' + config.bower + '**/*.html'])
+ .pipe(plumber({errorHandler: handleErrors}))
+ //init sourcemaps and prepend semicolon
+ .pipe(useref({}, initTask))
+ //append html templates
+ .pipe(gulpIf('**/app.js', footer(templates)))
+ .pipe(gulpIf('*.js', jsTask()))
+ .pipe(gulpIf('*.css', cssTask()))
+ .pipe(gulpIf('*.html', htmlmin({collapseWhitespace: true})))
+ .pipe(gulpIf('**/*.!(html)', rev()))
+ .pipe(revReplace({manifest: manifest}))
+ .pipe(sourcemaps.write('.'))
+ .pipe(gulp.dest(config.dist));
+};
diff --git a/jhipster/jhipster-microservice/gateway-app/gulp/config.js b/jhipster/jhipster-microservice/gateway-app/gulp/config.js
new file mode 100644
index 0000000000..49df6e6ddd
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/gulp/config.js
@@ -0,0 +1,23 @@
+'use strict';
+
+module.exports = {
+ app: 'src/main/webapp/',
+ dist: 'target/www/',
+ swaggerDist: 'target/www/swagger-ui/',
+ test: 'src/test/javascript/',
+ bower: 'src/main/webapp/bower_components/',
+ tmp: 'target/tmp',
+ revManifest: 'target/tmp/rev-manifest.json',
+ port: 9000,
+ apiPort: 8080,
+ liveReloadPort: 35729,
+ uri: 'http://localhost:',
+ constantTemplate:
+ '(function () {\n' +
+ ' \'use strict\';\n' +
+ ' // DO NOT EDIT THIS FILE, EDIT THE GULP TASK NGCONSTANT SETTINGS INSTEAD WHICH GENERATES THIS FILE\n' +
+ ' angular\n' +
+ ' .module(\'<%- moduleName %>\')\n' +
+ '<% constants.forEach(function(constant) { %> .constant(\'<%- constant.name %>\', <%= constant.value %>)\n<% }) %>;\n' +
+ '})();\n'
+};
diff --git a/jhipster/jhipster-microservice/gateway-app/gulp/copy.js b/jhipster/jhipster-microservice/gateway-app/gulp/copy.js
new file mode 100644
index 0000000000..2e6e71ba71
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/gulp/copy.js
@@ -0,0 +1,81 @@
+'use strict';
+
+var gulp = require('gulp'),
+ rev = require('gulp-rev'),
+ plumber = require('gulp-plumber'),
+ es = require('event-stream'),
+ flatten = require('gulp-flatten'),
+ replace = require('gulp-replace'),
+ bowerFiles = require('main-bower-files'),
+ changed = require('gulp-changed');
+
+var handleErrors = require('./handle-errors');
+var config = require('./config');
+
+module.exports = {
+ fonts: fonts,
+ common: common,
+ swagger: swagger,
+ images: images
+}
+
+function fonts() {
+ return es.merge(gulp.src(config.bower + 'bootstrap/fonts/*.*')
+ .pipe(plumber({errorHandler: handleErrors}))
+ .pipe(changed(config.dist + 'content/fonts/'))
+ .pipe(rev())
+ .pipe(gulp.dest(config.dist + 'content/fonts/'))
+ .pipe(rev.manifest(config.revManifest, {
+ base: config.dist,
+ merge: true
+ }))
+ .pipe(gulp.dest(config.dist)),
+ gulp.src(config.app + 'content/**/*.{woff,woff2,svg,ttf,eot,otf}')
+ .pipe(plumber({errorHandler: handleErrors}))
+ .pipe(changed(config.dist + 'content/fonts/'))
+ .pipe(flatten())
+ .pipe(rev())
+ .pipe(gulp.dest(config.dist + 'content/fonts/'))
+ .pipe(rev.manifest(config.revManifest, {
+ base: config.dist,
+ merge: true
+ }))
+ .pipe(gulp.dest(config.dist))
+ );
+}
+
+function common() {
+ return gulp.src([config.app + 'robots.txt', config.app + 'favicon.ico', config.app + '.htaccess'], { dot: true })
+ .pipe(plumber({errorHandler: handleErrors}))
+ .pipe(changed(config.dist))
+ .pipe(gulp.dest(config.dist));
+}
+
+function swagger() {
+ return es.merge(
+ gulp.src([config.bower + 'swagger-ui/dist/**',
+ '!' + config.bower + 'swagger-ui/dist/index.html',
+ '!' + config.bower + 'swagger-ui/dist/swagger-ui.min.js',
+ '!' + config.bower + 'swagger-ui/dist/swagger-ui.js'])
+ .pipe(plumber({errorHandler: handleErrors}))
+ .pipe(changed(config.swaggerDist))
+ .pipe(gulp.dest(config.swaggerDist)),
+ gulp.src(config.app + 'swagger-ui/index.html')
+ .pipe(plumber({errorHandler: handleErrors}))
+ .pipe(changed(config.swaggerDist))
+ .pipe(replace('../bower_components/swagger-ui/dist/', ''))
+ .pipe(replace('swagger-ui.js', 'lib/swagger-ui.min.js'))
+ .pipe(gulp.dest(config.swaggerDist)),
+ gulp.src(config.bower + 'swagger-ui/dist/swagger-ui.min.js')
+ .pipe(plumber({errorHandler: handleErrors}))
+ .pipe(changed(config.swaggerDist + 'lib/'))
+ .pipe(gulp.dest(config.swaggerDist + 'lib/'))
+ );
+}
+
+function images() {
+ return gulp.src(bowerFiles({filter: ['**/*.{gif,jpg,png}']}), { base: config.bower })
+ .pipe(plumber({errorHandler: handleErrors}))
+ .pipe(changed(config.dist + 'bower_components'))
+ .pipe(gulp.dest(config.dist + 'bower_components'));
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/gulp/handle-errors.js b/jhipster/jhipster-microservice/gateway-app/gulp/handle-errors.js
new file mode 100644
index 0000000000..98c4d4a64c
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/gulp/handle-errors.js
@@ -0,0 +1,22 @@
+'use strict';
+
+var notify = require("gulp-notify");
+var argv = require('yargs').argv;
+
+module.exports = function() {
+
+ var args = Array.prototype.slice.call(arguments);
+ var notification = argv.notification === undefined ? true : argv.notification;
+ // Send error to notification center with gulp-notify
+ if(notification) {
+ notify.onError({
+ title: "JHipster Gulp Build",
+ subtitle: "Failure!",
+ message: "Error: <%= error.message %>",
+ sound: "Beep"
+ }).apply(this, args);
+ }
+ // Keep gulp from hanging on this task
+ this.emit('end');
+
+};
diff --git a/jhipster/jhipster-microservice/gateway-app/gulp/inject.js b/jhipster/jhipster-microservice/gateway-app/gulp/inject.js
new file mode 100644
index 0000000000..1808e31a99
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/gulp/inject.js
@@ -0,0 +1,69 @@
+'use strict';
+
+var gulp = require('gulp'),
+ plumber = require('gulp-plumber'),
+ inject = require('gulp-inject'),
+ es = require('event-stream'),
+ naturalSort = require('gulp-natural-sort'),
+ angularFilesort = require('gulp-angular-filesort'),
+ bowerFiles = require('main-bower-files');
+
+var handleErrors = require('./handle-errors');
+
+var config = require('./config');
+
+module.exports = {
+ app: app,
+ vendor: vendor,
+ test: test,
+ troubleshoot: troubleshoot
+}
+
+function app() {
+ return gulp.src(config.app + 'index.html')
+ .pipe(inject(gulp.src(config.app + 'app/**/*.js')
+ .pipe(plumber({errorHandler: handleErrors}))
+ .pipe(naturalSort())
+ .pipe(angularFilesort()), {relative: true}))
+ .pipe(gulp.dest(config.app));
+}
+
+function vendor() {
+ var stream = gulp.src(config.app + 'index.html')
+ .pipe(plumber({errorHandler: handleErrors}))
+ .pipe(inject(gulp.src(bowerFiles(), {read: false}), {
+ name: 'bower',
+ relative: true
+ }))
+ .pipe(gulp.dest(config.app));
+
+ return stream;
+}
+
+function test() {
+ return gulp.src(config.test + 'karma.conf.js')
+ .pipe(plumber({errorHandler: handleErrors}))
+ .pipe(inject(gulp.src(bowerFiles({includeDev: true, filter: ['**/*.js']}), {read: false}), {
+ starttag: '// bower:js',
+ endtag: '// endbower',
+ transform: function (filepath) {
+ return '\'' + filepath.substring(1, filepath.length) + '\',';
+ }
+ }))
+ .pipe(gulp.dest(config.test));
+}
+
+function troubleshoot() {
+ /* this task removes the troubleshooting content from index.html*/
+ return gulp.src(config.app + 'index.html')
+ .pipe(plumber({errorHandler: handleErrors}))
+ /* having empty src as we dont have to read any files*/
+ .pipe(inject(gulp.src('', {read: false}), {
+ starttag: '',
+ removeTags: true,
+ transform: function () {
+ return '';
+ }
+ }))
+ .pipe(gulp.dest(config.app));
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/gulp/serve.js b/jhipster/jhipster-microservice/gateway-app/gulp/serve.js
new file mode 100644
index 0000000000..243a01784f
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/gulp/serve.js
@@ -0,0 +1,62 @@
+'use strict';
+
+var gulp = require('gulp'),
+ util = require('./utils'),
+ url = require('url'),
+ browserSync = require('browser-sync'),
+ proxy = require('proxy-middleware');
+
+var config = require('./config');
+
+module.exports = function () {
+ var baseUri = config.uri + config.apiPort;
+ // Routes to proxy to the backend. Routes ending with a / will setup
+ // a redirect so that if accessed without a trailing slash, will
+ // redirect. This is required for some endpoints for proxy-middleware
+ // to correctly handle them.
+ var proxyRoutes = [
+ '/'
+ ];
+
+ var requireTrailingSlash = proxyRoutes.filter(function (r) {
+ return util.endsWith(r, '/');
+ }).map(function (r) {
+ // Strip trailing slash so we can use the route to match requests
+ // with non trailing slash
+ return r.substr(0, r.length - 1);
+ });
+
+ var proxies = [
+ // Ensure trailing slash in routes that require it
+ function (req, res, next) {
+ requireTrailingSlash.forEach(function (route){
+ if (url.parse(req.url).path === route) {
+ res.statusCode = 301;
+ res.setHeader('Location', route + '/');
+ res.end();
+ }
+ });
+
+ next();
+ }
+ ]
+ .concat(
+ // Build a list of proxies for routes: [route1_proxy, route2_proxy, ...]
+ proxyRoutes.map(function (r) {
+ var options = url.parse(baseUri + r);
+ options.route = r;
+ options.preserveHost = true;
+ return proxy(options);
+ }));
+
+ browserSync({
+ open: true,
+ port: config.port,
+ server: {
+ baseDir: config.app,
+ middleware: proxies
+ }
+ });
+
+ gulp.start('watch');
+};
diff --git a/jhipster/jhipster-microservice/gateway-app/gulp/utils.js b/jhipster/jhipster-microservice/gateway-app/gulp/utils.js
new file mode 100644
index 0000000000..abb80d3e31
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/gulp/utils.js
@@ -0,0 +1,36 @@
+'use strict';
+
+var fs = require('fs');
+
+module.exports = {
+ endsWith : endsWith,
+ parseVersion : parseVersion,
+ isLintFixed : isLintFixed
+};
+
+function endsWith(str, suffix) {
+ return str.indexOf('/', str.length - suffix.length) !== -1;
+}
+
+var parseString = require('xml2js').parseString;
+// return the version number from `pom.xml` file
+function parseVersion() {
+ var version = null;
+ var pomXml = fs.readFileSync('pom.xml', 'utf8');
+ parseString(pomXml, function (err, result) {
+ if (result.project.version && result.project.version[0]) {
+ version = result.project.version[0];
+ } else if (result.project.parent && result.project.parent[0] && result.project.parent[0].version && result.project.parent[0].version[0]) {
+ version = result.project.parent[0].version[0];
+ }
+ });
+ if (version === null) {
+ throw new Error('pom.xml is malformed. No version is defined');
+ }
+ return version;
+}
+
+function isLintFixed(file) {
+ // Has ESLint fixed the file contents?
+ return file.eslint !== null && file.eslint.fixed;
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/gulpfile.js b/jhipster/jhipster-microservice/gateway-app/gulpfile.js
new file mode 100644
index 0000000000..e4b86a0df0
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/gulpfile.js
@@ -0,0 +1,166 @@
+// Generated on 2017-05-03 using generator-jhipster 4.0.8
+'use strict';
+
+var gulp = require('gulp'),
+ rev = require('gulp-rev'),
+ templateCache = require('gulp-angular-templatecache'),
+ htmlmin = require('gulp-htmlmin'),
+ imagemin = require('gulp-imagemin'),
+ ngConstant = require('gulp-ng-constant'),
+ rename = require('gulp-rename'),
+ eslint = require('gulp-eslint'),
+ del = require('del'),
+ runSequence = require('run-sequence'),
+ browserSync = require('browser-sync'),
+ KarmaServer = require('karma').Server,
+ plumber = require('gulp-plumber'),
+ changed = require('gulp-changed'),
+ gulpIf = require('gulp-if');
+
+var handleErrors = require('./gulp/handle-errors'),
+ serve = require('./gulp/serve'),
+ util = require('./gulp/utils'),
+ copy = require('./gulp/copy'),
+ inject = require('./gulp/inject'),
+ build = require('./gulp/build');
+
+var config = require('./gulp/config');
+
+gulp.task('clean', function () {
+ return del([config.dist], { dot: true });
+});
+
+gulp.task('copy', ['copy:fonts', 'copy:common']);
+
+gulp.task('copy:fonts', copy.fonts);
+
+gulp.task('copy:common', copy.common);
+
+gulp.task('copy:swagger', copy.swagger);
+
+gulp.task('copy:images', copy.images);
+
+gulp.task('images', function () {
+ return gulp.src(config.app + 'content/images/**')
+ .pipe(plumber({errorHandler: handleErrors}))
+ .pipe(changed(config.dist + 'content/images'))
+ .pipe(imagemin({optimizationLevel: 5, progressive: true, interlaced: true}))
+ .pipe(rev())
+ .pipe(gulp.dest(config.dist + 'content/images'))
+ .pipe(rev.manifest(config.revManifest, {
+ base: config.dist,
+ merge: true
+ }))
+ .pipe(gulp.dest(config.dist))
+ .pipe(browserSync.reload({stream: true}));
+});
+
+
+gulp.task('styles', [], function () {
+ return gulp.src(config.app + 'content/css')
+ .pipe(browserSync.reload({stream: true}));
+});
+
+gulp.task('inject', function() {
+ runSequence('inject:dep', 'inject:app');
+});
+
+gulp.task('inject:dep', ['inject:test', 'inject:vendor']);
+
+gulp.task('inject:app', inject.app);
+
+gulp.task('inject:vendor', inject.vendor);
+
+gulp.task('inject:test', inject.test);
+
+gulp.task('inject:troubleshoot', inject.troubleshoot);
+
+gulp.task('assets:prod', ['images', 'styles', 'html', 'copy:swagger', 'copy:images'], build);
+
+gulp.task('html', function () {
+ return gulp.src(config.app + 'app/**/*.html')
+ .pipe(htmlmin({collapseWhitespace: true}))
+ .pipe(templateCache({
+ module: 'gatewayApp',
+ root: 'app/',
+ moduleSystem: 'IIFE'
+ }))
+ .pipe(gulp.dest(config.tmp));
+});
+
+gulp.task('ngconstant:dev', function () {
+ return ngConstant({
+ name: 'gatewayApp',
+ constants: {
+ VERSION: util.parseVersion(),
+ DEBUG_INFO_ENABLED: true
+ },
+ template: config.constantTemplate,
+ stream: true
+ })
+ .pipe(rename('app.constants.js'))
+ .pipe(gulp.dest(config.app + 'app/'));
+});
+
+gulp.task('ngconstant:prod', function () {
+ return ngConstant({
+ name: 'gatewayApp',
+ constants: {
+ VERSION: util.parseVersion(),
+ DEBUG_INFO_ENABLED: false
+ },
+ template: config.constantTemplate,
+ stream: true
+ })
+ .pipe(rename('app.constants.js'))
+ .pipe(gulp.dest(config.app + 'app/'));
+});
+
+// check app for eslint errors
+gulp.task('eslint', function () {
+ return gulp.src(['gulpfile.js', config.app + 'app/**/*.js'])
+ .pipe(plumber({errorHandler: handleErrors}))
+ .pipe(eslint())
+ .pipe(eslint.format())
+ .pipe(eslint.failOnError());
+});
+
+// check app for eslint errors anf fix some of them
+gulp.task('eslint:fix', function () {
+ return gulp.src(config.app + 'app/**/*.js')
+ .pipe(plumber({errorHandler: handleErrors}))
+ .pipe(eslint({
+ fix: true
+ }))
+ .pipe(eslint.format())
+ .pipe(gulpIf(util.isLintFixed, gulp.dest(config.app + 'app')));
+});
+
+gulp.task('test', ['inject:test', 'ngconstant:dev'], function (done) {
+ new KarmaServer({
+ configFile: __dirname + '/' + config.test + 'karma.conf.js',
+ singleRun: true
+ }, done).start();
+});
+
+
+gulp.task('watch', function () {
+ gulp.watch('bower.json', ['install']);
+ gulp.watch(['gulpfile.js', 'pom.xml'], ['ngconstant:dev']);
+ gulp.watch(config.app + 'content/css/**/*.css', ['styles']);
+ gulp.watch(config.app + 'content/images/**', ['images']);
+ gulp.watch(config.app + 'app/**/*.js', ['inject:app']);
+ gulp.watch([config.app + '*.html', config.app + 'app/**', config.app + 'i18n/**']).on('change', browserSync.reload);
+});
+
+gulp.task('install', function () {
+ runSequence(['inject:dep', 'ngconstant:dev'], 'inject:app', 'inject:troubleshoot');
+});
+
+gulp.task('serve', ['install'], serve);
+
+gulp.task('build', ['clean'], function (cb) {
+ runSequence(['copy', 'inject:vendor', 'ngconstant:prod'], 'inject:app', 'inject:troubleshoot', 'assets:prod', cb);
+});
+
+gulp.task('default', ['serve']);
diff --git a/jhipster/jhipster-microservice/gateway-app/mvnw b/jhipster/jhipster-microservice/gateway-app/mvnw
new file mode 100755
index 0000000000..a1ba1bf554
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/mvnw
@@ -0,0 +1,233 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven2 Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ #
+ # Look for the Apple JDKs first to preserve the existing behaviour, and then look
+ # for the new JDKs provided by Oracle.
+ #
+ if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then
+ #
+ # Apple JDKs
+ #
+ export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
+ fi
+
+ if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then
+ #
+ # Apple JDKs
+ #
+ export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
+ fi
+
+ if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then
+ #
+ # Oracle JDKs
+ #
+ export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
+ fi
+
+ if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then
+ #
+ # Apple JDKs
+ #
+ export JAVA_HOME=`/usr/libexec/java_home`
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Migwn, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+ # TODO classpath?
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+ local basedir=$(pwd)
+ local wdir=$(pwd)
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ wdir=$(cd "$wdir/.."; pwd)
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)}
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} "$@"
diff --git a/jhipster/jhipster-microservice/gateway-app/mvnw.cmd b/jhipster/jhipster-microservice/gateway-app/mvnw.cmd
new file mode 100644
index 0000000000..2b934e89dd
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/mvnw.cmd
@@ -0,0 +1,145 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven2 Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+set MAVEN_CMD_LINE_ARGS=%*
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+
+set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar""
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS%
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
\ No newline at end of file
diff --git a/jhipster/jhipster-microservice/gateway-app/package.json b/jhipster/jhipster-microservice/gateway-app/package.json
new file mode 100644
index 0000000000..ece70314ab
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/package.json
@@ -0,0 +1,68 @@
+{
+ "name": "gateway",
+ "version": "0.0.0",
+ "description": "Description for gateway",
+ "private": true,
+ "cacheDirectories": [
+ "node_modules",
+ "src/main/webapp/bower_components"
+ ],
+ "devDependencies": {
+ "bower": "1.7.9",
+ "browser-sync": "2.17.0",
+ "del": "2.2.2",
+ "eslint-config-angular": "0.5.0",
+ "eslint-plugin-angular": "1.3.1",
+ "event-stream": "3.3.4",
+ "generator-jhipster": "4.0.8",
+ "gulp": "3.9.1",
+ "gulp-angular-filesort": "1.1.1",
+ "gulp-angular-templatecache": "2.0.0",
+ "gulp-autoprefixer": "3.1.1",
+ "gulp-changed": "1.3.2",
+ "gulp-cssnano": "2.1.2",
+ "gulp-eslint": "3.0.1",
+ "gulp-flatten": "0.3.1",
+ "gulp-footer": "1.0.5",
+ "gulp-htmlmin": "2.0.0",
+ "gulp-if": "2.0.1",
+ "gulp-imagemin": "3.0.3",
+ "gulp-inject": "4.1.0",
+ "gulp-natural-sort": "0.1.1",
+ "gulp-ng-annotate": "2.0.0",
+ "gulp-ng-constant": "1.1.0",
+ "gulp-notify": "2.2.0",
+ "gulp-plumber": "1.1.0",
+ "gulp-rename": "1.2.2",
+ "gulp-replace": "0.5.4",
+ "gulp-rev": "7.1.2",
+ "gulp-rev-replace": "0.4.3",
+ "gulp-sourcemaps": "1.6.0",
+ "gulp-uglify": "2.0.0",
+ "gulp-useref": "3.1.2",
+ "jasmine-core": "2.5.0",
+ "karma": "1.2.0",
+ "karma-chrome-launcher": "2.0.0",
+ "karma-coverage": "1.1.1",
+ "karma-jasmine": "1.0.2",
+ "karma-junit-reporter": "1.1.0",
+ "karma-phantomjs-launcher": "1.0.2",
+ "karma-script-launcher": "1.0.0",
+ "lazypipe": "1.0.1",
+ "lodash": "4.15.0",
+ "main-bower-files": "2.13.1",
+ "map-stream": "0.0.6",
+ "phantomjs-prebuilt": "2.1.12",
+ "proxy-middleware": "0.15.0",
+ "run-sequence": "1.2.2",
+ "xml2js": "0.4.17",
+
+ "yargs": "5.0.0"
+ },
+ "engines": {
+ "node": "^4.3"
+ },
+ "scripts": {
+ "test": "gulp test"
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/pom.xml b/jhipster/jhipster-microservice/gateway-app/pom.xml
new file mode 100644
index 0000000000..dc9168d824
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/pom.xml
@@ -0,0 +1,1043 @@
+
+
+ 4.0.0
+
+
+ spring-boot-starter-parent
+ org.springframework.boot
+ 1.5.2.RELEASE
+
+
+
+ com.gateway
+ gateway
+ 0.0.1-SNAPSHOT
+ war
+ Gateway
+
+
+ ${maven.version}
+
+
+
+ -Djava.security.egd=file:/dev/./urandom -Xmx256m
+ 3.6.2
+ 2.0.0
+ 1.10
+ 2.5
+ 3.5
+ 0.4.13
+ 1.3
+ 1.2
+ 5.2.8.Final
+ 2.6.0
+ 0.7.9
+ 1.8
+ 3.21.0-GA
+ 1.0.0
+ 1.1.0
+ 0.7.0
+ 3.6
+ 2.0.0
+ 4.8
+ 1.3.0
+ jdt_apt
+ 1.1.0.Final
+ 3.6.0
+ 1.4.1
+ 3.0.1
+ yyyyMMddHHmmss
+ ${java.version}
+ ${java.version}
+ 3.0.0
+ 3.1.3
+ v6.10.0
+
+
+
+ 0.0.20
+
+ ${project.build.directory}/test-results
+ false
+ 3.2.2
+ 2.12.1
+ 3.2
+
+ src/main/webapp/content/**/*.*, src/main/webapp/bower_components/**/*.*, src/main/webapp/i18n/*.js, target/www/**/*.*
+
+ S3437,UndocumentedApi,BoldAndItalicTagsCheck
+
+
+ src/main/webapp/app/**/*.*
+ Web:BoldAndItalicTagsCheck
+
+ src/main/java/**/*
+ squid:S3437
+
+ src/main/java/**/*
+ squid:UndocumentedApi
+
+ ${project.testresult.directory}/coverage/jacoco/jacoco-it.exec
+ ${project.testresult.directory}/coverage/jacoco/jacoco.exec
+ jacoco
+
+ ${project.testresult.directory}/karma
+
+ ${project.testresult.directory}/coverage/report-lcov/lcov.info
+
+ ${project.testresult.directory}/coverage/report-lcov/lcov.info
+
+ ${project.basedir}/src/main/
+ ${project.testresult.directory}/surefire-reports
+ ${project.basedir}/src/test/
+
+ 2.5.0
+
+ Camden.SR5
+ 2.6.1
+ 1.4.10.Final
+ 1.1.0.Final
+ v0.21.3
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+ io.github.jhipster
+ jhipster
+ ${jhipster.server.version}
+
+
+ io.dropwizard.metrics
+ metrics-core
+
+
+ io.dropwizard.metrics
+ metrics-annotation
+ ${dropwizard-metrics.version}
+
+
+ io.dropwizard.metrics
+ metrics-json
+ ${dropwizard-metrics.version}
+
+
+ io.dropwizard.metrics
+ metrics-jvm
+ ${dropwizard-metrics.version}
+
+
+ io.dropwizard.metrics
+ metrics-servlet
+ ${dropwizard-metrics.version}
+
+
+ io.dropwizard.metrics
+ metrics-servlets
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-hibernate5
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-hppc
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-json-org
+
+
+ com.h2database
+ h2
+
+
+ com.hazelcast
+ hazelcast
+
+
+ com.hazelcast
+ hazelcast-hibernate52
+ ${hazelcast-hibernate52.version}
+
+
+ com.hazelcast
+ hazelcast-spring
+
+
+ org.awaitility
+ awaitility
+ ${awaitility.version}
+ test
+
+
+ com.jayway.jsonpath
+ json-path
+ test
+
+
+
+ io.springfox
+ springfox-swagger2
+ ${springfox.version}
+
+
+ org.mapstruct
+ mapstruct
+
+
+
+
+ io.springfox
+ springfox-bean-validators
+ ${springfox.version}
+
+
+ com.mattbertolini
+ liquibase-slf4j
+ ${liquibase-slf4j.version}
+
+
+ com.ryantenney.metrics
+ metrics-spring
+ ${metrics-spring.version}
+
+
+ com.codahale.metrics
+ metrics-annotation
+
+
+ com.codahale.metrics
+ metrics-core
+
+
+ com.codahale.metrics
+ metrics-healthchecks
+
+
+
+
+ com.zaxxer
+ HikariCP
+
+
+ tools
+ com.sun
+
+
+
+
+
+ commons-codec
+ commons-codec
+ ${commons-codec.version}
+
+
+ commons-io
+ commons-io
+ ${commons-io.version}
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang.version}
+
+
+ javax.cache
+ cache-api
+
+
+ mysql
+ mysql-connector-java
+
+
+ net.jpountz.lz4
+ lz4
+ ${lz4.version}
+
+
+ org.assertj
+ assertj-core
+ test
+
+
+ org.hibernate
+ hibernate-envers
+
+
+ org.hibernate
+ hibernate-validator
+
+
+ org.liquibase
+ liquibase-core
+
+
+ jetty-servlet
+ org.eclipse.jetty
+
+
+
+
+ org.mapstruct
+ mapstruct-jdk8
+ ${mapstruct.version}
+
+
+ org.springframework
+ spring-context-support
+
+
+ org.springframework.boot
+ spring-boot-actuator
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ org.springframework.boot
+ spring-boot-loader-tools
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+ org.springframework.boot
+ spring-boot-starter-mail
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.security
+ spring-security-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+
+
+
+
+ io.jsonwebtoken
+ jjwt
+ ${jjwt.version}
+
+
+
+ com.datastax.cassandra
+ cassandra-driver-core
+
+
+ com.codahale.metrics
+ metrics-core
+
+
+
+
+ com.datastax.cassandra
+ cassandra-driver-extras
+ ${cassandra-driver.version}
+
+
+ com.datastax.cassandra
+ cassandra-driver-mapping
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-zuul
+
+
+ org.springframework.cloud
+ spring-cloud-starter
+
+
+ org.springframework.cloud
+ spring-cloud-starter-ribbon
+
+
+
+ io.netty
+ netty-transport-native-epoll
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-hystrix
+
+
+ org.springframework.cloud
+ spring-cloud-starter-spectator
+
+
+ org.springframework.retry
+ spring-retry
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+ org.springframework.cloud
+ spring-cloud-starter-feign
+
+
+ net.logstash.logback
+ logstash-logback-encoder
+ ${logstash-logback-encoder.version}
+
+
+ ch.qos.logback
+ logback-core
+
+
+ ch.qos.logback
+ logback-classic
+
+
+ ch.qos.logback
+ logback-access
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-cloud-connectors
+
+
+
+ org.springframework.security
+ spring-security-data
+
+
+
+
+ spring-boot:run
+
+
+ com.github.ekryd.sortpom
+ sortpom-maven-plugin
+ ${sortpom-maven-plugin.version}
+
+
+ verify
+
+ sort
+
+
+
+
+ true
+ 4
+ groupId,artifactId
+ groupId,artifactId
+ true
+ false
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+
+
+ org.mapstruct
+ mapstruct-processor
+ ${mapstruct.version}
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-eclipse-plugin
+
+ true
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ ${maven-enforcer-plugin.version}
+
+
+ enforce-versions
+
+ enforce
+
+
+
+
+
+
+ You are running an older version of Maven. JHipster requires at least Maven ${maven.version}
+ [${maven.version},)
+
+
+ You are running an older version of Java. JHipster requires at least JDK ${java.version}
+ [${java.version}.0,)
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ ${maven-resources-plugin.version}
+
+
+ default-resources
+ validate
+
+ copy-resources
+
+
+ target/classes
+ false
+
+ #
+
+
+
+ src/main/resources/
+ true
+
+ **/*.xml
+ **/*.yml
+
+
+
+ src/main/resources/
+ false
+
+ **/*.xml
+ **/*.yml
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ alphabetical
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ ${jacoco-maven-plugin.version}
+
+
+ pre-unit-tests
+
+ prepare-agent
+
+
+
+ ${project.testresult.directory}/coverage/jacoco/jacoco.exec
+
+
+
+
+ post-unit-test
+ test
+
+ report
+
+
+ ${project.testresult.directory}/coverage/jacoco/jacoco.exec
+ ${project.testresult.directory}/coverage/jacoco
+
+
+
+
+
+ org.sonarsource.scanner.maven
+ sonar-maven-plugin
+ ${sonar-maven-plugin.version}
+
+
+ org.liquibase
+ liquibase-maven-plugin
+ ${liquibase.version}
+
+ src/main/resources/config/liquibase/master.xml
+ src/main/resources/config/liquibase/changelog/${maven.build.timestamp}_changelog.xml
+ org.h2.Driver
+ jdbc:h2:file:./target/h2db/db/gateway
+
+ gateway
+
+ hibernate:spring:com.gateway.domain?dialect=org.hibernate.dialect.H2Dialect&hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy&hibernate.implicit_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
+ true
+ debug
+
+
+
+ org.javassist
+ javassist
+ ${javassist.version}
+
+
+ org.liquibase.ext
+ liquibase-hibernate5
+ ${liquibase-hibernate5.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+ ${project.parent.version}
+
+
+ javax.validation
+ validation-api
+ ${validation-api.version}
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+ true
+
+
+
+
+ com.spotify
+ docker-maven-plugin
+ ${docker-maven-plugin.version}
+
+ gateway
+ src/main/docker
+
+
+ /
+ ${project.build.directory}
+ ${project.build.finalName}.war
+
+
+
+
+
+
+
+
+
+
+ org.eclipse.m2e
+ lifecycle-mapping
+ 1.0.0
+
+
+
+
+
+ org.jacoco
+
+ jacoco-maven-plugin
+
+
+ ${jacoco-maven-plugin.version}
+
+
+ prepare-agent
+
+
+
+
+
+
+
+
+ com.github.eirslett
+ frontend-maven-plugin
+ ${frontend-maven-plugin.version}
+
+ install-node-and-yarn
+ yarn
+ bower
+ gulp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ no-liquibase
+
+ ,no-liquibase
+
+
+
+ swagger
+
+ ,swagger
+
+
+
+ dev
+
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-starter-undertow
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
+ src/main/webapp/
+
+
+
+
+
+
+ DEBUG
+
+ dev${profile.no-liquibase}
+
+
+
+ prod
+
+
+ org.springframework.boot
+ spring-boot-starter-undertow
+
+
+
+
+
+ maven-clean-plugin
+
+
+
+ target/www/
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
+ target/www/
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+
+
+
+
+ build-info
+
+
+
+
+
+ com.github.eirslett
+ frontend-maven-plugin
+ ${frontend-maven-plugin.version}
+
+
+ install node and yarn
+
+ install-node-and-yarn
+
+
+ ${node.version}
+ ${yarn.version}
+
+
+
+ yarn install
+
+ yarn
+
+
+ install
+
+
+
+ bower install
+
+ bower
+
+
+ install --no-color
+
+
+
+ gulp build
+
+ gulp
+
+
+ build --no-notification
+
+
+
+ gulp test
+
+ gulp
+
+ test
+
+ test --no-notification
+
+
+
+
+
+
+
+
+ INFO
+
+ prod${profile.swagger}${profile.no-liquibase}
+
+
+
+
+ cc
+
+
+ org.springframework.boot
+ spring-boot-starter-undertow
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
+ src/main/webapp/
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+ true
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ default-compile
+ none
+
+
+ default-testCompile
+ none
+
+
+
+
+ net.alchim31.maven
+ scala-maven-plugin
+ ${scala-maven-plugin.version}
+
+
+ compile
+ compile
+
+ add-source
+ compile
+
+
+
+ test-compile
+ test-compile
+
+ add-source
+ testCompile
+
+
+
+
+ incremental
+ true
+ ${scala.version}
+
+
+
+
+
+
+ DEBUG
+
+ dev,swagger
+
+
+
+
+ graphite
+
+
+ io.dropwizard.metrics
+ metrics-graphite
+
+
+
+
+
+ prometheus
+
+
+ io.prometheus
+ simpleclient
+ ${prometheus-simpleclient.version}
+
+
+ io.prometheus
+ simpleclient_servlet
+ ${prometheus-simpleclient.version}
+
+
+ io.prometheus
+ simpleclient_dropwizard
+ ${prometheus-simpleclient.version}
+
+
+
+
+
+ IDE
+
+
+ org.mapstruct
+ mapstruct-processor
+ ${mapstruct.version}
+
+
+
+
+
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/docker/Dockerfile b/jhipster/jhipster-microservice/gateway-app/src/main/docker/Dockerfile
new file mode 100644
index 0000000000..08c44eb8cf
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/docker/Dockerfile
@@ -0,0 +1,13 @@
+FROM openjdk:8-jre-alpine
+
+ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \
+ JHIPSTER_SLEEP=0
+
+# add directly the war
+ADD *.war /app.war
+
+VOLUME /tmp
+EXPOSE 8080 5701/udp
+CMD echo "The application will start in ${JHIPSTER_SLEEP}s..." && \
+ sleep ${JHIPSTER_SLEEP} && \
+ java -Djava.security.egd=file:/dev/./urandom -jar /app.war
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/docker/app.yml b/jhipster/jhipster-microservice/gateway-app/src/main/docker/app.yml
new file mode 100644
index 0000000000..bb53e40da5
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/docker/app.yml
@@ -0,0 +1,38 @@
+#-------------------------------------------------------------------------------
+# Note for using the rate-limiting:
+# The comment part won't be copied if you use the subgenerator docker-compose
+# you have to manually copy it
+#-------------------------------------------------------------------------------
+version: '2'
+services:
+ gateway-app:
+ image: gateway
+ environment:
+ - SPRING_PROFILES_ACTIVE=prod,swagger
+ - SPRING_CLOUD_CONFIG_URI=http://admin:$${jhipster.registry.password}@jhipster-registry:8761/config
+ - SPRING_DATASOURCE_URL=jdbc:mysql://gateway-mysql:3306/gateway?useUnicode=true&characterEncoding=utf8&useSSL=false
+ - SPRING_DATA_CASSANDRA_CONTACTPOINTS=gateway-cassandra
+ - JHIPSTER_SLEEP=30 # gives time for the Cassandra cluster to start and execute the migration scripts
+ ports:
+ - 8080:8080
+ gateway-mysql:
+ extends:
+ file: mysql.yml
+ service: gateway-mysql
+ # Uncomment to have Cassandra working with the gateway
+ # gateway-cassandra:
+ # extends:
+ # file: cassandra-cluster.yml
+ # service: gateway-cassandra
+ # gateway-cassandra-migration:
+ # extends:
+ # file: cassandra-migration.yml
+ # service: gateway-cassandra-migration
+ # environment:
+ # - CREATE_KEYSPACE_SCRIPT=create-keyspace-prod.cql
+ jhipster-registry:
+ extends:
+ file: jhipster-registry.yml
+ service: jhipster-registry
+ environment:
+ - SPRING_CLOUD_CONFIG_SERVER_NATIVE_SEARCH_LOCATIONS=file:./central-config/docker-config/
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/docker/cassandra-cluster.yml b/jhipster/jhipster-microservice/gateway-app/src/main/docker/cassandra-cluster.yml
new file mode 100644
index 0000000000..1329b4d3f3
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/docker/cassandra-cluster.yml
@@ -0,0 +1,22 @@
+version: '2'
+services:
+ gateway-cassandra:
+ image: cassandra:3.9
+ # volumes:
+ # - ~/volumes/jhipster/gateway/cassandra/:/var/lib/cassandra/data
+ ports:
+ - 7000:7000
+ - 7001:7001
+ - 7199:7199
+ - 9042:9042
+ - 9160:9160
+ gateway-cassandra-node:
+ image: cassandra:3.9
+ environment:
+ - CASSANDRA_SEEDS=gateway-cassandra
+ gateway-cassandra-migration:
+ extends:
+ file: cassandra-migration.yml
+ service: gateway-cassandra-migration
+ environment:
+ - CREATE_KEYSPACE_SCRIPT=create-keyspace-prod.cql
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/docker/cassandra-migration.yml b/jhipster/jhipster-microservice/gateway-app/src/main/docker/cassandra-migration.yml
new file mode 100644
index 0000000000..3e24f7814c
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/docker/cassandra-migration.yml
@@ -0,0 +1,12 @@
+version: '2'
+services:
+ gateway-cassandra-migration:
+ environment:
+ - CASSANDRA_CONTACT_POINT=gateway-cassandra
+ - USER=docker-cassandra-migration
+ # - DEBUG_LOG=1 # uncomment to show debug logs during the migration process
+ build:
+ context: .
+ dockerfile: cassandra/Cassandra-Migration.Dockerfile
+ volumes:
+ - ../resources/config/cql:/cql:ro
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/docker/cassandra.yml b/jhipster/jhipster-microservice/gateway-app/src/main/docker/cassandra.yml
new file mode 100644
index 0000000000..afb20a9732
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/docker/cassandra.yml
@@ -0,0 +1,18 @@
+version: '2'
+services:
+ gateway-cassandra:
+ image: cassandra:3.9
+ # volumes:
+ # - ~/volumes/jhipster/gateway/cassandra/:/var/lib/cassandra/data
+ ports:
+ - 7000:7000
+ - 7001:7001
+ - 7199:7199
+ - 9042:9042
+ - 9160:9160
+ gateway-cassandra-migration:
+ extends:
+ file: cassandra-migration.yml
+ service: gateway-cassandra-migration
+ environment:
+ - CREATE_KEYSPACE_SCRIPT=create-keyspace.cql
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/docker/cassandra/Cassandra-Migration.Dockerfile b/jhipster/jhipster-microservice/gateway-app/src/main/docker/cassandra/Cassandra-Migration.Dockerfile
new file mode 100644
index 0000000000..e5ceb1e56a
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/docker/cassandra/Cassandra-Migration.Dockerfile
@@ -0,0 +1,11 @@
+FROM cassandra:3.9
+
+# script to orchestrate the automatic keyspace creation and apply all migration scripts
+ADD cassandra/scripts/autoMigrate.sh /usr/local/bin/autoMigrate
+RUN chmod 755 /usr/local/bin/autoMigrate
+
+# script to run any cql script from src/main/resources/config/cql
+ADD cassandra/scripts/execute-cql.sh /usr/local/bin/execute-cql
+RUN chmod 755 /usr/local/bin/execute-cql
+
+ENTRYPOINT ["autoMigrate"]
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/docker/cassandra/scripts/autoMigrate.sh b/jhipster/jhipster-microservice/gateway-app/src/main/docker/cassandra/scripts/autoMigrate.sh
new file mode 100755
index 0000000000..83ed6347a2
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/docker/cassandra/scripts/autoMigrate.sh
@@ -0,0 +1,67 @@
+#!/usr/bin/env bash
+
+# Orchestrate the automatic execution of all the cql migration scripts when starting the cluster
+
+# Protect from iterating on empty directories
+shopt -s nullglob
+
+function log {
+ echo "[$(date)]: $*"
+}
+
+function logDebug {
+ ((DEBUG_LOG)) && echo "[DEBUG][$(date)]: $*"
+}
+
+function waitForClusterConnection() {
+ log "Waiting for Cassandra connection..."
+ retryCount=0
+ maxRetry=20
+ cqlsh -e "Describe KEYSPACES;" $CASSANDRA_CONTACT_POINT &>/dev/null
+ while [ $? -ne 0 ] && [ "$retryCount" -ne "$maxRetry" ]; do
+ logDebug 'Cassandra not reachable yet. sleep and retry. retryCount =' $retryCount
+ sleep 5
+ ((retryCount+=1))
+ cqlsh -e "Describe KEYSPACES;" $CASSANDRA_CONTACT_POINT &>/dev/null
+ done
+
+ if [ $? -ne 0 ]; then
+ log "Not connected after " $retryCount " retry. Abort the migration."
+ exit 1
+ fi
+
+ log "Connected to Cassandra cluster"
+}
+
+function executeScripts() {
+ local filePattern=$1
+ # loop over migration scripts
+ for cqlFile in $filePattern; do
+ . $EXECUTE_CQL_SCRIPT $cqlFile
+ done
+}
+
+# parse arguments
+if [ "$#" -gt 0 ]; then
+ log "Override for local usage"
+ CQL_FILES_PATH=$1
+ CREATE_KEYSPACE_SCRIPT="create-keyspace.cql" # default create-keyspace script
+ if [ "$#" -eq 2 ]; then
+ CREATE_KEYSPACE_SCRIPT=$2
+ fi
+ CREATE_KEYSPACE_SCRIPT_FOLDER="$(dirname $CQL_FILES_PATH)"
+ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+ EXECUTE_CQL_SCRIPT=$SCRIPT_DIR'/execute-cql.sh'
+else
+ CQL_FILES_PATH="/cql/changelog/"
+ EXECUTE_CQL_SCRIPT="./usr/local/bin/execute-cql"
+ CREATE_KEYSPACE_SCRIPT_FOLDER="/cql"
+fi
+
+log "Start Cassandra migration tool"
+waitForClusterConnection
+log "Use $CREATE_KEYSPACE_SCRIPT_FOLDER/$CREATE_KEYSPACE_SCRIPT script to create the keyspace if necessary"
+cqlsh -f $CREATE_KEYSPACE_SCRIPT_FOLDER'/'$CREATE_KEYSPACE_SCRIPT $CASSANDRA_CONTACT_POINT
+log "Execute all non already executed scripts from $CQL_FILES_PATH"
+executeScripts "$CQL_FILES_PATH*.cql"
+log "Migration done"
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/docker/cassandra/scripts/execute-cql.sh b/jhipster/jhipster-microservice/gateway-app/src/main/docker/cassandra/scripts/execute-cql.sh
new file mode 100755
index 0000000000..39739b56fe
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/docker/cassandra/scripts/execute-cql.sh
@@ -0,0 +1,124 @@
+#!/usr/bin/env bash
+
+KEYSPACE_NAME=gateway
+
+unset scripts
+declare -A scripts
+
+function log {
+ echo "[$(date)]: $*"
+}
+
+function logDebug {
+ ((DEBUG_LOG)) && echo "[DEBUG][$(date)]: $*"
+}
+
+function exitWithError() {
+ echo "ERROR :
+ $*"
+ exit 1
+}
+
+#usage checks
+if [ -z "$1" ]; then
+ echo "usage: ./execute-cql cqlFile.cql"
+ exit 1
+fi
+if [ -z "$CASSANDRA_CONTACT_POINT" ]; then
+ echo "CASSANDRA_CONTACT_POINT environment variable must be defined"
+ exit 1
+fi
+
+cqlFile=$1
+filename=$(basename "$1")
+
+#load already executed scripts in the `scripts` global variable: dictionary[scriptName->checksum]
+function loadExecutedScripts {
+ #allow spaces in cqlsh output
+ IFS=$'\n'
+ local rows=($(cqlsh -k $KEYSPACE_NAME -e "select * from schema_version" $CASSANDRA_CONTACT_POINT | tail -n+4 | sed '$d' |sed '$d'))
+
+ for r in "${rows[@]}"
+ do
+ local scriptName=$(echo "$r" |cut -d '|' -f 1 | sed s'/^[[:space:]]*//' | sed s'/[[:space:]]*$//')
+ local checksum=$(echo "$r" |cut -d '|' -f 2 | sed s'/^[[:space:]]*//' | sed s'/[[:space:]]*$//')
+ scripts+=(["$scriptName"]="$checksum")
+ done
+ unset IFS
+}
+
+function exists {
+ if [ "$2" != in ]; then
+ echo "Incorrect usage."
+ echo "Correct usage: exists {key} in {array}"
+ return 1
+ fi
+
+ eval '[ ${'$3'[$1]+exists} ]'
+}
+
+function checksumEquals {
+ local checksum=$(md5sum $cqlFile | cut -d ' ' -f 1)
+ local foundChecksum=${scripts[${filename}]}
+
+ if [[ "$checksum" == "$foundChecksum" ]]; then
+ logDebug "checksum equals for $cqlFile, checksum=$checksum"
+ return 0
+ else
+ logDebug "different checksum found for $cqlFile
+ checksum=$checksum
+ foundChecksum=$foundChecksum"
+ return 1
+ fi
+}
+
+function isExecuted {
+ if exists $filename in scripts; then
+ if checksumEquals $cqlFile; then
+ return 0
+ else
+ exitWithError "$cqlFile has already been executed but has a different checksum logged in the schema_version table.
+ scripts must not be changed after being executed.
+ to resolve this issue you can:
+ - revert the modified script to its initial state and create a new script
+ OR
+ - delete the script entry from the schema_version table
+ "
+ fi
+ else
+ return 1
+ fi
+}
+
+function executeCqlScript {
+ log "execute: $cqlFile"
+ cqlsh -k $KEYSPACE_NAME -f $cqlFile $CASSANDRA_CONTACT_POINT
+
+ # if execution failed
+ if [ $? -ne 0 ]; then
+ exitWithError "fail to apply script $filename
+ stop applying database changes"
+ fi
+ logDebug "execution of $cqlFile succeeded"
+}
+
+function logExecutedScript {
+ local duration=$1
+ local checksum=$(md5sum $cqlFile | cut -d ' ' -f 1)
+
+ logDebug "save $cqlFile execution in schema_version table"
+ local query="INSERT INTO schema_version (script_name, checksum, executed_by, executed_on, execution_time, status) VALUES ('$filename', '$checksum', '$USER', toTimestamp(now()), $duration, 'success');"
+ cqlsh -k $KEYSPACE_NAME -e "$query" $CASSANDRA_CONTACT_POINT
+}
+
+loadExecutedScripts
+if isExecuted; then
+ logDebug "skipping $cqlFile already executed"
+else
+ _start=$(date +"%s")
+ executeCqlScript
+ _end=$(date +"%s")
+ duration=`expr $_end - $_start`
+ logExecutedScript $duration
+ log "$cqlFile executed with success in $duration seconds"
+fi
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/docker/central-server-config/README.md b/jhipster/jhipster-microservice/gateway-app/src/main/docker/central-server-config/README.md
new file mode 100644
index 0000000000..022a152863
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/docker/central-server-config/README.md
@@ -0,0 +1,7 @@
+# Central configuration sources details
+
+The JHipster-Registry will use the following directories as its configuration source :
+- localhost-config : when running the registry in docker with the jhipster-registry.yml docker-compose file
+- docker-config : when running the registry and the app both in docker with the app.yml docker-compose file
+
+For more info, refer to http://jhipster.github.io/microservices-architecture/#registry_app_configuration
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/docker/central-server-config/docker-config/application.yml b/jhipster/jhipster-microservice/gateway-app/src/main/docker/central-server-config/docker-config/application.yml
new file mode 100644
index 0000000000..f11d367241
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/docker/central-server-config/docker-config/application.yml
@@ -0,0 +1,15 @@
+# Common configuration shared between all applications
+configserver:
+ name: Docker JHipster Registry
+ status: Connected to the JHipster Registry running in Docker
+
+jhipster:
+ security:
+ authentication:
+ jwt:
+ secret: my-secret-token-to-change-in-production
+
+eureka:
+ client:
+ serviceUrl:
+ defaultZone: http://admin:${jhipster.registry.password}@jhipster-registry:8761/eureka/
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/docker/central-server-config/localhost-config/application.yml b/jhipster/jhipster-microservice/gateway-app/src/main/docker/central-server-config/localhost-config/application.yml
new file mode 100644
index 0000000000..052a6d0535
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/docker/central-server-config/localhost-config/application.yml
@@ -0,0 +1,15 @@
+# Common configuration shared between all applications
+configserver:
+ name: Docker JHipster Registry
+ status: Connected to the JHipster Registry running in Docker
+
+jhipster:
+ security:
+ authentication:
+ jwt:
+ secret: my-secret-token-to-change-in-production
+
+eureka:
+ client:
+ serviceUrl:
+ defaultZone: http://admin:${jhipster.registry.password}@localhost:8761/eureka/
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/docker/jhipster-registry.yml b/jhipster/jhipster-microservice/gateway-app/src/main/docker/jhipster-registry.yml
new file mode 100644
index 0000000000..58feb685d4
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/docker/jhipster-registry.yml
@@ -0,0 +1,18 @@
+version: '2'
+services:
+ jhipster-registry:
+ image: jhipster/jhipster-registry:v2.5.8
+ volumes:
+ - ./central-server-config:/central-config
+ # When run with the "dev" Spring profile, the JHipster Registry will
+ # read the config from the local filesystem (central-server-config directory)
+ # When run with the "prod" Spring profile, it will read the config from a git repository
+ # See http://jhipster.github.io/microservices-architecture/#registry_app_configuration
+ environment:
+ - SPRING_PROFILES_ACTIVE=dev
+ - SECURITY_USER_PASSWORD=admin
+ - SPRING_CLOUD_CONFIG_SERVER_NATIVE_SEARCH_LOCATIONS=file:./central-config/localhost-config/
+ # - GIT_URI=https://github.com/jhipster/jhipster-registry/
+ # - GIT_SEARCH_PATHS=central-config
+ ports:
+ - 8761:8761
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/docker/mysql.yml b/jhipster/jhipster-microservice/gateway-app/src/main/docker/mysql.yml
new file mode 100644
index 0000000000..464243fd14
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/docker/mysql.yml
@@ -0,0 +1,13 @@
+version: '2'
+services:
+ gateway-mysql:
+ image: mysql:5.7.13
+ # volumes:
+ # - ~/volumes/jhipster/gateway/mysql/:/var/lib/mysql/
+ environment:
+ - MYSQL_USER=root
+ - MYSQL_ALLOW_EMPTY_PASSWORD=yes
+ - MYSQL_DATABASE=gateway
+ ports:
+ - 3306:3306
+ command: mysqld --lower_case_table_names=1 --skip-ssl --character_set_server=utf8
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/docker/sonar.yml b/jhipster/jhipster-microservice/gateway-app/src/main/docker/sonar.yml
new file mode 100644
index 0000000000..2790075014
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/docker/sonar.yml
@@ -0,0 +1,7 @@
+version: '2'
+services:
+ gateway-sonar:
+ image: sonarqube:6.2-alpine
+ ports:
+ - 9000:9000
+ - 9092:9092
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/ApplicationWebXml.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/ApplicationWebXml.java
new file mode 100644
index 0000000000..75c23ce9f5
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/ApplicationWebXml.java
@@ -0,0 +1,21 @@
+package com.gateway;
+
+import com.gateway.config.DefaultProfileUtil;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.support.SpringBootServletInitializer;
+
+/**
+ * This is a helper Java class that provides an alternative to creating a web.xml.
+ * This will be invoked only when the application is deployed to a servlet container like Tomcat, JBoss etc.
+ */
+public class ApplicationWebXml extends SpringBootServletInitializer {
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ /**
+ * set a default to use when no profile is configured.
+ */
+ DefaultProfileUtil.addDefaultProfile(application.application());
+ return application.sources(GatewayApp.class);
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/GatewayApp.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/GatewayApp.java
new file mode 100644
index 0000000000..1905b055b6
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/GatewayApp.java
@@ -0,0 +1,93 @@
+package com.gateway;
+
+import com.gateway.config.ApplicationProperties;
+import com.gateway.config.DefaultProfileUtil;
+
+import io.github.jhipster.config.JHipsterConstants;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.actuate.autoconfigure.*;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.core.env.Environment;
+
+import javax.annotation.PostConstruct;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.Collection;
+
+@ComponentScan
+@EnableAutoConfiguration(exclude = {MetricFilterAutoConfiguration.class, MetricRepositoryAutoConfiguration.class, MetricsDropwizardAutoConfiguration.class})
+@EnableConfigurationProperties({LiquibaseProperties.class, ApplicationProperties.class})
+@EnableDiscoveryClient
+@EnableZuulProxy
+public class GatewayApp {
+
+ private static final Logger log = LoggerFactory.getLogger(GatewayApp.class);
+
+ private final Environment env;
+
+ public GatewayApp(Environment env) {
+ this.env = env;
+ }
+
+ /**
+ * Initializes gateway.
+ *
+ * Spring profiles can be configured with a program arguments --spring.profiles.active=your-active-profile
+ *
+ * You can find more information on how profiles work with JHipster on http://jhipster.github.io/profiles/.
+ */
+ @PostConstruct
+ public void initApplication() {
+ Collection activeProfiles = Arrays.asList(env.getActiveProfiles());
+ if (activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) && activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_PRODUCTION)) {
+ log.error("You have misconfigured your application! It should not run " +
+ "with both the 'dev' and 'prod' profiles at the same time.");
+ }
+ if (activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) && activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_CLOUD)) {
+ log.error("You have misconfigured your application! It should not" +
+ "run with both the 'dev' and 'cloud' profiles at the same time.");
+ }
+ }
+
+ /**
+ * Main method, used to run the application.
+ *
+ * @param args the command line arguments
+ * @throws UnknownHostException if the local host name could not be resolved into an address
+ */
+ public static void main(String[] args) throws UnknownHostException {
+ SpringApplication app = new SpringApplication(GatewayApp.class);
+ DefaultProfileUtil.addDefaultProfile(app);
+ Environment env = app.run(args).getEnvironment();
+ String protocol = "http";
+ if (env.getProperty("server.ssl.key-store") != null) {
+ protocol = "https";
+ }
+ log.info("\n----------------------------------------------------------\n\t" +
+ "Application '{}' is running! Access URLs:\n\t" +
+ "Local: \t\t{}://localhost:{}\n\t" +
+ "External: \t{}://{}:{}\n\t" +
+ "Profile(s): \t{}\n----------------------------------------------------------",
+ env.getProperty("spring.application.name"),
+ protocol,
+ env.getProperty("server.port"),
+ protocol,
+ InetAddress.getLocalHost().getHostAddress(),
+ env.getProperty("server.port"),
+ env.getActiveProfiles());
+
+ String configServerStatus = env.getProperty("configserver.status");
+ log.info("\n----------------------------------------------------------\n\t" +
+ "Config Server: \t{}\n----------------------------------------------------------",
+ configServerStatus == null ? "Not found or not setup for this application" : configServerStatus);
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/aop/logging/LoggingAspect.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/aop/logging/LoggingAspect.java
new file mode 100644
index 0000000000..dd2c4464be
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/aop/logging/LoggingAspect.java
@@ -0,0 +1,79 @@
+package com.gateway.aop.logging;
+
+import io.github.jhipster.config.JHipsterConstants;
+
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.env.Environment;
+
+import java.util.Arrays;
+
+/**
+ * Aspect for logging execution of service and repository Spring components.
+ *
+ * By default, it only runs with the "dev" profile.
+ */
+@Aspect
+public class LoggingAspect {
+
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+ private final Environment env;
+
+ public LoggingAspect(Environment env) {
+ this.env = env;
+ }
+
+ /**
+ * Pointcut that matches all repositories, services and Web REST endpoints.
+ */
+ @Pointcut("within(com.gateway.repository..*) || within(com.gateway.service..*) || within(com.gateway.web.rest..*)")
+ public void loggingPointcut() {
+ // Method is empty as this is just a Pointcut, the implementations are in the advices.
+ }
+
+ /**
+ * Advice that logs methods throwing exceptions.
+ */
+ @AfterThrowing(pointcut = "loggingPointcut()", throwing = "e")
+ public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
+ if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
+ log.error("Exception in {}.{}() with cause = \'{}\' and exception = \'{}\'", joinPoint.getSignature().getDeclaringTypeName(),
+ joinPoint.getSignature().getName(), e.getCause() != null? e.getCause() : "NULL", e.getMessage(), e);
+
+ } else {
+ log.error("Exception in {}.{}() with cause = {}", joinPoint.getSignature().getDeclaringTypeName(),
+ joinPoint.getSignature().getName(), e.getCause() != null? e.getCause() : "NULL");
+ }
+ }
+
+ /**
+ * Advice that logs when a method is entered and exited.
+ */
+ @Around("loggingPointcut()")
+ public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
+ if (log.isDebugEnabled()) {
+ log.debug("Enter: {}.{}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
+ joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
+ }
+ try {
+ Object result = joinPoint.proceed();
+ if (log.isDebugEnabled()) {
+ log.debug("Exit: {}.{}() with result = {}", joinPoint.getSignature().getDeclaringTypeName(),
+ joinPoint.getSignature().getName(), result);
+ }
+ return result;
+ } catch (IllegalArgumentException e) {
+ log.error("Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()),
+ joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
+
+ throw e;
+ }
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/ApplicationProperties.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/ApplicationProperties.java
new file mode 100644
index 0000000000..18e87d7966
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/ApplicationProperties.java
@@ -0,0 +1,15 @@
+package com.gateway.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * Properties specific to JHipster.
+ *
+ *
+ * Properties are configured in the application.yml file.
+ *
+ */
+@ConfigurationProperties(prefix = "application", ignoreUnknownFields = false)
+public class ApplicationProperties {
+
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/AsyncConfiguration.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/AsyncConfiguration.java
new file mode 100644
index 0000000000..92ed89b5e4
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/AsyncConfiguration.java
@@ -0,0 +1,46 @@
+package com.gateway.config;
+
+import io.github.jhipster.async.ExceptionHandlingAsyncTaskExecutor;
+import io.github.jhipster.config.JHipsterProperties;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
+import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.*;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+
+@Configuration
+@EnableAsync
+@EnableScheduling
+public class AsyncConfiguration implements AsyncConfigurer {
+
+ private final Logger log = LoggerFactory.getLogger(AsyncConfiguration.class);
+
+ private final JHipsterProperties jHipsterProperties;
+
+ public AsyncConfiguration(JHipsterProperties jHipsterProperties) {
+ this.jHipsterProperties = jHipsterProperties;
+ }
+
+ @Override
+ @Bean(name = "taskExecutor")
+ public Executor getAsyncExecutor() {
+ log.debug("Creating Async Task Executor");
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ executor.setCorePoolSize(jHipsterProperties.getAsync().getCorePoolSize());
+ executor.setMaxPoolSize(jHipsterProperties.getAsync().getMaxPoolSize());
+ executor.setQueueCapacity(jHipsterProperties.getAsync().getQueueCapacity());
+ executor.setThreadNamePrefix("gateway-Executor-");
+ return new ExceptionHandlingAsyncTaskExecutor(executor);
+ }
+
+ @Override
+ public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
+ return new SimpleAsyncUncaughtExceptionHandler();
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/CacheConfiguration.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/CacheConfiguration.java
new file mode 100644
index 0000000000..d5f464f490
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/CacheConfiguration.java
@@ -0,0 +1,134 @@
+package com.gateway.config;
+
+import io.github.jhipster.config.JHipsterConstants;
+import io.github.jhipster.config.JHipsterProperties;
+
+import com.hazelcast.config.Config;
+import com.hazelcast.core.HazelcastInstance;
+import com.hazelcast.core.Hazelcast;
+import com.hazelcast.config.MapConfig;
+import com.hazelcast.config.EvictionPolicy;
+import com.hazelcast.config.MaxSizeConfig;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.web.ServerProperties;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.cloud.client.discovery.DiscoveryClient;
+import org.springframework.context.annotation.*;
+import org.springframework.core.env.Environment;
+
+import javax.annotation.PreDestroy;
+
+@Configuration
+@EnableCaching
+@AutoConfigureAfter(value = { MetricsConfiguration.class })
+@AutoConfigureBefore(value = { WebConfigurer.class, DatabaseConfiguration.class })
+public class CacheConfiguration {
+
+ private final Logger log = LoggerFactory.getLogger(CacheConfiguration.class);
+
+ private final Environment env;
+
+ private final DiscoveryClient discoveryClient;
+
+ private final ServerProperties serverProperties;
+
+ public CacheConfiguration(Environment env, DiscoveryClient discoveryClient, ServerProperties serverProperties) {
+ this.env = env;
+ this.discoveryClient = discoveryClient;
+ this.serverProperties = serverProperties;
+ }
+
+ @PreDestroy
+ public void destroy() {
+ log.info("Closing Cache Manager");
+ Hazelcast.shutdownAll();
+ }
+
+ @Bean
+ public CacheManager cacheManager(HazelcastInstance hazelcastInstance) {
+ log.debug("Starting HazelcastCacheManager");
+ CacheManager cacheManager = new com.hazelcast.spring.cache.HazelcastCacheManager(hazelcastInstance);
+ return cacheManager;
+ }
+
+ @Bean
+ public HazelcastInstance hazelcastInstance(JHipsterProperties jHipsterProperties) {
+ log.debug("Configuring Hazelcast");
+ Config config = new Config();
+ config.setInstanceName("gateway");
+ // The serviceId is by default the application's name, see Spring Boot's eureka.instance.appname property
+ String serviceId = discoveryClient.getLocalServiceInstance().getServiceId();
+ log.debug("Configuring Hazelcast clustering for instanceId: {}", serviceId);
+
+ // In development, everything goes through 127.0.0.1, with a different port
+ if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
+ log.debug("Application is running with the \"dev\" profile, Hazelcast " +
+ "cluster will only work with localhost instances");
+
+ System.setProperty("hazelcast.local.localAddress", "127.0.0.1");
+ config.getNetworkConfig().setPort(serverProperties.getPort() + 5701);
+ config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false);
+ config.getNetworkConfig().getJoin().getTcpIpConfig().setEnabled(true);
+ for (ServiceInstance instance : discoveryClient.getInstances(serviceId)) {
+ String clusterMember = "127.0.0.1:" + (instance.getPort() + 5701);
+ log.debug("Adding Hazelcast (dev) cluster member " + clusterMember);
+ config.getNetworkConfig().getJoin().getTcpIpConfig().addMember(clusterMember);
+ }
+ } else { // Production configuration, one host per instance all using port 5701
+ config.getNetworkConfig().setPort(5701);
+ config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false);
+ config.getNetworkConfig().getJoin().getTcpIpConfig().setEnabled(true);
+ for (ServiceInstance instance : discoveryClient.getInstances(serviceId)) {
+ String clusterMember = instance.getHost() + ":5701";
+ log.debug("Adding Hazelcast (prod) cluster member " + clusterMember);
+ config.getNetworkConfig().getJoin().getTcpIpConfig().addMember(clusterMember);
+ }
+ }
+ config.getMapConfigs().put("default", initializeDefaultMapConfig());
+ config.getMapConfigs().put("com.gateway.domain.*", initializeDomainMapConfig(jHipsterProperties));
+ return Hazelcast.newHazelcastInstance(config);
+ }
+
+ private MapConfig initializeDefaultMapConfig() {
+ MapConfig mapConfig = new MapConfig();
+
+ /*
+ Number of backups. If 1 is set as the backup-count for example,
+ then all entries of the map will be copied to another JVM for
+ fail-safety. Valid numbers are 0 (no backup), 1, 2, 3.
+ */
+ mapConfig.setBackupCount(0);
+
+ /*
+ Valid values are:
+ NONE (no eviction),
+ LRU (Least Recently Used),
+ LFU (Least Frequently Used).
+ NONE is the default.
+ */
+ mapConfig.setEvictionPolicy(EvictionPolicy.LRU);
+
+ /*
+ Maximum size of the map. When max size is reached,
+ map is evicted based on the policy defined.
+ Any integer between 0 and Integer.MAX_VALUE. 0 means
+ Integer.MAX_VALUE. Default is 0.
+ */
+ mapConfig.setMaxSizeConfig(new MaxSizeConfig(0, MaxSizeConfig.MaxSizePolicy.USED_HEAP_SIZE));
+
+ return mapConfig;
+ }
+
+ private MapConfig initializeDomainMapConfig(JHipsterProperties jHipsterProperties) {
+ MapConfig mapConfig = new MapConfig();
+ mapConfig.setTimeToLiveSeconds(jHipsterProperties.getCache().getHazelcast().getTimeToLiveSeconds());
+ return mapConfig;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/CloudDatabaseConfiguration.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/CloudDatabaseConfiguration.java
new file mode 100644
index 0000000000..ad025f4149
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/CloudDatabaseConfiguration.java
@@ -0,0 +1,24 @@
+package com.gateway.config;
+
+import io.github.jhipster.config.JHipsterConstants;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cache.CacheManager;
+import org.springframework.cloud.config.java.AbstractCloudConfig;
+import org.springframework.context.annotation.*;
+
+import javax.sql.DataSource;
+
+@Configuration
+@Profile(JHipsterConstants.SPRING_PROFILE_CLOUD)
+public class CloudDatabaseConfiguration extends AbstractCloudConfig {
+
+ private final Logger log = LoggerFactory.getLogger(CloudDatabaseConfiguration.class);
+
+ @Bean
+ public DataSource dataSource(CacheManager cacheManager) {
+ log.info("Configuring JDBC datasource from a cloud provider");
+ return connectionFactory().dataSource();
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/Constants.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/Constants.java
new file mode 100644
index 0000000000..aa79156573
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/Constants.java
@@ -0,0 +1,16 @@
+package com.gateway.config;
+
+/**
+ * Application constants.
+ */
+public final class Constants {
+
+ //Regex for acceptable logins
+ public static final String LOGIN_REGEX = "^[_'.@A-Za-z0-9-]*$";
+
+ public static final String SYSTEM_ACCOUNT = "system";
+ public static final String ANONYMOUS_USER = "anonymoususer";
+
+ private Constants() {
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/DatabaseConfiguration.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/DatabaseConfiguration.java
new file mode 100644
index 0000000000..83bf0db1bc
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/DatabaseConfiguration.java
@@ -0,0 +1,75 @@
+package com.gateway.config;
+
+import io.github.jhipster.config.JHipsterConstants;
+import io.github.jhipster.config.liquibase.AsyncSpringLiquibase;
+
+import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
+import liquibase.integration.spring.SpringLiquibase;
+import org.h2.tools.Server;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.core.env.Environment;
+import org.springframework.core.task.TaskExecutor;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import javax.sql.DataSource;
+import java.sql.SQLException;
+
+@Configuration
+@EnableJpaRepositories("com.gateway.repository")
+@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
+@EnableTransactionManagement
+public class DatabaseConfiguration {
+
+ private final Logger log = LoggerFactory.getLogger(DatabaseConfiguration.class);
+
+ private final Environment env;
+
+ public DatabaseConfiguration(Environment env) {
+ this.env = env;
+ }
+
+ /**
+ * Open the TCP port for the H2 database, so it is available remotely.
+ *
+ * @return the H2 database TCP server
+ * @throws SQLException if the server failed to start
+ */
+ @Bean(initMethod = "start", destroyMethod = "stop")
+ @Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)
+ public Server h2TCPServer() throws SQLException {
+ return Server.createTcpServer("-tcp","-tcpAllowOthers");
+ }
+
+ @Bean
+ public SpringLiquibase liquibase(@Qualifier("taskExecutor") TaskExecutor taskExecutor,
+ DataSource dataSource, LiquibaseProperties liquibaseProperties) {
+
+ // Use liquibase.integration.spring.SpringLiquibase if you don't want Liquibase to start asynchronously
+ SpringLiquibase liquibase = new AsyncSpringLiquibase(taskExecutor, env);
+ liquibase.setDataSource(dataSource);
+ liquibase.setChangeLog("classpath:config/liquibase/master.xml");
+ liquibase.setContexts(liquibaseProperties.getContexts());
+ liquibase.setDefaultSchema(liquibaseProperties.getDefaultSchema());
+ liquibase.setDropFirst(liquibaseProperties.isDropFirst());
+ if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_NO_LIQUIBASE)) {
+ liquibase.setShouldRun(false);
+ } else {
+ liquibase.setShouldRun(liquibaseProperties.isEnabled());
+ log.debug("Configuring Liquibase");
+ }
+ return liquibase;
+ }
+
+ @Bean
+ public Hibernate5Module hibernate5Module() {
+ return new Hibernate5Module();
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/DateTimeFormatConfiguration.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/DateTimeFormatConfiguration.java
new file mode 100644
index 0000000000..e9391c5b1d
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/DateTimeFormatConfiguration.java
@@ -0,0 +1,17 @@
+package com.gateway.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.format.FormatterRegistry;
+import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+
+@Configuration
+public class DateTimeFormatConfiguration extends WebMvcConfigurerAdapter {
+
+ @Override
+ public void addFormatters(FormatterRegistry registry) {
+ DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
+ registrar.setUseIsoFormat(true);
+ registrar.registerFormatters(registry);
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/DefaultProfileUtil.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/DefaultProfileUtil.java
new file mode 100644
index 0000000000..379abc93d5
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/DefaultProfileUtil.java
@@ -0,0 +1,48 @@
+package com.gateway.config;
+
+import io.github.jhipster.config.JHipsterConstants;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.core.env.Environment;
+
+import java.util.*;
+
+/**
+ * Utility class to load a Spring profile to be used as default
+ * when there is no spring.profiles.active set in the environment or as command line argument.
+ * If the value is not available in application.yml then dev profile will be used as default.
+ */
+public final class DefaultProfileUtil {
+
+ private static final String SPRING_PROFILE_DEFAULT = "spring.profiles.default";
+
+ private DefaultProfileUtil() {
+ }
+
+ /**
+ * Set a default to use when no profile is configured.
+ *
+ * @param app the Spring application
+ */
+ public static void addDefaultProfile(SpringApplication app) {
+ Map defProperties = new HashMap<>();
+ /*
+ * The default profile to use when no other profiles are defined
+ * This cannot be set in the application.yml file.
+ * See https://github.com/spring-projects/spring-boot/issues/1219
+ */
+ defProperties.put(SPRING_PROFILE_DEFAULT, JHipsterConstants.SPRING_PROFILE_DEVELOPMENT);
+ app.setDefaultProperties(defProperties);
+ }
+
+ /**
+ * Get the profiles that are applied else get default profiles.
+ */
+ public static String[] getActiveProfiles(Environment env) {
+ String[] profiles = env.getActiveProfiles();
+ if (profiles.length == 0) {
+ return env.getDefaultProfiles();
+ }
+ return profiles;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/GatewayConfiguration.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/GatewayConfiguration.java
new file mode 100644
index 0000000000..301d7304bd
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/GatewayConfiguration.java
@@ -0,0 +1,71 @@
+package com.gateway.config;
+
+import io.github.jhipster.config.JHipsterProperties;
+
+import com.gateway.gateway.ratelimiting.RateLimitingFilter;
+import com.gateway.gateway.ratelimiting.RateLimitingRepository;
+import com.gateway.gateway.accesscontrol.AccessControlFilter;
+import com.gateway.gateway.responserewriting.SwaggerBasePathRewritingFilter;
+
+import com.datastax.driver.core.*;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class GatewayConfiguration {
+
+ @Configuration
+ public static class SwaggerBasePathRewritingConfiguration {
+
+ @Bean
+ public SwaggerBasePathRewritingFilter swaggerBasePathRewritingFilter(){
+ return new SwaggerBasePathRewritingFilter();
+ }
+ }
+
+ @Configuration
+ public static class AccessControlFilterConfiguration {
+
+ @Bean
+ public AccessControlFilter accessControlFilter(RouteLocator routeLocator, JHipsterProperties jHipsterProperties){
+ return new AccessControlFilter(routeLocator, jHipsterProperties);
+ }
+ }
+
+ /**
+ * Configures the Zuul filter that limits the number of API calls per user.
+ *
+ * For this filter to work, you need to have:
+ *
+ *
A working Cassandra cluster
+ *
A schema with the JHipster rate-limiting tables configured, using the
+ * "create_keyspace.cql" and "create_tables.cql" scripts from the
+ * "src/main/resources/config/cql" directory
+ *
Your cluster configured in your application-*.yml files, using the
+ * "spring.data.cassandra" keys
+ *
+ */
+ @Configuration
+ @ConditionalOnProperty("jhipster.gateway.rate-limiting.enabled")
+ public static class RateLimitingConfiguration {
+
+ private final JHipsterProperties jHipsterProperties;
+
+ public RateLimitingConfiguration(JHipsterProperties jHipsterProperties) {
+ this.jHipsterProperties = jHipsterProperties;
+ }
+
+ @Bean
+ public RateLimitingRepository rateLimitingRepository(Session session) {
+ return new RateLimitingRepository(session);
+ }
+
+ @Bean
+ public RateLimitingFilter rateLimitingFilter(RateLimitingRepository rateLimitingRepository) {
+ return new RateLimitingFilter(rateLimitingRepository, jHipsterProperties);
+ }
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/LocaleConfiguration.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/LocaleConfiguration.java
new file mode 100644
index 0000000000..1affdfe7f4
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/LocaleConfiguration.java
@@ -0,0 +1,35 @@
+package com.gateway.config;
+
+import io.github.jhipster.config.locale.AngularCookieLocaleResolver;
+
+import org.springframework.context.EnvironmentAware;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+import org.springframework.web.servlet.LocaleResolver;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
+
+@Configuration
+public class LocaleConfiguration extends WebMvcConfigurerAdapter implements EnvironmentAware {
+
+ @Override
+ public void setEnvironment(Environment environment) {
+ // unused
+ }
+
+ @Bean(name = "localeResolver")
+ public LocaleResolver localeResolver() {
+ AngularCookieLocaleResolver cookieLocaleResolver = new AngularCookieLocaleResolver();
+ cookieLocaleResolver.setCookieName("NG_TRANSLATE_LANG_KEY");
+ return cookieLocaleResolver;
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
+ localeChangeInterceptor.setParamName("language");
+ registry.addInterceptor(localeChangeInterceptor);
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/LoggingAspectConfiguration.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/LoggingAspectConfiguration.java
new file mode 100644
index 0000000000..bd02cc46cf
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/LoggingAspectConfiguration.java
@@ -0,0 +1,19 @@
+package com.gateway.config;
+
+import com.gateway.aop.logging.LoggingAspect;
+
+import io.github.jhipster.config.JHipsterConstants;
+
+import org.springframework.context.annotation.*;
+import org.springframework.core.env.Environment;
+
+@Configuration
+@EnableAspectJAutoProxy
+public class LoggingAspectConfiguration {
+
+ @Bean
+ @Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)
+ public LoggingAspect loggingAspect(Environment env) {
+ return new LoggingAspect(env);
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/LoggingConfiguration.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/LoggingConfiguration.java
new file mode 100644
index 0000000000..c9c0a06adc
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/LoggingConfiguration.java
@@ -0,0 +1,113 @@
+package com.gateway.config;
+
+import io.github.jhipster.config.JHipsterProperties;
+
+import ch.qos.logback.classic.AsyncAppender;
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.spi.LoggerContextListener;
+import ch.qos.logback.core.spi.ContextAwareBase;
+import net.logstash.logback.appender.LogstashSocketAppender;
+import net.logstash.logback.stacktrace.ShortenedThrowableConverter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class LoggingConfiguration {
+
+ private final Logger log = LoggerFactory.getLogger(LoggingConfiguration.class);
+
+ private LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
+
+ @Value("${spring.application.name}")
+ private String appName;
+
+ @Value("${server.port}")
+ private String serverPort;
+
+ @Value("${eureka.instance.instanceId}")
+ private String instanceId;
+
+ private final JHipsterProperties jHipsterProperties;
+
+ public LoggingConfiguration(JHipsterProperties jHipsterProperties) {
+ this.jHipsterProperties = jHipsterProperties;
+ if (jHipsterProperties.getLogging().getLogstash().isEnabled()) {
+ addLogstashAppender(context);
+
+ // Add context listener
+ LogbackLoggerContextListener loggerContextListener = new LogbackLoggerContextListener();
+ loggerContextListener.setContext(context);
+ context.addListener(loggerContextListener);
+ }
+ }
+
+ public void addLogstashAppender(LoggerContext context) {
+ log.info("Initializing Logstash logging");
+
+ LogstashSocketAppender logstashAppender = new LogstashSocketAppender();
+ logstashAppender.setName("LOGSTASH");
+ logstashAppender.setContext(context);
+ String customFields = "{\"app_name\":\"" + appName + "\",\"app_port\":\"" + serverPort + "\"," +
+ "\"instance_id\":\"" + instanceId + "\"}";
+
+ // Set the Logstash appender config from JHipster properties
+ logstashAppender.setSyslogHost(jHipsterProperties.getLogging().getLogstash().getHost());
+ logstashAppender.setPort(jHipsterProperties.getLogging().getLogstash().getPort());
+ logstashAppender.setCustomFields(customFields);
+
+ // Limit the maximum length of the forwarded stacktrace so that it won't exceed the 8KB UDP limit of logstash
+ ShortenedThrowableConverter throwableConverter = new ShortenedThrowableConverter();
+ throwableConverter.setMaxLength(7500);
+ throwableConverter.setRootCauseFirst(true);
+ logstashAppender.setThrowableConverter(throwableConverter);
+
+ logstashAppender.start();
+
+ // Wrap the appender in an Async appender for performance
+ AsyncAppender asyncLogstashAppender = new AsyncAppender();
+ asyncLogstashAppender.setContext(context);
+ asyncLogstashAppender.setName("ASYNC_LOGSTASH");
+ asyncLogstashAppender.setQueueSize(jHipsterProperties.getLogging().getLogstash().getQueueSize());
+ asyncLogstashAppender.addAppender(logstashAppender);
+ asyncLogstashAppender.start();
+
+ context.getLogger("ROOT").addAppender(asyncLogstashAppender);
+ }
+
+ /**
+ * Logback configuration is achieved by configuration file and API.
+ * When configuration file change is detected, the configuration is reset.
+ * This listener ensures that the programmatic configuration is also re-applied after reset.
+ */
+ class LogbackLoggerContextListener extends ContextAwareBase implements LoggerContextListener {
+
+ @Override
+ public boolean isResetResistant() {
+ return true;
+ }
+
+ @Override
+ public void onStart(LoggerContext context) {
+ addLogstashAppender(context);
+ }
+
+ @Override
+ public void onReset(LoggerContext context) {
+ addLogstashAppender(context);
+ }
+
+ @Override
+ public void onStop(LoggerContext context) {
+ // Nothing to do.
+ }
+
+ @Override
+ public void onLevelChange(ch.qos.logback.classic.Logger logger, Level level) {
+ // Nothing to do.
+ }
+ }
+
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/MetricsConfiguration.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/MetricsConfiguration.java
new file mode 100644
index 0000000000..79689196df
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/MetricsConfiguration.java
@@ -0,0 +1,113 @@
+package com.gateway.config;
+
+import io.github.jhipster.config.JHipsterProperties;
+import io.github.jhipster.config.metrics.SpectatorLogMetricWriter;
+
+import com.netflix.spectator.api.Registry;
+import org.springframework.boot.actuate.autoconfigure.ExportMetricReader;
+import org.springframework.boot.actuate.autoconfigure.ExportMetricWriter;
+import org.springframework.boot.actuate.metrics.writer.MetricWriter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.cloud.netflix.metrics.spectator.SpectatorMetricReader;
+
+import com.codahale.metrics.JmxReporter;
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.Slf4jReporter;
+import com.codahale.metrics.health.HealthCheckRegistry;
+import com.codahale.metrics.jvm.*;
+import com.ryantenney.metrics.spring.config.annotation.EnableMetrics;
+import com.ryantenney.metrics.spring.config.annotation.MetricsConfigurerAdapter;
+import com.zaxxer.hikari.HikariDataSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.*;
+
+import javax.annotation.PostConstruct;
+import java.lang.management.ManagementFactory;
+import java.util.concurrent.TimeUnit;
+
+@Configuration
+@EnableMetrics(proxyTargetClass = true)
+public class MetricsConfiguration extends MetricsConfigurerAdapter {
+
+ private static final String PROP_METRIC_REG_JVM_MEMORY = "jvm.memory";
+ private static final String PROP_METRIC_REG_JVM_GARBAGE = "jvm.garbage";
+ private static final String PROP_METRIC_REG_JVM_THREADS = "jvm.threads";
+ private static final String PROP_METRIC_REG_JVM_FILES = "jvm.files";
+ private static final String PROP_METRIC_REG_JVM_BUFFERS = "jvm.buffers";
+ private final Logger log = LoggerFactory.getLogger(MetricsConfiguration.class);
+
+ private MetricRegistry metricRegistry = new MetricRegistry();
+
+ private HealthCheckRegistry healthCheckRegistry = new HealthCheckRegistry();
+
+ private final JHipsterProperties jHipsterProperties;
+
+ private HikariDataSource hikariDataSource;
+
+ public MetricsConfiguration(JHipsterProperties jHipsterProperties) {
+ this.jHipsterProperties = jHipsterProperties;
+ }
+
+ @Autowired(required = false)
+ public void setHikariDataSource(HikariDataSource hikariDataSource) {
+ this.hikariDataSource = hikariDataSource;
+ }
+
+ @Override
+ @Bean
+ public MetricRegistry getMetricRegistry() {
+ return metricRegistry;
+ }
+
+ @Override
+ @Bean
+ public HealthCheckRegistry getHealthCheckRegistry() {
+ return healthCheckRegistry;
+ }
+
+ @PostConstruct
+ public void init() {
+ log.debug("Registering JVM gauges");
+ metricRegistry.register(PROP_METRIC_REG_JVM_MEMORY, new MemoryUsageGaugeSet());
+ metricRegistry.register(PROP_METRIC_REG_JVM_GARBAGE, new GarbageCollectorMetricSet());
+ metricRegistry.register(PROP_METRIC_REG_JVM_THREADS, new ThreadStatesGaugeSet());
+ metricRegistry.register(PROP_METRIC_REG_JVM_FILES, new FileDescriptorRatioGauge());
+ metricRegistry.register(PROP_METRIC_REG_JVM_BUFFERS, new BufferPoolMetricSet(ManagementFactory.getPlatformMBeanServer()));
+ if (hikariDataSource != null) {
+ log.debug("Monitoring the datasource");
+ hikariDataSource.setMetricRegistry(metricRegistry);
+ }
+ if (jHipsterProperties.getMetrics().getJmx().isEnabled()) {
+ log.debug("Initializing Metrics JMX reporting");
+ JmxReporter jmxReporter = JmxReporter.forRegistry(metricRegistry).build();
+ jmxReporter.start();
+ }
+ if (jHipsterProperties.getMetrics().getLogs().isEnabled()) {
+ log.info("Initializing Metrics Log reporting");
+ final Slf4jReporter reporter = Slf4jReporter.forRegistry(metricRegistry)
+ .outputTo(LoggerFactory.getLogger("metrics"))
+ .convertRatesTo(TimeUnit.SECONDS)
+ .convertDurationsTo(TimeUnit.MILLISECONDS)
+ .build();
+ reporter.start(jHipsterProperties.getMetrics().getLogs().getReportFrequency(), TimeUnit.SECONDS);
+ }
+ }
+
+ /* Spectator metrics log reporting */
+ @Bean
+ @ConditionalOnProperty("jhipster.logging.spectator-metrics.enabled")
+ @ExportMetricReader
+ public SpectatorMetricReader SpectatorMetricReader(Registry registry) {
+ log.info("Initializing Spectator Metrics Log reporting");
+ return new SpectatorMetricReader(registry);
+ }
+
+ @Bean
+ @ConditionalOnProperty("jhipster.logging.spectator-metrics.enabled")
+ @ExportMetricWriter
+ MetricWriter metricWriter() {
+ return new SpectatorLogMetricWriter();
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/SecurityConfiguration.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/SecurityConfiguration.java
new file mode 100644
index 0000000000..73963b5b52
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/SecurityConfiguration.java
@@ -0,0 +1,127 @@
+package com.gateway.config;
+
+import com.gateway.security.*;
+import com.gateway.security.jwt.*;
+
+import io.github.jhipster.security.*;
+
+import org.springframework.beans.factory.BeanInitializationException;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.data.repository.query.SecurityEvaluationContextExtension;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.web.filter.CorsFilter;
+
+import javax.annotation.PostConstruct;
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
+public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
+
+ private final AuthenticationManagerBuilder authenticationManagerBuilder;
+
+ private final UserDetailsService userDetailsService;
+
+ private final TokenProvider tokenProvider;
+
+ private final CorsFilter corsFilter;
+
+ public SecurityConfiguration(AuthenticationManagerBuilder authenticationManagerBuilder, UserDetailsService userDetailsService,
+ TokenProvider tokenProvider,
+ CorsFilter corsFilter) {
+
+ this.authenticationManagerBuilder = authenticationManagerBuilder;
+ this.userDetailsService = userDetailsService;
+ this.tokenProvider = tokenProvider;
+ this.corsFilter = corsFilter;
+ }
+
+ @PostConstruct
+ public void init() {
+ try {
+ authenticationManagerBuilder
+ .userDetailsService(userDetailsService)
+ .passwordEncoder(passwordEncoder());
+ } catch (Exception e) {
+ throw new BeanInitializationException("Security configuration failed", e);
+ }
+ }
+
+ @Bean
+ public Http401UnauthorizedEntryPoint http401UnauthorizedEntryPoint() {
+ return new Http401UnauthorizedEntryPoint();
+ }
+
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
+
+ @Override
+ public void configure(WebSecurity web) throws Exception {
+ web.ignoring()
+ .antMatchers(HttpMethod.OPTIONS, "/**")
+ .antMatchers("/app/**/*.{js,html}")
+ .antMatchers("/bower_components/**")
+ .antMatchers("/i18n/**")
+ .antMatchers("/content/**")
+ .antMatchers("/swagger-ui/index.html")
+ .antMatchers("/test/**")
+ .antMatchers("/h2-console/**");
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http
+ .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
+ .exceptionHandling()
+ .authenticationEntryPoint(http401UnauthorizedEntryPoint())
+ .and()
+ .csrf()
+ .disable()
+ .headers()
+ .frameOptions()
+ .disable()
+ .and()
+ .sessionManagement()
+ .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ .and()
+ .authorizeRequests()
+ .antMatchers("/api/register").permitAll()
+ .antMatchers("/api/activate").permitAll()
+ .antMatchers("/api/authenticate").permitAll()
+ .antMatchers("/api/account/reset_password/init").permitAll()
+ .antMatchers("/api/account/reset_password/finish").permitAll()
+ .antMatchers("/api/profile-info").permitAll()
+ .antMatchers("/api/**").authenticated()
+ .antMatchers("/management/health").permitAll()
+ .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
+ .antMatchers("/v2/api-docs/**").permitAll()
+ .antMatchers("/swagger-resources/configuration/ui").permitAll()
+ .antMatchers("/swagger-ui/index.html").hasAuthority(AuthoritiesConstants.ADMIN)
+ .and()
+ .apply(securityConfigurerAdapter());
+
+ }
+
+ private JWTConfigurer securityConfigurerAdapter() {
+ return new JWTConfigurer(tokenProvider);
+ }
+
+ @Bean
+ public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
+ return new SecurityEvaluationContextExtension();
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/ThymeleafConfiguration.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/ThymeleafConfiguration.java
new file mode 100644
index 0000000000..a39a0363c8
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/ThymeleafConfiguration.java
@@ -0,0 +1,26 @@
+package com.gateway.config;
+
+import org.apache.commons.lang3.CharEncoding;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.*;
+import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
+
+@Configuration
+public class ThymeleafConfiguration {
+
+ @SuppressWarnings("unused")
+ private final Logger log = LoggerFactory.getLogger(ThymeleafConfiguration.class);
+
+ @Bean
+ @Description("Thymeleaf template resolver serving HTML 5 emails")
+ public ClassLoaderTemplateResolver emailTemplateResolver() {
+ ClassLoaderTemplateResolver emailTemplateResolver = new ClassLoaderTemplateResolver();
+ emailTemplateResolver.setPrefix("mails/");
+ emailTemplateResolver.setSuffix(".html");
+ emailTemplateResolver.setTemplateMode("HTML5");
+ emailTemplateResolver.setCharacterEncoding(CharEncoding.UTF_8);
+ emailTemplateResolver.setOrder(1);
+ return emailTemplateResolver;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/WebConfigurer.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/WebConfigurer.java
new file mode 100644
index 0000000000..1b780a8caf
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/WebConfigurer.java
@@ -0,0 +1,195 @@
+package com.gateway.config;
+
+import io.github.jhipster.config.JHipsterConstants;
+import io.github.jhipster.config.JHipsterProperties;
+import io.github.jhipster.web.filter.CachingHttpHeadersFilter;
+
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.servlet.InstrumentedFilter;
+import com.codahale.metrics.servlets.MetricsServlet;
+import com.hazelcast.core.HazelcastInstance;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.embedded.*;
+import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory;
+import io.undertow.UndertowOptions;
+import org.springframework.boot.web.servlet.ServletContextInitializer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+import java.io.File;
+import java.nio.file.Paths;
+import java.util.*;
+import javax.servlet.*;
+
+/**
+ * Configuration of web application with Servlet 3.0 APIs.
+ */
+@Configuration
+public class WebConfigurer implements ServletContextInitializer, EmbeddedServletContainerCustomizer {
+
+ private final Logger log = LoggerFactory.getLogger(WebConfigurer.class);
+
+ private final Environment env;
+
+ private final JHipsterProperties jHipsterProperties;
+
+ private final HazelcastInstance hazelcastInstance;
+
+ private MetricRegistry metricRegistry;
+
+ public WebConfigurer(Environment env, JHipsterProperties jHipsterProperties, HazelcastInstance hazelcastInstance) {
+
+ this.env = env;
+ this.jHipsterProperties = jHipsterProperties;
+ this.hazelcastInstance = hazelcastInstance;
+ }
+
+ @Override
+ public void onStartup(ServletContext servletContext) throws ServletException {
+ if (env.getActiveProfiles().length != 0) {
+ log.info("Web application configuration, using profiles: {}", (Object[]) env.getActiveProfiles());
+ }
+ EnumSet disps = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.ASYNC);
+ initMetrics(servletContext, disps);
+ if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_PRODUCTION)) {
+ initCachingHttpHeadersFilter(servletContext, disps);
+ }
+ if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
+ initH2Console(servletContext);
+ }
+ log.info("Web application fully configured");
+ }
+
+ /**
+ * Customize the Servlet engine: Mime types, the document root, the cache.
+ */
+ @Override
+ public void customize(ConfigurableEmbeddedServletContainer container) {
+ MimeMappings mappings = new MimeMappings(MimeMappings.DEFAULT);
+ // IE issue, see https://github.com/jhipster/generator-jhipster/pull/711
+ mappings.add("html", "text/html;charset=utf-8");
+ // CloudFoundry issue, see https://github.com/cloudfoundry/gorouter/issues/64
+ mappings.add("json", "text/html;charset=utf-8");
+ container.setMimeMappings(mappings);
+ // When running in an IDE or with ./mvnw spring-boot:run, set location of the static web assets.
+ setLocationForStaticAssets(container);
+
+ /*
+ * Enable HTTP/2 for Undertow - https://twitter.com/ankinson/status/829256167700492288
+ * HTTP/2 requires HTTPS, so HTTP requests will fallback to HTTP/1.1.
+ * See the JHipsterProperties class and your application-*.yml configuration files
+ * for more information.
+ */
+ if (jHipsterProperties.getHttp().getVersion().equals(JHipsterProperties.Http.Version.V_2_0) &&
+ container instanceof UndertowEmbeddedServletContainerFactory) {
+
+ ((UndertowEmbeddedServletContainerFactory) container)
+ .addBuilderCustomizers(builder ->
+ builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true));
+ }
+ }
+
+ private void setLocationForStaticAssets(ConfigurableEmbeddedServletContainer container) {
+ File root;
+ String prefixPath = resolvePathPrefix();
+ if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_PRODUCTION)) {
+ root = new File(prefixPath + "target/www/");
+ } else {
+ root = new File(prefixPath + "src/main/webapp/");
+ }
+ if (root.exists() && root.isDirectory()) {
+ container.setDocumentRoot(root);
+ }
+ }
+
+ /**
+ * Resolve path prefix to static resources.
+ */
+ private String resolvePathPrefix() {
+ String fullExecutablePath = this.getClass().getResource("").getPath();
+ String rootPath = Paths.get(".").toUri().normalize().getPath();
+ String extractedPath = fullExecutablePath.replace(rootPath, "");
+ int extractionEndIndex = extractedPath.indexOf("target/");
+ if(extractionEndIndex <= 0) {
+ return "";
+ }
+ return extractedPath.substring(0, extractionEndIndex);
+ }
+
+ /**
+ * Initializes the caching HTTP Headers Filter.
+ */
+ private void initCachingHttpHeadersFilter(ServletContext servletContext,
+ EnumSet disps) {
+ log.debug("Registering Caching HTTP Headers Filter");
+ FilterRegistration.Dynamic cachingHttpHeadersFilter =
+ servletContext.addFilter("cachingHttpHeadersFilter",
+ new CachingHttpHeadersFilter(jHipsterProperties));
+
+ cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/content/*");
+ cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/app/*");
+ cachingHttpHeadersFilter.setAsyncSupported(true);
+ }
+
+ /**
+ * Initializes Metrics.
+ */
+ private void initMetrics(ServletContext servletContext, EnumSet disps) {
+ log.debug("Initializing Metrics registries");
+ servletContext.setAttribute(InstrumentedFilter.REGISTRY_ATTRIBUTE,
+ metricRegistry);
+ servletContext.setAttribute(MetricsServlet.METRICS_REGISTRY,
+ metricRegistry);
+
+ log.debug("Registering Metrics Filter");
+ FilterRegistration.Dynamic metricsFilter = servletContext.addFilter("webappMetricsFilter",
+ new InstrumentedFilter());
+
+ metricsFilter.addMappingForUrlPatterns(disps, true, "/*");
+ metricsFilter.setAsyncSupported(true);
+
+ log.debug("Registering Metrics Servlet");
+ ServletRegistration.Dynamic metricsAdminServlet =
+ servletContext.addServlet("metricsServlet", new MetricsServlet());
+
+ metricsAdminServlet.addMapping("/management/metrics/*");
+ metricsAdminServlet.setAsyncSupported(true);
+ metricsAdminServlet.setLoadOnStartup(2);
+ }
+
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ CorsConfiguration config = jHipsterProperties.getCors();
+ if (config.getAllowedOrigins() != null && !config.getAllowedOrigins().isEmpty()) {
+ log.debug("Registering CORS filter");
+ source.registerCorsConfiguration("/api/**", config);
+ source.registerCorsConfiguration("/v2/api-docs", config);
+ source.registerCorsConfiguration("/*/api/**", config);
+ }
+ return new CorsFilter(source);
+ }
+
+ /**
+ * Initializes H2 console.
+ */
+ private void initH2Console(ServletContext servletContext) {
+ log.debug("Initialize H2 console");
+ ServletRegistration.Dynamic h2ConsoleServlet = servletContext.addServlet("H2Console", new org.h2.server.web.WebServlet());
+ h2ConsoleServlet.addMapping("/h2-console/*");
+ h2ConsoleServlet.setInitParameter("-properties", "src/main/resources/");
+ h2ConsoleServlet.setLoadOnStartup(1);
+ }
+
+ @Autowired(required = false)
+ public void setMetricRegistry(MetricRegistry metricRegistry) {
+ this.metricRegistry = metricRegistry;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/apidoc/GatewaySwaggerResourcesProvider.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/apidoc/GatewaySwaggerResourcesProvider.java
new file mode 100644
index 0000000000..1ef6c7e00b
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/apidoc/GatewaySwaggerResourcesProvider.java
@@ -0,0 +1,63 @@
+package com.gateway.config.apidoc;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import io.github.jhipster.config.JHipsterConstants;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.*;
+import org.springframework.cloud.client.discovery.DiscoveryClient;
+import org.springframework.cloud.netflix.zuul.filters.Route;
+import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Component;
+
+import springfox.documentation.swagger.web.SwaggerResource;
+import springfox.documentation.swagger.web.SwaggerResourcesProvider;
+
+/**
+ * Retrieves all registered microservices Swagger resources.
+ */
+@Component
+@Primary
+@Profile(JHipsterConstants.SPRING_PROFILE_SWAGGER)
+public class GatewaySwaggerResourcesProvider implements SwaggerResourcesProvider {
+
+ private final Logger log = LoggerFactory.getLogger(GatewaySwaggerResourcesProvider.class);
+
+ private final RouteLocator routeLocator;
+
+ private final DiscoveryClient discoveryClient;
+
+ public GatewaySwaggerResourcesProvider(RouteLocator routeLocator, DiscoveryClient discoveryClient) {
+ this.routeLocator = routeLocator;
+ this.discoveryClient = discoveryClient;
+ }
+
+ @Override
+ public List get() {
+ List resources = new ArrayList<>();
+
+ //Add the default swagger resource that correspond to the gateway's own swagger doc
+ resources.add(swaggerResource("default", "/v2/api-docs"));
+
+ //Add the registered microservices swagger docs as additional swagger resources
+ List routes = routeLocator.getRoutes();
+ routes.forEach(route -> {
+ resources.add(swaggerResource(route.getId(), route.getFullPath().replace("**", "v2/api-docs")));
+ });
+
+ return resources;
+ }
+
+ private SwaggerResource swaggerResource(String name, String location) {
+ SwaggerResource swaggerResource = new SwaggerResource();
+ swaggerResource.setName(name);
+ swaggerResource.setLocation(location);
+ swaggerResource.setSwaggerVersion("2.0");
+ return swaggerResource;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/audit/AuditEventConverter.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/audit/AuditEventConverter.java
new file mode 100644
index 0000000000..60189a42b4
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/audit/AuditEventConverter.java
@@ -0,0 +1,91 @@
+package com.gateway.config.audit;
+
+import com.gateway.domain.PersistentAuditEvent;
+
+import org.springframework.boot.actuate.audit.AuditEvent;
+import org.springframework.security.web.authentication.WebAuthenticationDetails;
+import org.springframework.stereotype.Component;
+
+import java.time.Instant;
+import java.time.ZoneId;
+import java.util.*;
+
+@Component
+public class AuditEventConverter {
+
+ /**
+ * Convert a list of PersistentAuditEvent to a list of AuditEvent
+ *
+ * @param persistentAuditEvents the list to convert
+ * @return the converted list.
+ */
+ public List convertToAuditEvent(Iterable persistentAuditEvents) {
+ if (persistentAuditEvents == null) {
+ return Collections.emptyList();
+ }
+ List auditEvents = new ArrayList<>();
+ for (PersistentAuditEvent persistentAuditEvent : persistentAuditEvents) {
+ auditEvents.add(convertToAuditEvent(persistentAuditEvent));
+ }
+ return auditEvents;
+ }
+
+ /**
+ * Convert a PersistentAuditEvent to an AuditEvent
+ *
+ * @param persistentAuditEvent the event to convert
+ * @return the converted list.
+ */
+ public AuditEvent convertToAuditEvent(PersistentAuditEvent persistentAuditEvent) {
+ Instant instant = persistentAuditEvent.getAuditEventDate().atZone(ZoneId.systemDefault()).toInstant();
+ return new AuditEvent(Date.from(instant), persistentAuditEvent.getPrincipal(),
+ persistentAuditEvent.getAuditEventType(), convertDataToObjects(persistentAuditEvent.getData()));
+ }
+
+ /**
+ * Internal conversion. This is needed to support the current SpringBoot actuator AuditEventRepository interface
+ *
+ * @param data the data to convert
+ * @return a map of String, Object
+ */
+ public Map convertDataToObjects(Map data) {
+ Map results = new HashMap<>();
+
+ if (data != null) {
+ for (Map.Entry entry : data.entrySet()) {
+ results.put(entry.getKey(), entry.getValue());
+ }
+ }
+ return results;
+ }
+
+ /**
+ * Internal conversion. This method will allow to save additional data.
+ * By default, it will save the object as string
+ *
+ * @param data the data to convert
+ * @return a map of String, String
+ */
+ public Map convertDataToStrings(Map data) {
+ Map results = new HashMap<>();
+
+ if (data != null) {
+ for (Map.Entry entry : data.entrySet()) {
+ Object object = entry.getValue();
+
+ // Extract the data that will be saved.
+ if (object instanceof WebAuthenticationDetails) {
+ WebAuthenticationDetails authenticationDetails = (WebAuthenticationDetails) object;
+ results.put("remoteAddress", authenticationDetails.getRemoteAddress());
+ results.put("sessionId", authenticationDetails.getSessionId());
+ } else if (object != null) {
+ results.put(entry.getKey(), object.toString());
+ } else {
+ results.put(entry.getKey(), "null");
+ }
+ }
+ }
+
+ return results;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/audit/package-info.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/audit/package-info.java
new file mode 100644
index 0000000000..91e4a657bf
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/audit/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Audit specific code.
+ */
+package com.gateway.config.audit;
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/cassandra/CassandraConfiguration.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/cassandra/CassandraConfiguration.java
new file mode 100644
index 0000000000..b528d8b96b
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/cassandra/CassandraConfiguration.java
@@ -0,0 +1,122 @@
+package com.gateway.config.cassandra;
+
+import io.github.jhipster.config.JHipsterConstants;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.cassandra.CassandraProperties;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.util.StringUtils;
+
+import com.codahale.metrics.MetricRegistry;
+import com.datastax.driver.core.Cluster;
+import com.datastax.driver.core.ProtocolVersion;
+import com.datastax.driver.core.QueryOptions;
+import com.datastax.driver.core.Session;
+import com.datastax.driver.core.SocketOptions;
+import com.datastax.driver.core.policies.LoadBalancingPolicy;
+import com.datastax.driver.core.policies.ReconnectionPolicy;
+import com.datastax.driver.core.policies.RetryPolicy;
+import com.datastax.driver.extras.codecs.jdk8.LocalDateCodec;
+
+@Configuration
+@ConditionalOnProperty("jhipster.gateway.rate-limiting.enabled")
+@EnableConfigurationProperties(CassandraProperties.class)
+@Profile({JHipsterConstants.SPRING_PROFILE_DEVELOPMENT, JHipsterConstants.SPRING_PROFILE_PRODUCTION})
+public class CassandraConfiguration {
+
+ @Value("${spring.data.cassandra.protocolVersion:V4}")
+ private ProtocolVersion protocolVersion;
+
+ @Autowired(required = false)
+ MetricRegistry metricRegistry;
+
+ private final Logger log = LoggerFactory.getLogger(CassandraConfiguration.class);
+
+ @Bean
+ public Cluster cluster(CassandraProperties properties) {
+ Cluster.Builder builder = Cluster.builder()
+ .withClusterName(properties.getClusterName())
+ .withProtocolVersion(protocolVersion)
+ .withPort(getPort(properties));
+
+ if (properties.getUsername() != null) {
+ builder.withCredentials(properties.getUsername(), properties.getPassword());
+ }
+ if (properties.getCompression() != null) {
+ builder.withCompression(properties.getCompression());
+ }
+ if (properties.getLoadBalancingPolicy() != null) {
+ LoadBalancingPolicy policy = instantiate(properties.getLoadBalancingPolicy());
+ builder.withLoadBalancingPolicy(policy);
+ }
+ builder.withQueryOptions(getQueryOptions(properties));
+ if (properties.getReconnectionPolicy() != null) {
+ ReconnectionPolicy policy = instantiate(properties.getReconnectionPolicy());
+ builder.withReconnectionPolicy(policy);
+ }
+ if (properties.getRetryPolicy() != null) {
+ RetryPolicy policy = instantiate(properties.getRetryPolicy());
+ builder.withRetryPolicy(policy);
+ }
+ builder.withSocketOptions(getSocketOptions(properties));
+ if (properties.isSsl()) {
+ builder.withSSL();
+ }
+ String points = properties.getContactPoints();
+ builder.addContactPoints(StringUtils.commaDelimitedListToStringArray(points));
+
+ Cluster cluster = builder.build();
+
+ cluster.getConfiguration().getCodecRegistry()
+ .register(LocalDateCodec.instance)
+ .register(CustomZonedDateTimeCodec.instance);
+
+ if (metricRegistry != null) {
+ cluster.init();
+ metricRegistry.registerAll(cluster.getMetrics().getRegistry());
+ }
+
+ return cluster;
+ }
+
+ protected int getPort(CassandraProperties properties) {
+ return properties.getPort();
+ }
+
+ public static T instantiate(Class type) {
+ return BeanUtils.instantiate(type);
+ }
+
+ private QueryOptions getQueryOptions(CassandraProperties properties) {
+ QueryOptions options = new QueryOptions();
+ if (properties.getConsistencyLevel() != null) {
+ options.setConsistencyLevel(properties.getConsistencyLevel());
+ }
+ if (properties.getSerialConsistencyLevel() != null) {
+ options.setSerialConsistencyLevel(properties.getSerialConsistencyLevel());
+ }
+ options.setFetchSize(properties.getFetchSize());
+ return options;
+ }
+
+ private SocketOptions getSocketOptions(CassandraProperties properties) {
+ SocketOptions options = new SocketOptions();
+ options.setConnectTimeoutMillis(properties.getConnectTimeoutMillis());
+ options.setReadTimeoutMillis(properties.getReadTimeoutMillis());
+ return options;
+ }
+
+ @Bean(destroyMethod = "close")
+ public Session session(CassandraProperties properties, Cluster cluster) {
+ log.debug("Configuring Cassandra session");
+ return StringUtils.hasText(properties.getKeyspaceName()) ? cluster.connect(properties.getKeyspaceName()) : cluster.connect();
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/cassandra/CustomZonedDateTimeCodec.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/cassandra/CustomZonedDateTimeCodec.java
new file mode 100644
index 0000000000..5cdab7ac5b
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/cassandra/CustomZonedDateTimeCodec.java
@@ -0,0 +1,93 @@
+package com.gateway.config.cassandra;
+
+import com.datastax.driver.core.*;
+import com.datastax.driver.core.exceptions.InvalidTypeException;
+
+import java.nio.ByteBuffer;
+import java.time.Instant;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.DateTimeParseException;
+
+import static com.datastax.driver.core.ParseUtils.isLongLiteral;
+import static com.datastax.driver.core.ParseUtils.quote;
+import static java.time.temporal.ChronoField.*;
+
+public class CustomZonedDateTimeCodec extends TypeCodec {
+
+ public static final CustomZonedDateTimeCodec instance = new CustomZonedDateTimeCodec();
+
+ private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder()
+ .parseCaseSensitive()
+ .parseStrict()
+ .append(DateTimeFormatter.ISO_LOCAL_DATE)
+ .optionalStart()
+ .appendLiteral('T')
+ .appendValue(HOUR_OF_DAY, 2)
+ .appendLiteral(':')
+ .appendValue(MINUTE_OF_HOUR, 2)
+ .optionalEnd()
+ .optionalStart()
+ .appendLiteral(':')
+ .appendValue(SECOND_OF_MINUTE, 2)
+ .optionalEnd()
+ .optionalStart()
+ .appendFraction(NANO_OF_SECOND, 0, 9, true)
+ .optionalEnd()
+ .optionalStart()
+ .appendZoneOrOffsetId()
+ .optionalEnd()
+ .toFormatter()
+ .withZone(ZoneOffset.UTC);
+
+ private CustomZonedDateTimeCodec() {
+ super(DataType.timestamp(), ZonedDateTime.class);
+ }
+
+ @Override
+ public ByteBuffer serialize(ZonedDateTime value, ProtocolVersion protocolVersion) {
+ if (value == null) {
+ return null;
+ }
+ long millis = value.toInstant().toEpochMilli();
+ return bigint().serializeNoBoxing(millis, protocolVersion);
+ }
+
+ @Override
+ public ZonedDateTime deserialize(ByteBuffer bytes, ProtocolVersion protocolVersion) {
+ if (bytes == null || bytes.remaining() == 0) {
+ return null;
+ }
+ long millis = bigint().deserializeNoBoxing(bytes, protocolVersion);
+ return Instant.ofEpochMilli(millis).atZone(ZoneOffset.UTC);
+ }
+
+ @Override
+ public String format(ZonedDateTime value) {
+ return quote(FORMATTER.format(value));
+ }
+
+ @Override
+ public ZonedDateTime parse(String value) {
+ // strip enclosing single quotes, if any
+ if (ParseUtils.isQuoted(value)) {
+ value = ParseUtils.unquote(value);
+ }
+ if (isLongLiteral(value)) {
+ try {
+ long millis = Long.parseLong(value);
+ return ZonedDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneOffset.UTC);
+ } catch (NumberFormatException e) {
+ throw new InvalidTypeException(String.format("Cannot parse timestamp value from \"%s\"", value));
+ }
+ }
+ try {
+ return ZonedDateTime.from(FORMATTER.parse(value));
+ } catch (DateTimeParseException e) {
+ throw new InvalidTypeException(String.format("Cannot parse timestamp value from \"%s\"", value));
+ }
+ }
+
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/cassandra/package-info.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/cassandra/package-info.java
new file mode 100644
index 0000000000..a77f49c447
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/cassandra/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Cassandra specific configuration.
+ */
+package com.gateway.config.cassandra;
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/package-info.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/package-info.java
new file mode 100644
index 0000000000..00f6440bfb
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/config/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Spring Framework configuration files.
+ */
+package com.gateway.config;
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/domain/AbstractAuditingEntity.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/domain/AbstractAuditingEntity.java
new file mode 100644
index 0000000000..1c270ab70e
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/domain/AbstractAuditingEntity.java
@@ -0,0 +1,80 @@
+package com.gateway.domain;
+
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import org.hibernate.envers.Audited;
+import org.springframework.data.annotation.CreatedBy;
+import org.springframework.data.annotation.CreatedDate;
+import org.springframework.data.annotation.LastModifiedBy;
+import org.springframework.data.annotation.LastModifiedDate;
+
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+import java.time.ZonedDateTime;
+import javax.persistence.Column;
+import javax.persistence.EntityListeners;
+import javax.persistence.MappedSuperclass;
+
+/**
+ * Base abstract class for entities which will hold definitions for created, last modified by and created,
+ * last modified by date.
+ */
+@MappedSuperclass
+@Audited
+@EntityListeners(AuditingEntityListener.class)
+public abstract class AbstractAuditingEntity implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @CreatedBy
+ @Column(name = "created_by", nullable = false, length = 50, updatable = false)
+ @JsonIgnore
+ private String createdBy;
+
+ @CreatedDate
+ @Column(name = "created_date", nullable = false)
+ @JsonIgnore
+ private ZonedDateTime createdDate = ZonedDateTime.now();
+
+ @LastModifiedBy
+ @Column(name = "last_modified_by", length = 50)
+ @JsonIgnore
+ private String lastModifiedBy;
+
+ @LastModifiedDate
+ @Column(name = "last_modified_date")
+ @JsonIgnore
+ private ZonedDateTime lastModifiedDate = ZonedDateTime.now();
+
+ public String getCreatedBy() {
+ return createdBy;
+ }
+
+ public void setCreatedBy(String createdBy) {
+ this.createdBy = createdBy;
+ }
+
+ public ZonedDateTime getCreatedDate() {
+ return createdDate;
+ }
+
+ public void setCreatedDate(ZonedDateTime createdDate) {
+ this.createdDate = createdDate;
+ }
+
+ public String getLastModifiedBy() {
+ return lastModifiedBy;
+ }
+
+ public void setLastModifiedBy(String lastModifiedBy) {
+ this.lastModifiedBy = lastModifiedBy;
+ }
+
+ public ZonedDateTime getLastModifiedDate() {
+ return lastModifiedDate;
+ }
+
+ public void setLastModifiedDate(ZonedDateTime lastModifiedDate) {
+ this.lastModifiedDate = lastModifiedDate;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/domain/Authority.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/domain/Authority.java
new file mode 100644
index 0000000000..ede3ced0d2
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/domain/Authority.java
@@ -0,0 +1,66 @@
+package com.gateway.domain;
+
+import org.hibernate.annotations.Cache;
+import org.hibernate.annotations.CacheConcurrencyStrategy;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Column;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.io.Serializable;
+
+/**
+ * An authority (a security role) used by Spring Security.
+ */
+@Entity
+@Table(name = "jhi_authority")
+@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
+public class Authority implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @NotNull
+ @Size(min = 0, max = 50)
+ @Id
+ @Column(length = 50)
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Authority authority = (Authority) o;
+
+ if (name != null ? !name.equals(authority.name) : authority.name != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return name != null ? name.hashCode() : 0;
+ }
+
+ @Override
+ public String toString() {
+ return "Authority{" +
+ "name='" + name + '\'' +
+ "}";
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/domain/PersistentAuditEvent.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/domain/PersistentAuditEvent.java
new file mode 100644
index 0000000000..4bc123af1e
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/domain/PersistentAuditEvent.java
@@ -0,0 +1,78 @@
+package com.gateway.domain;
+
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import javax.persistence.*;
+import javax.validation.constraints.NotNull;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Persist AuditEvent managed by the Spring Boot actuator
+ * @see org.springframework.boot.actuate.audit.AuditEvent
+ */
+@Entity
+@Table(name = "jhi_persistent_audit_event")
+public class PersistentAuditEvent implements Serializable {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "event_id")
+ private Long id;
+
+ @NotNull
+ @Column(nullable = false)
+ private String principal;
+
+ @Column(name = "event_date")
+ private LocalDateTime auditEventDate;
+ @Column(name = "event_type")
+ private String auditEventType;
+
+ @ElementCollection
+ @MapKeyColumn(name = "name")
+ @Column(name = "value")
+ @CollectionTable(name = "jhi_persistent_audit_evt_data", joinColumns=@JoinColumn(name="event_id"))
+ private Map data = new HashMap<>();
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getPrincipal() {
+ return principal;
+ }
+
+ public void setPrincipal(String principal) {
+ this.principal = principal;
+ }
+
+ public LocalDateTime getAuditEventDate() {
+ return auditEventDate;
+ }
+
+ public void setAuditEventDate(LocalDateTime auditEventDate) {
+ this.auditEventDate = auditEventDate;
+ }
+
+ public String getAuditEventType() {
+ return auditEventType;
+ }
+
+ public void setAuditEventType(String auditEventType) {
+ this.auditEventType = auditEventType;
+ }
+
+ public Map getData() {
+ return data;
+ }
+
+ public void setData(Map data) {
+ this.data = data;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/domain/User.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/domain/User.java
new file mode 100644
index 0000000000..1dfab5f93c
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/domain/User.java
@@ -0,0 +1,235 @@
+package com.gateway.domain;
+
+import com.gateway.config.Constants;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import org.hibernate.annotations.BatchSize;
+import org.hibernate.annotations.Cache;
+import org.hibernate.annotations.CacheConcurrencyStrategy;
+import org.hibernate.validator.constraints.Email;
+
+import javax.persistence.*;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+import java.time.ZonedDateTime;
+
+/**
+ * A user.
+ */
+@Entity
+@Table(name = "jhi_user")
+@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
+public class User extends AbstractAuditingEntity implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @NotNull
+ @Pattern(regexp = Constants.LOGIN_REGEX)
+ @Size(min = 1, max = 50)
+ @Column(length = 50, unique = true, nullable = false)
+ private String login;
+
+ @JsonIgnore
+ @NotNull
+ @Size(min = 60, max = 60)
+ @Column(name = "password_hash",length = 60)
+ private String password;
+
+ @Size(max = 50)
+ @Column(name = "first_name", length = 50)
+ private String firstName;
+
+ @Size(max = 50)
+ @Column(name = "last_name", length = 50)
+ private String lastName;
+
+ @Email
+ @Size(max = 100)
+ @Column(length = 100, unique = true)
+ private String email;
+
+ @NotNull
+ @Column(nullable = false)
+ private boolean activated = false;
+
+ @Size(min = 2, max = 5)
+ @Column(name = "lang_key", length = 5)
+ private String langKey;
+
+ @Size(max = 256)
+ @Column(name = "image_url", length = 256)
+ private String imageUrl;
+
+ @Size(max = 20)
+ @Column(name = "activation_key", length = 20)
+ @JsonIgnore
+ private String activationKey;
+
+ @Size(max = 20)
+ @Column(name = "reset_key", length = 20)
+ private String resetKey;
+
+ @Column(name = "reset_date")
+ private ZonedDateTime resetDate = null;
+
+ @JsonIgnore
+ @ManyToMany
+ @JoinTable(
+ name = "jhi_user_authority",
+ joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
+ inverseJoinColumns = {@JoinColumn(name = "authority_name", referencedColumnName = "name")})
+ @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
+ @BatchSize(size = 20)
+ private Set authorities = new HashSet<>();
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getLogin() {
+ return login;
+ }
+
+ //Lowercase the login before saving it in database
+ public void setLogin(String login) {
+ this.login = login.toLowerCase(Locale.ENGLISH);
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getImageUrl() {
+ return imageUrl;
+ }
+
+ public void setImageUrl(String imageUrl) {
+ this.imageUrl = imageUrl;
+ }
+
+ public boolean getActivated() {
+ return activated;
+ }
+
+ public void setActivated(boolean activated) {
+ this.activated = activated;
+ }
+
+ public String getActivationKey() {
+ return activationKey;
+ }
+
+ public void setActivationKey(String activationKey) {
+ this.activationKey = activationKey;
+ }
+
+ public String getResetKey() {
+ return resetKey;
+ }
+
+ public void setResetKey(String resetKey) {
+ this.resetKey = resetKey;
+ }
+
+ public ZonedDateTime getResetDate() {
+ return resetDate;
+ }
+
+ public void setResetDate(ZonedDateTime resetDate) {
+ this.resetDate = resetDate;
+ }
+
+ public String getLangKey() {
+ return langKey;
+ }
+
+ public void setLangKey(String langKey) {
+ this.langKey = langKey;
+ }
+
+ public Set getAuthorities() {
+ return authorities;
+ }
+
+ public void setAuthorities(Set authorities) {
+ this.authorities = authorities;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ User user = (User) o;
+
+ if (!login.equals(user.login)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return login.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "User{" +
+ "login='" + login + '\'' +
+ ", firstName='" + firstName + '\'' +
+ ", lastName='" + lastName + '\'' +
+ ", email='" + email + '\'' +
+ ", imageUrl='" + imageUrl + '\'' +
+ ", activated='" + activated + '\'' +
+ ", langKey='" + langKey + '\'' +
+ ", activationKey='" + activationKey + '\'' +
+ "}";
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/domain/package-info.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/domain/package-info.java
new file mode 100644
index 0000000000..d56162dc07
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/domain/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * JPA domain objects.
+ */
+package com.gateway.domain;
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/gateway/TokenRelayFilter.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/gateway/TokenRelayFilter.java
new file mode 100644
index 0000000000..ae057b8b00
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/gateway/TokenRelayFilter.java
@@ -0,0 +1,36 @@
+package com.gateway.gateway;
+
+import com.netflix.zuul.ZuulFilter;
+import com.netflix.zuul.context.RequestContext;
+import org.springframework.stereotype.Component;
+
+import java.util.Set;
+
+@Component
+public class TokenRelayFilter extends ZuulFilter {
+ @Override
+ public Object run() {
+ RequestContext ctx = RequestContext.getCurrentContext();
+
+ Set headers = (Set) ctx.get("ignoredHeaders");
+ // We need our JWT tokens relayed to resource servers
+ headers.remove("authorization");
+
+ return null;
+ }
+
+ @Override
+ public boolean shouldFilter() {
+ return true;
+ }
+
+ @Override
+ public String filterType() {
+ return "pre";
+ }
+
+ @Override
+ public int filterOrder() {
+ return 10000;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/gateway/accesscontrol/AccessControlFilter.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/gateway/accesscontrol/AccessControlFilter.java
new file mode 100644
index 0000000000..b2d9800c4d
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/gateway/accesscontrol/AccessControlFilter.java
@@ -0,0 +1,100 @@
+package com.gateway.gateway.accesscontrol;
+
+import io.github.jhipster.config.JHipsterProperties;
+
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cloud.netflix.zuul.filters.Route;
+import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
+import org.springframework.http.HttpStatus;
+
+import com.netflix.zuul.ZuulFilter;
+import com.netflix.zuul.context.RequestContext;
+
+/**
+ * Zuul filter for restricting access to backend micro-services endpoints.
+ */
+public class AccessControlFilter extends ZuulFilter {
+
+ private final Logger log = LoggerFactory.getLogger(AccessControlFilter.class);
+
+ private final RouteLocator routeLocator;
+
+ private final JHipsterProperties jHipsterProperties;
+
+ public AccessControlFilter(RouteLocator routeLocator, JHipsterProperties jHipsterProperties) {
+ this.routeLocator = routeLocator;
+ this.jHipsterProperties = jHipsterProperties;
+ }
+
+ @Override
+ public String filterType() {
+ return "pre";
+ }
+
+ @Override
+ public int filterOrder() {
+ return 0;
+ }
+
+ /**
+ * Filter requests on endpoints that are not in the list of authorized microservices endpoints.
+ */
+ @Override
+ public boolean shouldFilter() {
+ String requestUri = RequestContext.getCurrentContext().getRequest().getRequestURI();
+
+ // If the request Uri does not start with the path of the authorized endpoints, we block the request
+ for (Route route : routeLocator.getRoutes()) {
+ String serviceUrl = route.getFullPath();
+ String serviceName = route.getId();
+
+ // If this route correspond to the current request URI
+ // We do a substring to remove the "**" at the end of the route URL
+ if (requestUri.startsWith(serviceUrl.substring(0, serviceUrl.length() - 2))) {
+ return !isAuthorizedRequest(serviceUrl, serviceName, requestUri);
+ }
+ }
+ return true;
+ }
+
+ private boolean isAuthorizedRequest(String serviceUrl, String serviceName, String requestUri) {
+ Map> authorizedMicroservicesEndpoints = jHipsterProperties.getGateway()
+ .getAuthorizedMicroservicesEndpoints();
+
+ // If the authorized endpoints list was left empty for this route, all access are allowed
+ if (authorizedMicroservicesEndpoints.get(serviceName) == null) {
+ log.debug("Access Control: allowing access for {}, as no access control policy has been set up for " +
+ "service: {}", requestUri, serviceName);
+ return true;
+ } else {
+ List authorizedEndpoints = authorizedMicroservicesEndpoints.get(serviceName);
+
+ // Go over the authorized endpoints to control that the request URI matches it
+ for (String endpoint : authorizedEndpoints) {
+ // We do a substring to remove the "**/" at the end of the route URL
+ String gatewayEndpoint = serviceUrl.substring(0, serviceUrl.length() - 3) + endpoint;
+ if (requestUri.startsWith(gatewayEndpoint)) {
+ log.debug("Access Control: allowing access for {}, as it matches the following authorized " +
+ "microservice endpoint: {}", requestUri, gatewayEndpoint);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Object run() {
+ RequestContext ctx = RequestContext.getCurrentContext();
+ ctx.setResponseStatusCode(HttpStatus.FORBIDDEN.value());
+ if (ctx.getResponseBody() == null && !ctx.getResponseGZipped()) {
+ ctx.setSendZuulResponse(false);
+ }
+ log.debug("Access Control: filtered unauthorized access on endpoint {}", ctx.getRequest().getRequestURI());
+ return null;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/gateway/ratelimiting/RateLimitingFilter.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/gateway/ratelimiting/RateLimitingFilter.java
new file mode 100644
index 0000000000..e065491b07
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/gateway/ratelimiting/RateLimitingFilter.java
@@ -0,0 +1,103 @@
+package com.gateway.gateway.ratelimiting;
+
+import com.gateway.security.SecurityUtils;
+
+import io.github.jhipster.config.JHipsterProperties;
+
+import java.util.Calendar;
+import java.util.Date;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+
+import com.netflix.zuul.ZuulFilter;
+import com.netflix.zuul.context.RequestContext;
+
+/**
+ * Zuul filter for limiting the number of HTTP calls per client.
+ */
+public class RateLimitingFilter extends ZuulFilter {
+
+ private final Logger log = LoggerFactory.getLogger(RateLimitingFilter.class);
+
+ private static final String TIME_PERIOD = "hour";
+
+ private long rateLimit = 100000L;
+
+ private final RateLimitingRepository rateLimitingRepository;
+
+ public RateLimitingFilter(RateLimitingRepository rateLimitingRepository, JHipsterProperties jHipsterProperties) {
+ this.rateLimitingRepository = rateLimitingRepository;
+ this.rateLimit = jHipsterProperties.getGateway().getRateLimiting().getLimit();
+ }
+
+ @Override
+ public String filterType() {
+ return "pre";
+ }
+
+ @Override
+ public int filterOrder() {
+ return 10;
+ }
+
+ @Override
+ public boolean shouldFilter() {
+ // specific APIs can be filtered out using
+ // if (RequestContext.getCurrentContext().getRequest().getRequestURI().startsWith("/api")) { ... }
+ return true;
+ }
+
+ @Override
+ public Object run() {
+ String id = getId(RequestContext.getCurrentContext().getRequest());
+ Date date = getPeriod();
+
+ // check current rate limit
+ // default limit per user is 100,000 API calls per hour
+ Long count = rateLimitingRepository.getCounter(id, TIME_PERIOD, date);
+ log.debug("Rate limiting for user {} at {} - {}", id, date, count);
+ if (count > rateLimit) {
+ apiLimitExceeded();
+ } else {
+ // count calls per hour
+ rateLimitingRepository.incrementCounter(id, TIME_PERIOD, date);
+ }
+ return null;
+ }
+
+ private void apiLimitExceeded() {
+ RequestContext ctx = RequestContext.getCurrentContext();
+ ctx.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value());
+ if (ctx.getResponseBody() == null) {
+ ctx.setResponseBody("API rate limit exceeded");
+ ctx.setSendZuulResponse(false);
+ }
+ }
+
+ /**
+ * The ID that will identify the limit: the user login or the user IP address.
+ */
+ private String getId(HttpServletRequest httpServletRequest) {
+ String login = SecurityUtils.getCurrentUserLogin();
+ if (login != null) {
+ return login;
+ } else {
+ return httpServletRequest.getRemoteAddr();
+ }
+ }
+
+ /**
+ * The period for which the rate is calculated.
+ */
+ private Date getPeriod() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.clear(Calendar.MILLISECOND);
+ calendar.clear(Calendar.SECOND);
+ calendar.clear(Calendar.MINUTE);
+ return calendar.getTime();
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/gateway/ratelimiting/RateLimitingRepository.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/gateway/ratelimiting/RateLimitingRepository.java
new file mode 100644
index 0000000000..9c710f1b46
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/gateway/ratelimiting/RateLimitingRepository.java
@@ -0,0 +1,51 @@
+package com.gateway.gateway.ratelimiting;
+
+import java.util.Date;
+
+import com.datastax.driver.core.*;
+
+/**
+ * Repository storing data used by the gateway's rate limiting filter.
+ */
+public class RateLimitingRepository {
+
+ private final Session session;
+
+ private PreparedStatement rateLimitingIncrement;
+
+ private PreparedStatement rateLimitingCount;
+
+ public RateLimitingRepository(Session session) {
+ this.session = session;
+ this.rateLimitingIncrement = session.prepare(
+ "UPDATE gateway_ratelimiting\n" +
+ " SET value = value + 1\n" +
+ " WHERE id = :id AND time_unit = :time_unit AND time = :time");
+
+ this.rateLimitingCount = session.prepare(
+ "SELECT value\n" +
+ " FROM gateway_ratelimiting\n" +
+ " WHERE id = :id AND time_unit = :time_unit AND time = :time"
+ );
+ }
+
+ public void incrementCounter(String id, String timeUnit, Date time) {
+ BoundStatement stmt = rateLimitingIncrement.bind();
+ stmt.setString("id", id);
+ stmt.setString("time_unit", timeUnit);
+ stmt.setTimestamp("time", time);
+ session.executeAsync(stmt);
+ }
+
+ public long getCounter(String id, String timeUnit, Date time) {
+ BoundStatement stmt = rateLimitingCount.bind();
+ stmt.setString("id", id);
+ stmt.setString("time_unit", timeUnit);
+ stmt.setTimestamp("time", time);
+ ResultSet rs = session.execute(stmt);
+ if (rs.isExhausted()) {
+ return 0;
+ }
+ return rs.one().getLong(0);
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/gateway/responserewriting/SwaggerBasePathRewritingFilter.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/gateway/responserewriting/SwaggerBasePathRewritingFilter.java
new file mode 100644
index 0000000000..43b1ec4f5a
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/gateway/responserewriting/SwaggerBasePathRewritingFilter.java
@@ -0,0 +1,78 @@
+package com.gateway.gateway.responserewriting;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.netflix.zuul.context.RequestContext;
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter;
+import springfox.documentation.swagger2.web.Swagger2Controller;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.LinkedHashMap;
+import java.util.zip.GZIPInputStream;
+
+/**
+ * Zuul filter to rewrite micro-services Swagger URL Base Path.
+ */
+public class SwaggerBasePathRewritingFilter extends SendResponseFilter {
+
+ private final Logger log = LoggerFactory.getLogger(SwaggerBasePathRewritingFilter.class);
+
+ private ObjectMapper mapper = new ObjectMapper();
+
+ @Override
+ public String filterType() {
+ return "post";
+ }
+
+ @Override
+ public int filterOrder() {
+ return 100;
+ }
+
+ /**
+ * Filter requests to micro-services Swagger docs.
+ */
+ @Override
+ public boolean shouldFilter() {
+ return RequestContext.getCurrentContext().getRequest().getRequestURI().endsWith(Swagger2Controller.DEFAULT_URL);
+ }
+
+ @Override
+ public Object run() {
+ RequestContext context = RequestContext.getCurrentContext();
+
+ if (!context.getResponseGZipped()) {
+ context.getResponse().setCharacterEncoding("UTF-8");
+ }
+
+ String rewrittenResponse = rewriteBasePath(context);
+ context.setResponseBody(rewrittenResponse);
+ return null;
+ }
+
+ private String rewriteBasePath(RequestContext context) {
+ InputStream responseDataStream = context.getResponseDataStream();
+ String requestUri = RequestContext.getCurrentContext().getRequest().getRequestURI();
+ try {
+ if (context.getResponseGZipped()) {
+ responseDataStream = new GZIPInputStream(context.getResponseDataStream());
+ }
+ String response = IOUtils.toString(responseDataStream, StandardCharsets.UTF_8);
+ if (response != null) {
+ LinkedHashMap map = this.mapper.readValue(response, LinkedHashMap.class);
+
+ String basePath = requestUri.replace(Swagger2Controller.DEFAULT_URL,"");
+ map.put("basePath",basePath);
+ log.debug("Swagger-docs: rewritten Base URL with correct micro-service route: {}", basePath);
+ return mapper.writeValueAsString(map);
+ }
+ } catch (IOException e) {
+ log.error("Swagger-docs filter error", e);
+ }
+ return null;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/repository/AuthorityRepository.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/repository/AuthorityRepository.java
new file mode 100644
index 0000000000..553c8913b6
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/repository/AuthorityRepository.java
@@ -0,0 +1,11 @@
+package com.gateway.repository;
+
+import com.gateway.domain.Authority;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+/**
+ * Spring Data JPA repository for the Authority entity.
+ */
+public interface AuthorityRepository extends JpaRepository {
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/repository/CustomAuditEventRepository.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/repository/CustomAuditEventRepository.java
new file mode 100644
index 0000000000..6eb893f095
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/repository/CustomAuditEventRepository.java
@@ -0,0 +1,81 @@
+package com.gateway.repository;
+
+import com.gateway.config.Constants;
+import com.gateway.config.audit.AuditEventConverter;
+import com.gateway.domain.PersistentAuditEvent;
+
+import org.springframework.boot.actuate.audit.AuditEvent;
+import org.springframework.boot.actuate.audit.AuditEventRepository;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * An implementation of Spring Boot's AuditEventRepository.
+ */
+@Repository
+public class CustomAuditEventRepository implements AuditEventRepository {
+
+ private static final String AUTHORIZATION_FAILURE = "AUTHORIZATION_FAILURE";
+
+ private final PersistenceAuditEventRepository persistenceAuditEventRepository;
+
+ private final AuditEventConverter auditEventConverter;
+
+ public CustomAuditEventRepository(PersistenceAuditEventRepository persistenceAuditEventRepository,
+ AuditEventConverter auditEventConverter) {
+
+ this.persistenceAuditEventRepository = persistenceAuditEventRepository;
+ this.auditEventConverter = auditEventConverter;
+ }
+
+ @Override
+ public List find(Date after) {
+ Iterable persistentAuditEvents =
+ persistenceAuditEventRepository.findByAuditEventDateAfter(LocalDateTime.from(after.toInstant()));
+ return auditEventConverter.convertToAuditEvent(persistentAuditEvents);
+ }
+
+ @Override
+ public List find(String principal, Date after) {
+ Iterable persistentAuditEvents;
+ if (principal == null && after == null) {
+ persistentAuditEvents = persistenceAuditEventRepository.findAll();
+ } else if (after == null) {
+ persistentAuditEvents = persistenceAuditEventRepository.findByPrincipal(principal);
+ } else {
+ persistentAuditEvents =
+ persistenceAuditEventRepository.findByPrincipalAndAuditEventDateAfter(principal, LocalDateTime.from(after.toInstant()));
+ }
+ return auditEventConverter.convertToAuditEvent(persistentAuditEvents);
+ }
+
+ @Override
+ public List find(String principal, Date after, String type) {
+ Iterable persistentAuditEvents =
+ persistenceAuditEventRepository.findByPrincipalAndAuditEventDateAfterAndAuditEventType(principal, LocalDateTime.from(after.toInstant()), type);
+ return auditEventConverter.convertToAuditEvent(persistentAuditEvents);
+ }
+
+ @Override
+ @Transactional(propagation = Propagation.REQUIRES_NEW)
+ public void add(AuditEvent event) {
+ if (!AUTHORIZATION_FAILURE.equals(event.getType()) &&
+ !Constants.ANONYMOUS_USER.equals(event.getPrincipal())) {
+
+ PersistentAuditEvent persistentAuditEvent = new PersistentAuditEvent();
+ persistentAuditEvent.setPrincipal(event.getPrincipal());
+ persistentAuditEvent.setAuditEventType(event.getType());
+ Instant instant = Instant.ofEpochMilli(event.getTimestamp().getTime());
+ persistentAuditEvent.setAuditEventDate(LocalDateTime.ofInstant(instant, ZoneId.systemDefault()));
+ persistentAuditEvent.setData(auditEventConverter.convertDataToStrings(event.getData()));
+ persistenceAuditEventRepository.save(persistentAuditEvent);
+ }
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/repository/PersistenceAuditEventRepository.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/repository/PersistenceAuditEventRepository.java
new file mode 100644
index 0000000000..7c6ba05d54
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/repository/PersistenceAuditEventRepository.java
@@ -0,0 +1,26 @@
+package com.gateway.repository;
+
+import com.gateway.domain.PersistentAuditEvent;
+
+import java.time.LocalDateTime;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
+import java.util.List;
+
+/**
+ * Spring Data JPA repository for the PersistentAuditEvent entity.
+ */
+public interface PersistenceAuditEventRepository extends JpaRepository {
+
+ List findByPrincipal(String principal);
+
+ List findByAuditEventDateAfter(LocalDateTime after);
+
+ List findByPrincipalAndAuditEventDateAfter(String principal, LocalDateTime after);
+
+ List findByPrincipalAndAuditEventDateAfterAndAuditEventType(String principle, LocalDateTime after, String type);
+
+ Page findAllByAuditEventDateBetween(LocalDateTime fromDate, LocalDateTime toDate, Pageable pageable);
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/repository/UserRepository.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/repository/UserRepository.java
new file mode 100644
index 0000000000..41b10f2ecf
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/repository/UserRepository.java
@@ -0,0 +1,37 @@
+package com.gateway.repository;
+
+import com.gateway.domain.User;
+
+import java.time.ZonedDateTime;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.EntityGraph;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Spring Data JPA repository for the User entity.
+ */
+public interface UserRepository extends JpaRepository {
+
+ Optional findOneByActivationKey(String activationKey);
+
+ List findAllByActivatedIsFalseAndCreatedDateBefore(ZonedDateTime dateTime);
+
+ Optional findOneByResetKey(String resetKey);
+
+ Optional findOneByEmail(String email);
+
+ Optional findOneByLogin(String login);
+
+ @EntityGraph(attributePaths = "authorities")
+ User findOneWithAuthoritiesById(Long id);
+
+ @EntityGraph(attributePaths = "authorities")
+ Optional findOneWithAuthoritiesByLogin(String login);
+
+ Page findAllByLoginNot(Pageable pageable, String login);
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/repository/package-info.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/repository/package-info.java
new file mode 100644
index 0000000000..f15a3e98c6
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/repository/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Spring Data JPA repositories.
+ */
+package com.gateway.repository;
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/AuthoritiesConstants.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/AuthoritiesConstants.java
new file mode 100644
index 0000000000..bdf81f928b
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/AuthoritiesConstants.java
@@ -0,0 +1,16 @@
+package com.gateway.security;
+
+/**
+ * Constants for Spring Security authorities.
+ */
+public final class AuthoritiesConstants {
+
+ public static final String ADMIN = "ROLE_ADMIN";
+
+ public static final String USER = "ROLE_USER";
+
+ public static final String ANONYMOUS = "ROLE_ANONYMOUS";
+
+ private AuthoritiesConstants() {
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/DomainUserDetailsService.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/DomainUserDetailsService.java
new file mode 100644
index 0000000000..e175d83cb9
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/DomainUserDetailsService.java
@@ -0,0 +1,51 @@
+package com.gateway.security;
+
+import com.gateway.domain.User;
+import com.gateway.repository.UserRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * Authenticate a user from the database.
+ */
+@Component("userDetailsService")
+public class DomainUserDetailsService implements UserDetailsService {
+
+ private final Logger log = LoggerFactory.getLogger(DomainUserDetailsService.class);
+
+ private final UserRepository userRepository;
+
+ public DomainUserDetailsService(UserRepository userRepository) {
+ this.userRepository = userRepository;
+ }
+
+ @Override
+ @Transactional
+ public UserDetails loadUserByUsername(final String login) {
+ log.debug("Authenticating {}", login);
+ String lowercaseLogin = login.toLowerCase(Locale.ENGLISH);
+ Optional userFromDatabase = userRepository.findOneWithAuthoritiesByLogin(lowercaseLogin);
+ return userFromDatabase.map(user -> {
+ if (!user.getActivated()) {
+ throw new UserNotActivatedException("User " + lowercaseLogin + " was not activated");
+ }
+ List grantedAuthorities = user.getAuthorities().stream()
+ .map(authority -> new SimpleGrantedAuthority(authority.getName()))
+ .collect(Collectors.toList());
+ return new org.springframework.security.core.userdetails.User(lowercaseLogin,
+ user.getPassword(),
+ grantedAuthorities);
+ }).orElseThrow(() -> new UsernameNotFoundException("User " + lowercaseLogin + " was not found in the " +
+ "database"));
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/SecurityUtils.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/SecurityUtils.java
new file mode 100644
index 0000000000..5fed368fe3
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/SecurityUtils.java
@@ -0,0 +1,68 @@
+package com.gateway.security;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+
+/**
+ * Utility class for Spring Security.
+ */
+public final class SecurityUtils {
+
+ private SecurityUtils() {
+ }
+
+ /**
+ * Get the login of the current user.
+ *
+ * @return the login of the current user
+ */
+ public static String getCurrentUserLogin() {
+ SecurityContext securityContext = SecurityContextHolder.getContext();
+ Authentication authentication = securityContext.getAuthentication();
+ String userName = null;
+ if (authentication != null) {
+ if (authentication.getPrincipal() instanceof UserDetails) {
+ UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal();
+ userName = springSecurityUser.getUsername();
+ } else if (authentication.getPrincipal() instanceof String) {
+ userName = (String) authentication.getPrincipal();
+ }
+ }
+ return userName;
+ }
+
+ /**
+ * Check if a user is authenticated.
+ *
+ * @return true if the user is authenticated, false otherwise
+ */
+ public static boolean isAuthenticated() {
+ SecurityContext securityContext = SecurityContextHolder.getContext();
+ Authentication authentication = securityContext.getAuthentication();
+ if (authentication != null) {
+ return authentication.getAuthorities().stream()
+ .noneMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(AuthoritiesConstants.ANONYMOUS));
+ }
+ return false;
+ }
+
+ /**
+ * If the current user has a specific authority (security role).
+ *
+ *
The name of this method comes from the isUserInRole() method in the Servlet API
+ *
+ * @param authority the authority to check
+ * @return true if the current user has the authority, false otherwise
+ */
+ public static boolean isCurrentUserInRole(String authority) {
+ SecurityContext securityContext = SecurityContextHolder.getContext();
+ Authentication authentication = securityContext.getAuthentication();
+ if (authentication != null) {
+ return authentication.getAuthorities().stream()
+ .anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(authority));
+ }
+ return false;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/SpringSecurityAuditorAware.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/SpringSecurityAuditorAware.java
new file mode 100644
index 0000000000..f1dd81f129
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/SpringSecurityAuditorAware.java
@@ -0,0 +1,19 @@
+package com.gateway.security;
+
+import com.gateway.config.Constants;
+
+import org.springframework.data.domain.AuditorAware;
+import org.springframework.stereotype.Component;
+
+/**
+ * Implementation of AuditorAware based on Spring Security.
+ */
+@Component
+public class SpringSecurityAuditorAware implements AuditorAware {
+
+ @Override
+ public String getCurrentAuditor() {
+ String userName = SecurityUtils.getCurrentUserLogin();
+ return userName != null ? userName : Constants.SYSTEM_ACCOUNT;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/UserNotActivatedException.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/UserNotActivatedException.java
new file mode 100644
index 0000000000..d8bd57ccfe
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/UserNotActivatedException.java
@@ -0,0 +1,19 @@
+package com.gateway.security;
+
+import org.springframework.security.core.AuthenticationException;
+
+/**
+ * This exception is thrown in case of a not activated user trying to authenticate.
+ */
+public class UserNotActivatedException extends AuthenticationException {
+
+ private static final long serialVersionUID = 1L;
+
+ public UserNotActivatedException(String message) {
+ super(message);
+ }
+
+ public UserNotActivatedException(String message, Throwable t) {
+ super(message, t);
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/jwt/JWTConfigurer.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/jwt/JWTConfigurer.java
new file mode 100644
index 0000000000..a673e98b3e
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/jwt/JWTConfigurer.java
@@ -0,0 +1,23 @@
+package com.gateway.security.jwt;
+
+import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.web.DefaultSecurityFilterChain;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+public class JWTConfigurer extends SecurityConfigurerAdapter {
+
+ public static final String AUTHORIZATION_HEADER = "Authorization";
+
+ private TokenProvider tokenProvider;
+
+ public JWTConfigurer(TokenProvider tokenProvider) {
+ this.tokenProvider = tokenProvider;
+ }
+
+ @Override
+ public void configure(HttpSecurity http) throws Exception {
+ JWTFilter customFilter = new JWTFilter(tokenProvider);
+ http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/jwt/JWTFilter.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/jwt/JWTFilter.java
new file mode 100644
index 0000000000..58462ce4a8
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/jwt/JWTFilter.java
@@ -0,0 +1,58 @@
+package com.gateway.security.jwt;
+
+import java.io.IOException;
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.util.StringUtils;
+import org.springframework.web.filter.GenericFilterBean;
+
+import io.jsonwebtoken.ExpiredJwtException;
+
+/**
+ * Filters incoming requests and installs a Spring Security principal if a header corresponding to a valid user is
+ * found.
+ */
+public class JWTFilter extends GenericFilterBean {
+
+ private final Logger log = LoggerFactory.getLogger(JWTFilter.class);
+
+ private TokenProvider tokenProvider;
+
+ public JWTFilter(TokenProvider tokenProvider) {
+ this.tokenProvider = tokenProvider;
+ }
+
+ @Override
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
+ throws IOException, ServletException {
+ try {
+ HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
+ String jwt = resolveToken(httpServletRequest);
+ if (StringUtils.hasText(jwt) && this.tokenProvider.validateToken(jwt)) {
+ Authentication authentication = this.tokenProvider.getAuthentication(jwt);
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ }
+ filterChain.doFilter(servletRequest, servletResponse);
+ } catch (ExpiredJwtException eje) {
+ log.info("Security exception for user {} - {}",
+ eje.getClaims().getSubject(), eje.getMessage());
+
+ log.trace("Security exception trace: {}", eje);
+ ((HttpServletResponse) servletResponse).setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ }
+ }
+
+ private String resolveToken(HttpServletRequest request){
+ String bearerToken = request.getHeader(JWTConfigurer.AUTHORIZATION_HEADER);
+ if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
+ return bearerToken.substring(7, bearerToken.length());
+ }
+ return null;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/jwt/TokenProvider.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/jwt/TokenProvider.java
new file mode 100644
index 0000000000..5ffb55f33e
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/jwt/TokenProvider.java
@@ -0,0 +1,109 @@
+package com.gateway.security.jwt;
+
+import io.github.jhipster.config.JHipsterProperties;
+
+import java.util.*;
+import java.util.stream.Collectors;
+import javax.annotation.PostConstruct;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.stereotype.Component;
+
+import io.jsonwebtoken.*;
+
+@Component
+public class TokenProvider {
+
+ private final Logger log = LoggerFactory.getLogger(TokenProvider.class);
+
+ private static final String AUTHORITIES_KEY = "auth";
+
+ private String secretKey;
+
+ private long tokenValidityInMilliseconds;
+
+ private long tokenValidityInMillisecondsForRememberMe;
+
+ private final JHipsterProperties jHipsterProperties;
+
+ public TokenProvider(JHipsterProperties jHipsterProperties) {
+ this.jHipsterProperties = jHipsterProperties;
+ }
+
+ @PostConstruct
+ public void init() {
+ this.secretKey =
+ jHipsterProperties.getSecurity().getAuthentication().getJwt().getSecret();
+
+ this.tokenValidityInMilliseconds =
+ 1000 * jHipsterProperties.getSecurity().getAuthentication().getJwt().getTokenValidityInSeconds();
+ this.tokenValidityInMillisecondsForRememberMe =
+ 1000 * jHipsterProperties.getSecurity().getAuthentication().getJwt().getTokenValidityInSecondsForRememberMe();
+ }
+
+ public String createToken(Authentication authentication, Boolean rememberMe) {
+ String authorities = authentication.getAuthorities().stream()
+ .map(GrantedAuthority::getAuthority)
+ .collect(Collectors.joining(","));
+
+ long now = (new Date()).getTime();
+ Date validity;
+ if (rememberMe) {
+ validity = new Date(now + this.tokenValidityInMillisecondsForRememberMe);
+ } else {
+ validity = new Date(now + this.tokenValidityInMilliseconds);
+ }
+
+ return Jwts.builder()
+ .setSubject(authentication.getName())
+ .claim(AUTHORITIES_KEY, authorities)
+ .signWith(SignatureAlgorithm.HS512, secretKey)
+ .setExpiration(validity)
+ .compact();
+ }
+
+ public Authentication getAuthentication(String token) {
+ Claims claims = Jwts.parser()
+ .setSigningKey(secretKey)
+ .parseClaimsJws(token)
+ .getBody();
+
+ Collection extends GrantedAuthority> authorities =
+ Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(","))
+ .map(SimpleGrantedAuthority::new)
+ .collect(Collectors.toList());
+
+ User principal = new User(claims.getSubject(), "", authorities);
+
+ return new UsernamePasswordAuthenticationToken(principal, "", authorities);
+ }
+
+ public boolean validateToken(String authToken) {
+ try {
+ Jwts.parser().setSigningKey(secretKey).parseClaimsJws(authToken);
+ return true;
+ } catch (SignatureException e) {
+ log.info("Invalid JWT signature.");
+ log.trace("Invalid JWT signature trace: {}", e);
+ } catch (MalformedJwtException e) {
+ log.info("Invalid JWT token.");
+ log.trace("Invalid JWT token trace: {}", e);
+ } catch (ExpiredJwtException e) {
+ log.info("Expired JWT token.");
+ log.trace("Expired JWT token trace: {}", e);
+ } catch (UnsupportedJwtException e) {
+ log.info("Unsupported JWT token.");
+ log.trace("Unsupported JWT token trace: {}", e);
+ } catch (IllegalArgumentException e) {
+ log.info("JWT token compact of handler are invalid.");
+ log.trace("JWT token compact of handler are invalid trace: {}", e);
+ }
+ return false;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/package-info.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/package-info.java
new file mode 100644
index 0000000000..d834be18bf
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/security/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Spring Security configuration.
+ */
+package com.gateway.security;
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/AuditEventService.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/AuditEventService.java
new file mode 100644
index 0000000000..64c63a7938
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/AuditEventService.java
@@ -0,0 +1,50 @@
+package com.gateway.service;
+
+import com.gateway.config.audit.AuditEventConverter;
+import com.gateway.repository.PersistenceAuditEventRepository;
+import java.time.LocalDateTime;
+import org.springframework.boot.actuate.audit.AuditEvent;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Optional;
+
+/**
+ * Service for managing audit events.
+ *
+ * This is the default implementation to support SpringBoot Actuator AuditEventRepository
+ *
+ * We use the @Async annotation to send e-mails asynchronously.
+ *
+ */
+@Service
+public class MailService {
+
+ private final Logger log = LoggerFactory.getLogger(MailService.class);
+
+ private static final String USER = "user";
+
+ private static final String BASE_URL = "baseUrl";
+
+ private final JHipsterProperties jHipsterProperties;
+
+ private final JavaMailSender javaMailSender;
+
+ private final MessageSource messageSource;
+
+ private final SpringTemplateEngine templateEngine;
+
+ public MailService(JHipsterProperties jHipsterProperties, JavaMailSender javaMailSender,
+ MessageSource messageSource, SpringTemplateEngine templateEngine) {
+
+ this.jHipsterProperties = jHipsterProperties;
+ this.javaMailSender = javaMailSender;
+ this.messageSource = messageSource;
+ this.templateEngine = templateEngine;
+ }
+
+ @Async
+ public void sendEmail(String to, String subject, String content, boolean isMultipart, boolean isHtml) {
+ log.debug("Send e-mail[multipart '{}' and html '{}'] to '{}' with subject '{}' and content={}",
+ isMultipart, isHtml, to, subject, content);
+
+ // Prepare message using a Spring helper
+ MimeMessage mimeMessage = javaMailSender.createMimeMessage();
+ try {
+ MimeMessageHelper message = new MimeMessageHelper(mimeMessage, isMultipart, CharEncoding.UTF_8);
+ message.setTo(to);
+ message.setFrom(jHipsterProperties.getMail().getFrom());
+ message.setSubject(subject);
+ message.setText(content, isHtml);
+ javaMailSender.send(mimeMessage);
+ log.debug("Sent e-mail to User '{}'", to);
+ } catch (Exception e) {
+ log.warn("E-mail could not be sent to user '{}'", to, e);
+ }
+ }
+
+ @Async
+ public void sendActivationEmail(User user) {
+ log.debug("Sending activation e-mail to '{}'", user.getEmail());
+ Locale locale = Locale.forLanguageTag(user.getLangKey());
+ Context context = new Context(locale);
+ context.setVariable(USER, user);
+ context.setVariable(BASE_URL, jHipsterProperties.getMail().getBaseUrl());
+ String content = templateEngine.process("activationEmail", context);
+ String subject = messageSource.getMessage("email.activation.title", null, locale);
+ sendEmail(user.getEmail(), subject, content, false, true);
+ }
+
+ @Async
+ public void sendCreationEmail(User user) {
+ log.debug("Sending creation e-mail to '{}'", user.getEmail());
+ Locale locale = Locale.forLanguageTag(user.getLangKey());
+ Context context = new Context(locale);
+ context.setVariable(USER, user);
+ context.setVariable(BASE_URL, jHipsterProperties.getMail().getBaseUrl());
+ String content = templateEngine.process("creationEmail", context);
+ String subject = messageSource.getMessage("email.activation.title", null, locale);
+ sendEmail(user.getEmail(), subject, content, false, true);
+ }
+
+ @Async
+ public void sendPasswordResetMail(User user) {
+ log.debug("Sending password reset e-mail to '{}'", user.getEmail());
+ Locale locale = Locale.forLanguageTag(user.getLangKey());
+ Context context = new Context(locale);
+ context.setVariable(USER, user);
+ context.setVariable(BASE_URL, jHipsterProperties.getMail().getBaseUrl());
+ String content = templateEngine.process("passwordResetEmail", context);
+ String subject = messageSource.getMessage("email.reset.title", null, locale);
+ sendEmail(user.getEmail(), subject, content, false, true);
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/UserService.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/UserService.java
new file mode 100644
index 0000000000..a95136bca4
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/UserService.java
@@ -0,0 +1,228 @@
+package com.gateway.service;
+
+import com.gateway.domain.Authority;
+import com.gateway.domain.User;
+import com.gateway.repository.AuthorityRepository;
+import com.gateway.config.Constants;
+import com.gateway.repository.UserRepository;
+import com.gateway.security.AuthoritiesConstants;
+import com.gateway.security.SecurityUtils;
+import com.gateway.service.util.RandomUtil;
+import com.gateway.service.dto.UserDTO;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.ZonedDateTime;
+import java.util.*;
+
+/**
+ * Service class for managing users.
+ */
+@Service
+@Transactional
+public class UserService {
+
+ private final Logger log = LoggerFactory.getLogger(UserService.class);
+
+ private final UserRepository userRepository;
+
+ private final PasswordEncoder passwordEncoder;
+
+ private final AuthorityRepository authorityRepository;
+
+ public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder, AuthorityRepository authorityRepository) {
+ this.userRepository = userRepository;
+ this.passwordEncoder = passwordEncoder;
+ this.authorityRepository = authorityRepository;
+ }
+
+ public Optional activateRegistration(String key) {
+ log.debug("Activating user for activation key {}", key);
+ return userRepository.findOneByActivationKey(key)
+ .map(user -> {
+ // activate given user for the registration key.
+ user.setActivated(true);
+ user.setActivationKey(null);
+ log.debug("Activated user: {}", user);
+ return user;
+ });
+ }
+
+ public Optional completePasswordReset(String newPassword, String key) {
+ log.debug("Reset user password for reset key {}", key);
+
+ return userRepository.findOneByResetKey(key)
+ .filter(user -> {
+ ZonedDateTime oneDayAgo = ZonedDateTime.now().minusHours(24);
+ return user.getResetDate().isAfter(oneDayAgo);
+ })
+ .map(user -> {
+ user.setPassword(passwordEncoder.encode(newPassword));
+ user.setResetKey(null);
+ user.setResetDate(null);
+ return user;
+ });
+ }
+
+ public Optional requestPasswordReset(String mail) {
+ return userRepository.findOneByEmail(mail)
+ .filter(User::getActivated)
+ .map(user -> {
+ user.setResetKey(RandomUtil.generateResetKey());
+ user.setResetDate(ZonedDateTime.now());
+ return user;
+ });
+ }
+
+ public User createUser(String login, String password, String firstName, String lastName, String email,
+ String imageUrl, String langKey) {
+
+ User newUser = new User();
+ Authority authority = authorityRepository.findOne(AuthoritiesConstants.USER);
+ Set authorities = new HashSet<>();
+ String encryptedPassword = passwordEncoder.encode(password);
+ newUser.setLogin(login);
+ // new user gets initially a generated password
+ newUser.setPassword(encryptedPassword);
+ newUser.setFirstName(firstName);
+ newUser.setLastName(lastName);
+ newUser.setEmail(email);
+ newUser.setImageUrl(imageUrl);
+ newUser.setLangKey(langKey);
+ // new user is not active
+ newUser.setActivated(false);
+ // new user gets registration key
+ newUser.setActivationKey(RandomUtil.generateActivationKey());
+ authorities.add(authority);
+ newUser.setAuthorities(authorities);
+ userRepository.save(newUser);
+ log.debug("Created Information for User: {}", newUser);
+ return newUser;
+ }
+
+ public User createUser(UserDTO userDTO) {
+ User user = new User();
+ user.setLogin(userDTO.getLogin());
+ user.setFirstName(userDTO.getFirstName());
+ user.setLastName(userDTO.getLastName());
+ user.setEmail(userDTO.getEmail());
+ user.setImageUrl(userDTO.getImageUrl());
+ if (userDTO.getLangKey() == null) {
+ user.setLangKey("en"); // default language
+ } else {
+ user.setLangKey(userDTO.getLangKey());
+ }
+ if (userDTO.getAuthorities() != null) {
+ Set authorities = new HashSet<>();
+ userDTO.getAuthorities().forEach(
+ authority -> authorities.add(authorityRepository.findOne(authority))
+ );
+ user.setAuthorities(authorities);
+ }
+ String encryptedPassword = passwordEncoder.encode(RandomUtil.generatePassword());
+ user.setPassword(encryptedPassword);
+ user.setResetKey(RandomUtil.generateResetKey());
+ user.setResetDate(ZonedDateTime.now());
+ user.setActivated(true);
+ userRepository.save(user);
+ log.debug("Created Information for User: {}", user);
+ return user;
+ }
+
+ /**
+ * Update basic information (first name, last name, email, language) for the current user.
+ */
+ public void updateUser(String firstName, String lastName, String email, String langKey) {
+ userRepository.findOneByLogin(SecurityUtils.getCurrentUserLogin()).ifPresent(user -> {
+ user.setFirstName(firstName);
+ user.setLastName(lastName);
+ user.setEmail(email);
+ user.setLangKey(langKey);
+ log.debug("Changed Information for User: {}", user);
+ });
+ }
+
+ /**
+ * Update all information for a specific user, and return the modified user.
+ */
+ public Optional updateUser(UserDTO userDTO) {
+ return Optional.of(userRepository
+ .findOne(userDTO.getId()))
+ .map(user -> {
+ user.setLogin(userDTO.getLogin());
+ user.setFirstName(userDTO.getFirstName());
+ user.setLastName(userDTO.getLastName());
+ user.setEmail(userDTO.getEmail());
+ user.setImageUrl(userDTO.getImageUrl());
+ user.setActivated(userDTO.isActivated());
+ user.setLangKey(userDTO.getLangKey());
+ Set managedAuthorities = user.getAuthorities();
+ managedAuthorities.clear();
+ userDTO.getAuthorities().stream()
+ .map(authorityRepository::findOne)
+ .forEach(managedAuthorities::add);
+ log.debug("Changed Information for User: {}", user);
+ return user;
+ })
+ .map(UserDTO::new);
+ }
+
+ public void deleteUser(String login) {
+ userRepository.findOneByLogin(login).ifPresent(user -> {
+ userRepository.delete(user);
+ log.debug("Deleted User: {}", user);
+ });
+ }
+
+ public void changePassword(String password) {
+ userRepository.findOneByLogin(SecurityUtils.getCurrentUserLogin()).ifPresent(user -> {
+ String encryptedPassword = passwordEncoder.encode(password);
+ user.setPassword(encryptedPassword);
+ log.debug("Changed password for User: {}", user);
+ });
+ }
+
+ @Transactional(readOnly = true)
+ public Page getAllManagedUsers(Pageable pageable) {
+ return userRepository.findAllByLoginNot(pageable, Constants.ANONYMOUS_USER).map(UserDTO::new);
+ }
+
+ @Transactional(readOnly = true)
+ public Optional getUserWithAuthoritiesByLogin(String login) {
+ return userRepository.findOneWithAuthoritiesByLogin(login);
+ }
+
+ @Transactional(readOnly = true)
+ public User getUserWithAuthorities(Long id) {
+ return userRepository.findOneWithAuthoritiesById(id);
+ }
+
+ @Transactional(readOnly = true)
+ public User getUserWithAuthorities() {
+ return userRepository.findOneWithAuthoritiesByLogin(SecurityUtils.getCurrentUserLogin()).orElse(null);
+ }
+
+
+ /**
+ * Not activated users should be automatically deleted after 3 days.
+ *
+ * This is scheduled to get fired everyday, at 01:00 (am).
+ *
+ */
+ @Scheduled(cron = "0 0 1 * * ?")
+ public void removeNotActivatedUsers() {
+ ZonedDateTime now = ZonedDateTime.now();
+ List users = userRepository.findAllByActivatedIsFalseAndCreatedDateBefore(now.minusDays(3));
+ for (User user : users) {
+ log.debug("Deleting not activated user {}", user.getLogin());
+ userRepository.delete(user);
+ }
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/dto/UserDTO.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/dto/UserDTO.java
new file mode 100644
index 0000000000..7acf62b299
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/dto/UserDTO.java
@@ -0,0 +1,167 @@
+package com.gateway.service.dto;
+
+import com.gateway.config.Constants;
+
+import com.gateway.domain.Authority;
+import com.gateway.domain.User;
+
+import org.hibernate.validator.constraints.Email;
+
+import javax.validation.constraints.*;
+import java.time.ZonedDateTime;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * A DTO representing a user, with his authorities.
+ */
+public class UserDTO {
+
+ private Long id;
+
+ @Pattern(regexp = Constants.LOGIN_REGEX)
+ @Size(min = 1, max = 50)
+ private String login;
+
+ @Size(max = 50)
+ private String firstName;
+
+ @Size(max = 50)
+ private String lastName;
+
+ @Email
+ @Size(min = 5, max = 100)
+ private String email;
+
+ @Size(max = 256)
+ private String imageUrl;
+
+ private boolean activated = false;
+
+ @Size(min = 2, max = 5)
+ private String langKey;
+
+ private String createdBy;
+
+ private ZonedDateTime createdDate;
+
+ private String lastModifiedBy;
+
+ private ZonedDateTime lastModifiedDate;
+
+ private Set authorities;
+
+ public UserDTO() {
+ // Empty constructor needed for MapStruct.
+ }
+
+ public UserDTO(User user) {
+ this(user.getId(), user.getLogin(), user.getFirstName(), user.getLastName(),
+ user.getEmail(), user.getActivated(), user.getImageUrl(), user.getLangKey(),
+ user.getCreatedBy(), user.getCreatedDate(), user.getLastModifiedBy(), user.getLastModifiedDate(),
+ user.getAuthorities().stream().map(Authority::getName)
+ .collect(Collectors.toSet()));
+ }
+
+ public UserDTO(Long id, String login, String firstName, String lastName,
+ String email, boolean activated, String imageUrl, String langKey,
+ String createdBy, ZonedDateTime createdDate, String lastModifiedBy, ZonedDateTime lastModifiedDate,
+ Set authorities) {
+
+ this.id = id;
+ this.login = login;
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.email = email;
+ this.activated = activated;
+ this.imageUrl = imageUrl;
+ this.langKey = langKey;
+ this.createdBy = createdBy;
+ this.createdDate = createdDate;
+ this.lastModifiedBy = lastModifiedBy;
+ this.lastModifiedDate = lastModifiedDate;
+ this.authorities = authorities;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getLogin() {
+ return login;
+ }
+
+ public void setLogin(String login) {
+ this.login = login;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public String getImageUrl() {
+ return imageUrl;
+ }
+
+ public boolean isActivated() {
+ return activated;
+ }
+
+ public String getLangKey() {
+ return langKey;
+ }
+
+ public String getCreatedBy() {
+ return createdBy;
+ }
+
+ public ZonedDateTime getCreatedDate() {
+ return createdDate;
+ }
+
+ public String getLastModifiedBy() {
+ return lastModifiedBy;
+ }
+
+ public ZonedDateTime getLastModifiedDate() {
+ return lastModifiedDate;
+ }
+
+ public void setLastModifiedDate(ZonedDateTime lastModifiedDate) {
+ this.lastModifiedDate = lastModifiedDate;
+ }
+
+ public Set getAuthorities() {
+ return authorities;
+ }
+
+ @Override
+ public String toString() {
+ return "UserDTO{" +
+ "login='" + login + '\'' +
+ ", firstName='" + firstName + '\'' +
+ ", lastName='" + lastName + '\'' +
+ ", email='" + email + '\'' +
+ ", imageUrl='" + imageUrl + '\'' +
+ ", activated=" + activated +
+ ", langKey='" + langKey + '\'' +
+ ", createdBy=" + createdBy +
+ ", createdDate=" + createdDate +
+ ", lastModifiedBy='" + lastModifiedBy + '\'' +
+ ", lastModifiedDate=" + lastModifiedDate +
+ ", authorities=" + authorities +
+ "}";
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/dto/package-info.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/dto/package-info.java
new file mode 100644
index 0000000000..e8c13430ca
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/dto/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Data Transfer Objects.
+ */
+package com.gateway.service.dto;
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/mapper/UserMapper.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/mapper/UserMapper.java
new file mode 100644
index 0000000000..d2bf0170c4
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/mapper/UserMapper.java
@@ -0,0 +1,55 @@
+package com.gateway.service.mapper;
+
+import com.gateway.domain.Authority;
+import com.gateway.domain.User;
+import com.gateway.service.dto.UserDTO;
+import org.mapstruct.*;
+
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Mapper for the entity User and its DTO UserDTO.
+ */
+@Mapper(componentModel = "spring", uses = {})
+public interface UserMapper {
+
+ UserDTO userToUserDTO(User user);
+
+ List usersToUserDTOs(List users);
+
+ @Mapping(target = "createdBy", ignore = true)
+ @Mapping(target = "createdDate", ignore = true)
+ @Mapping(target = "lastModifiedBy", ignore = true)
+ @Mapping(target = "lastModifiedDate", ignore = true)
+ @Mapping(target = "activationKey", ignore = true)
+ @Mapping(target = "resetKey", ignore = true)
+ @Mapping(target = "resetDate", ignore = true)
+ @Mapping(target = "password", ignore = true)
+ User userDTOToUser(UserDTO userDTO);
+
+ List userDTOsToUsers(List userDTOs);
+
+ default User userFromId(Long id) {
+ if (id == null) {
+ return null;
+ }
+ User user = new User();
+ user.setId(id);
+ return user;
+ }
+
+ default Set stringsFromAuthorities (Set authorities) {
+ return authorities.stream().map(Authority::getName)
+ .collect(Collectors.toSet());
+ }
+
+ default Set authoritiesFromStrings(Set strings) {
+ return strings.stream().map(string -> {
+ Authority auth = new Authority();
+ auth.setName(string);
+ return auth;
+ }).collect(Collectors.toSet());
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/mapper/package-info.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/mapper/package-info.java
new file mode 100644
index 0000000000..7f1db9976c
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/mapper/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * MapStruct mappers for mapping domain objects and Data Transfer Objects.
+ */
+package com.gateway.service.mapper;
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/package-info.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/package-info.java
new file mode 100644
index 0000000000..05b7074c1b
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Service layer beans.
+ */
+package com.gateway.service;
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/util/RandomUtil.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/util/RandomUtil.java
new file mode 100644
index 0000000000..ec2db0f6b0
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/service/util/RandomUtil.java
@@ -0,0 +1,41 @@
+package com.gateway.service.util;
+
+import org.apache.commons.lang3.RandomStringUtils;
+
+/**
+ * Utility class for generating random Strings.
+ */
+public final class RandomUtil {
+
+ private static final int DEF_COUNT = 20;
+
+ private RandomUtil() {
+ }
+
+ /**
+ * Generate a password.
+ *
+ * @return the generated password
+ */
+ public static String generatePassword() {
+ return RandomStringUtils.randomAlphanumeric(DEF_COUNT);
+ }
+
+ /**
+ * Generate an activation key.
+ *
+ * @return the generated activation key
+ */
+ public static String generateActivationKey() {
+ return RandomStringUtils.randomNumeric(DEF_COUNT);
+ }
+
+ /**
+ * Generate a reset key.
+ *
+ * @return the generated reset key
+ */
+ public static String generateResetKey() {
+ return RandomStringUtils.randomNumeric(DEF_COUNT);
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/AccountResource.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/AccountResource.java
new file mode 100644
index 0000000000..1e71217a5d
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/AccountResource.java
@@ -0,0 +1,202 @@
+package com.gateway.web.rest;
+
+import com.codahale.metrics.annotation.Timed;
+
+import com.gateway.domain.User;
+import com.gateway.repository.UserRepository;
+import com.gateway.security.SecurityUtils;
+import com.gateway.service.MailService;
+import com.gateway.service.UserService;
+import com.gateway.service.dto.UserDTO;
+import com.gateway.web.rest.vm.KeyAndPasswordVM;
+import com.gateway.web.rest.vm.ManagedUserVM;
+import com.gateway.web.rest.util.HeaderUtil;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
+import java.util.*;
+
+/**
+ * REST controller for managing the current user's account.
+ */
+@RestController
+@RequestMapping("/api")
+public class AccountResource {
+
+ private final Logger log = LoggerFactory.getLogger(AccountResource.class);
+
+ private final UserRepository userRepository;
+
+ private final UserService userService;
+
+ private final MailService mailService;
+
+ public AccountResource(UserRepository userRepository, UserService userService,
+ MailService mailService) {
+
+ this.userRepository = userRepository;
+ this.userService = userService;
+ this.mailService = mailService;
+ }
+
+ /**
+ * POST /register : register the user.
+ *
+ * @param managedUserVM the managed user View Model
+ * @return the ResponseEntity with status 201 (Created) if the user is registered or 400 (Bad Request) if the login or e-mail is already in use
+ */
+ @PostMapping(path = "/register",
+ produces={MediaType.APPLICATION_JSON_VALUE, MediaType.TEXT_PLAIN_VALUE})
+ @Timed
+ public ResponseEntity registerAccount(@Valid @RequestBody ManagedUserVM managedUserVM) {
+
+ HttpHeaders textPlainHeaders = new HttpHeaders();
+ textPlainHeaders.setContentType(MediaType.TEXT_PLAIN);
+
+ return userRepository.findOneByLogin(managedUserVM.getLogin().toLowerCase())
+ .map(user -> new ResponseEntity<>("login already in use", textPlainHeaders, HttpStatus.BAD_REQUEST))
+ .orElseGet(() -> userRepository.findOneByEmail(managedUserVM.getEmail())
+ .map(user -> new ResponseEntity<>("e-mail address already in use", textPlainHeaders, HttpStatus.BAD_REQUEST))
+ .orElseGet(() -> {
+ User user = userService
+ .createUser(managedUserVM.getLogin(), managedUserVM.getPassword(),
+ managedUserVM.getFirstName(), managedUserVM.getLastName(),
+ managedUserVM.getEmail().toLowerCase(), managedUserVM.getImageUrl(), managedUserVM.getLangKey());
+
+ mailService.sendActivationEmail(user);
+ return new ResponseEntity<>(HttpStatus.CREATED);
+ })
+ );
+ }
+
+ /**
+ * GET /activate : activate the registered user.
+ *
+ * @param key the activation key
+ * @return the ResponseEntity with status 200 (OK) and the activated user in body, or status 500 (Internal Server Error) if the user couldn't be activated
+ */
+ @GetMapping("/activate")
+ @Timed
+ public ResponseEntity activateAccount(@RequestParam(value = "key") String key) {
+ return userService.activateRegistration(key)
+ .map(user -> new ResponseEntity(HttpStatus.OK))
+ .orElse(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
+ }
+
+ /**
+ * GET /authenticate : check if the user is authenticated, and return its login.
+ *
+ * @param request the HTTP request
+ * @return the login if the user is authenticated
+ */
+ @GetMapping("/authenticate")
+ @Timed
+ public String isAuthenticated(HttpServletRequest request) {
+ log.debug("REST request to check if the current user is authenticated");
+ return request.getRemoteUser();
+ }
+
+ /**
+ * GET /account : get the current user.
+ *
+ * @return the ResponseEntity with status 200 (OK) and the current user in body, or status 500 (Internal Server Error) if the user couldn't be returned
+ */
+ @GetMapping("/account")
+ @Timed
+ public ResponseEntity getAccount() {
+ return Optional.ofNullable(userService.getUserWithAuthorities())
+ .map(user -> new ResponseEntity<>(new UserDTO(user), HttpStatus.OK))
+ .orElse(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
+ }
+
+ /**
+ * POST /account : update the current user information.
+ *
+ * @param userDTO the current user information
+ * @return the ResponseEntity with status 200 (OK), or status 400 (Bad Request) or 500 (Internal Server Error) if the user couldn't be updated
+ */
+ @PostMapping("/account")
+ @Timed
+ public ResponseEntity saveAccount(@Valid @RequestBody UserDTO userDTO) {
+ Optional existingUser = userRepository.findOneByEmail(userDTO.getEmail());
+ if (existingUser.isPresent() && (!existingUser.get().getLogin().equalsIgnoreCase(userDTO.getLogin()))) {
+ return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert("user-management", "emailexists", "Email already in use")).body(null);
+ }
+ return userRepository
+ .findOneByLogin(SecurityUtils.getCurrentUserLogin())
+ .map(u -> {
+ userService.updateUser(userDTO.getFirstName(), userDTO.getLastName(), userDTO.getEmail(),
+ userDTO.getLangKey());
+ return new ResponseEntity(HttpStatus.OK);
+ })
+ .orElseGet(() -> new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
+ }
+
+ /**
+ * POST /account/change_password : changes the current user's password
+ *
+ * @param password the new password
+ * @return the ResponseEntity with status 200 (OK), or status 400 (Bad Request) if the new password is not strong enough
+ */
+ @PostMapping(path = "/account/change_password",
+ produces = MediaType.TEXT_PLAIN_VALUE)
+ @Timed
+ public ResponseEntity changePassword(@RequestBody String password) {
+ if (!checkPasswordLength(password)) {
+ return new ResponseEntity<>("Incorrect password", HttpStatus.BAD_REQUEST);
+ }
+ userService.changePassword(password);
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+
+ /**
+ * POST /account/reset_password/init : Send an e-mail to reset the password of the user
+ *
+ * @param mail the mail of the user
+ * @return the ResponseEntity with status 200 (OK) if the e-mail was sent, or status 400 (Bad Request) if the e-mail address is not registered
+ */
+ @PostMapping(path = "/account/reset_password/init",
+ produces = MediaType.TEXT_PLAIN_VALUE)
+ @Timed
+ public ResponseEntity requestPasswordReset(@RequestBody String mail) {
+ return userService.requestPasswordReset(mail)
+ .map(user -> {
+ mailService.sendPasswordResetMail(user);
+ return new ResponseEntity<>("e-mail was sent", HttpStatus.OK);
+ }).orElse(new ResponseEntity<>("e-mail address not registered", HttpStatus.BAD_REQUEST));
+ }
+
+ /**
+ * POST /account/reset_password/finish : Finish to reset the password of the user
+ *
+ * @param keyAndPassword the generated key and the new password
+ * @return the ResponseEntity with status 200 (OK) if the password has been reset,
+ * or status 400 (Bad Request) or 500 (Internal Server Error) if the password could not be reset
+ */
+ @PostMapping(path = "/account/reset_password/finish",
+ produces = MediaType.TEXT_PLAIN_VALUE)
+ @Timed
+ public ResponseEntity finishPasswordReset(@RequestBody KeyAndPasswordVM keyAndPassword) {
+ if (!checkPasswordLength(keyAndPassword.getNewPassword())) {
+ return new ResponseEntity<>("Incorrect password", HttpStatus.BAD_REQUEST);
+ }
+ return userService.completePasswordReset(keyAndPassword.getNewPassword(), keyAndPassword.getKey())
+ .map(user -> new ResponseEntity(HttpStatus.OK))
+ .orElse(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
+ }
+
+ private boolean checkPasswordLength(String password) {
+ return !StringUtils.isEmpty(password) &&
+ password.length() >= ManagedUserVM.PASSWORD_MIN_LENGTH &&
+ password.length() <= ManagedUserVM.PASSWORD_MAX_LENGTH;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/AuditResource.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/AuditResource.java
new file mode 100644
index 0000000000..f61d1ebcb9
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/AuditResource.java
@@ -0,0 +1,76 @@
+package com.gateway.web.rest;
+
+import com.gateway.service.AuditEventService;
+import com.gateway.web.rest.util.PaginationUtil;
+
+import io.github.jhipster.web.util.ResponseUtil;
+import io.swagger.annotations.ApiParam;
+import org.springframework.boot.actuate.audit.AuditEvent;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.net.URISyntaxException;
+import java.time.LocalDate;
+import java.util.List;
+
+/**
+ * REST controller for getting the audit events.
+ */
+@RestController
+@RequestMapping("/management/audits")
+public class AuditResource {
+
+ private final AuditEventService auditEventService;
+
+ public AuditResource(AuditEventService auditEventService) {
+ this.auditEventService = auditEventService;
+ }
+
+ /**
+ * GET /audits : get a page of AuditEvents.
+ *
+ * @param pageable the pagination information
+ * @return the ResponseEntity with status 200 (OK) and the list of AuditEvents in body
+ */
+ @GetMapping
+ public ResponseEntity> getAll(@ApiParam Pageable pageable) {
+ Page page = auditEventService.findAll(pageable);
+ HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/management/audits");
+ return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
+ }
+
+ /**
+ * GET /audits : get a page of AuditEvents between the fromDate and toDate.
+ *
+ * @param fromDate the start of the time period of AuditEvents to get
+ * @param toDate the end of the time period of AuditEvents to get
+ * @param pageable the pagination information
+ * @return the ResponseEntity with status 200 (OK) and the list of AuditEvents in body
+ */
+
+ @GetMapping(params = {"fromDate", "toDate"})
+ public ResponseEntity> getByDates(
+ @RequestParam(value = "fromDate") LocalDate fromDate,
+ @RequestParam(value = "toDate") LocalDate toDate,
+ @ApiParam Pageable pageable) {
+
+ Page page = auditEventService.findByDates(fromDate.atTime(0, 0), toDate.atTime(23, 59), pageable);
+ HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/management/audits");
+ return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
+ }
+
+ /**
+ * GET /audits/:id : get an AuditEvent by id.
+ *
+ * @param id the id of the entity to get
+ * @return the ResponseEntity with status 200 (OK) and the AuditEvent in body, or status 404 (Not Found)
+ */
+ @GetMapping("/{id:.+}")
+ public ResponseEntity get(@PathVariable Long id) {
+ return ResponseUtil.wrapOrNotFound(auditEventService.find(id));
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/GatewayResource.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/GatewayResource.java
new file mode 100644
index 0000000000..74bf2fd151
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/GatewayResource.java
@@ -0,0 +1,55 @@
+package com.gateway.web.rest;
+
+import com.gateway.web.rest.vm.RouteVM;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cloud.client.discovery.DiscoveryClient;
+import org.springframework.cloud.netflix.zuul.filters.Route;
+import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
+import org.springframework.http.*;
+import org.springframework.web.bind.annotation.*;
+
+import com.codahale.metrics.annotation.Timed;
+
+/**
+ * REST controller for managing Gateway configuration.
+ */
+@RestController
+@RequestMapping("/api/gateway")
+public class GatewayResource {
+
+ private final Logger log = LoggerFactory.getLogger(GatewayResource.class);
+
+ private final RouteLocator routeLocator;
+
+ private final DiscoveryClient discoveryClient;
+
+ public GatewayResource(RouteLocator routeLocator, DiscoveryClient discoveryClient) {
+ this.routeLocator = routeLocator;
+ this.discoveryClient = discoveryClient;
+ }
+
+ /**
+ * GET /routes : get the active routes.
+ *
+ * @return the ResponseEntity with status 200 (OK) and with body the list of routes
+ */
+ @GetMapping("/routes")
+ @Timed
+ public ResponseEntity> activeRoutes() {
+ List routes = routeLocator.getRoutes();
+ List routeVMs = new ArrayList<>();
+ routes.forEach(route -> {
+ RouteVM routeVM = new RouteVM();
+ routeVM.setPath(route.getFullPath());
+ routeVM.setServiceId(route.getId());
+ routeVM.setServiceInstances(discoveryClient.getInstances(route.getId()));
+ routeVMs.add(routeVM);
+ });
+ return new ResponseEntity<>(routeVMs, HttpStatus.OK);
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/JWTToken.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/JWTToken.java
new file mode 100644
index 0000000000..7305f901dd
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/JWTToken.java
@@ -0,0 +1,24 @@
+package com.gateway.web.rest;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Object to return as body in JWT Authentication.
+ */
+public class JWTToken {
+
+ private String idToken;
+
+ public JWTToken(String idToken) {
+ this.idToken = idToken;
+ }
+
+ @JsonProperty("id_token")
+ public String getIdToken() {
+ return idToken;
+ }
+
+ public void setIdToken(String idToken) {
+ this.idToken = idToken;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/LogsResource.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/LogsResource.java
new file mode 100644
index 0000000000..7197afbec1
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/LogsResource.java
@@ -0,0 +1,39 @@
+package com.gateway.web.rest;
+
+import com.gateway.web.rest.vm.LoggerVM;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.LoggerContext;
+import com.codahale.metrics.annotation.Timed;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Controller for view and managing Log Level at runtime.
+ */
+@RestController
+@RequestMapping("/management")
+public class LogsResource {
+
+ @GetMapping("/logs")
+ @Timed
+ public List getList() {
+ LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
+ return context.getLoggerList()
+ .stream()
+ .map(LoggerVM::new)
+ .collect(Collectors.toList());
+ }
+
+ @PutMapping("/logs")
+ @ResponseStatus(HttpStatus.NO_CONTENT)
+ @Timed
+ public void changeLevel(@RequestBody LoggerVM jsonLogger) {
+ LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
+ context.getLogger(jsonLogger.getName()).setLevel(Level.valueOf(jsonLogger.getLevel()));
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/ProfileInfoResource.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/ProfileInfoResource.java
new file mode 100644
index 0000000000..f077bd07f7
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/ProfileInfoResource.java
@@ -0,0 +1,69 @@
+package com.gateway.web.rest;
+
+import com.gateway.config.DefaultProfileUtil;
+
+import io.github.jhipster.config.JHipsterProperties;
+
+import org.springframework.core.env.Environment;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Resource to return information about the currently running Spring profiles.
+ */
+@RestController
+@RequestMapping("/api")
+public class ProfileInfoResource {
+
+ private final Environment env;
+
+ private final JHipsterProperties jHipsterProperties;
+
+ public ProfileInfoResource(Environment env, JHipsterProperties jHipsterProperties) {
+ this.env = env;
+ this.jHipsterProperties = jHipsterProperties;
+ }
+
+ @GetMapping("/profile-info")
+ public ProfileInfoVM getActiveProfiles() {
+ String[] activeProfiles = DefaultProfileUtil.getActiveProfiles(env);
+ return new ProfileInfoVM(activeProfiles, getRibbonEnv(activeProfiles));
+ }
+
+ private String getRibbonEnv(String[] activeProfiles) {
+ String[] displayOnActiveProfiles = jHipsterProperties.getRibbon().getDisplayOnActiveProfiles();
+ if (displayOnActiveProfiles == null) {
+ return null;
+ }
+ List ribbonProfiles = new ArrayList<>(Arrays.asList(displayOnActiveProfiles));
+ List springBootProfiles = Arrays.asList(activeProfiles);
+ ribbonProfiles.retainAll(springBootProfiles);
+ if (!ribbonProfiles.isEmpty()) {
+ return ribbonProfiles.get(0);
+ }
+ return null;
+ }
+
+ class ProfileInfoVM {
+
+ private String[] activeProfiles;
+
+ private String ribbonEnv;
+
+ ProfileInfoVM(String[] activeProfiles, String ribbonEnv) {
+ this.activeProfiles = activeProfiles;
+ this.ribbonEnv = ribbonEnv;
+ }
+
+ public String[] getActiveProfiles() {
+ return activeProfiles;
+ }
+
+ public String getRibbonEnv() {
+ return ribbonEnv;
+ }
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/UserJWTController.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/UserJWTController.java
new file mode 100644
index 0000000000..908e4f096b
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/UserJWTController.java
@@ -0,0 +1,60 @@
+package com.gateway.web.rest;
+
+import com.gateway.security.jwt.JWTConfigurer;
+import com.gateway.security.jwt.TokenProvider;
+import com.gateway.web.rest.vm.LoginVM;
+
+import java.util.Collections;
+
+import com.codahale.metrics.annotation.Timed;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+
+@RestController
+@RequestMapping("/api")
+public class UserJWTController {
+
+ private final Logger log = LoggerFactory.getLogger(UserJWTController.class);
+
+ private final TokenProvider tokenProvider;
+
+ private final AuthenticationManager authenticationManager;
+
+ public UserJWTController(TokenProvider tokenProvider, AuthenticationManager authenticationManager) {
+ this.tokenProvider = tokenProvider;
+ this.authenticationManager = authenticationManager;
+ }
+
+ @PostMapping("/authenticate")
+ @Timed
+ public ResponseEntity authorize(@Valid @RequestBody LoginVM loginVM, HttpServletResponse response) {
+
+ UsernamePasswordAuthenticationToken authenticationToken =
+ new UsernamePasswordAuthenticationToken(loginVM.getUsername(), loginVM.getPassword());
+
+ try {
+ Authentication authentication = this.authenticationManager.authenticate(authenticationToken);
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ boolean rememberMe = (loginVM.isRememberMe() == null) ? false : loginVM.isRememberMe();
+ String jwt = tokenProvider.createToken(authentication, rememberMe);
+ response.addHeader(JWTConfigurer.AUTHORIZATION_HEADER, "Bearer " + jwt);
+ return ResponseEntity.ok(new JWTToken(jwt));
+ } catch (AuthenticationException ae) {
+ log.trace("Authentication exception trace: {}", ae);
+ return new ResponseEntity<>(Collections.singletonMap("AuthenticationException",
+ ae.getLocalizedMessage()), HttpStatus.UNAUTHORIZED);
+ }
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/UserResource.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/UserResource.java
new file mode 100644
index 0000000000..80012aacd5
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/UserResource.java
@@ -0,0 +1,187 @@
+package com.gateway.web.rest;
+
+import com.gateway.config.Constants;
+import com.codahale.metrics.annotation.Timed;
+import com.gateway.domain.User;
+import com.gateway.repository.UserRepository;
+import com.gateway.security.AuthoritiesConstants;
+import com.gateway.service.MailService;
+import com.gateway.service.UserService;
+import com.gateway.service.dto.UserDTO;
+import com.gateway.web.rest.vm.ManagedUserVM;
+import com.gateway.web.rest.util.HeaderUtil;
+import com.gateway.web.rest.util.PaginationUtil;
+import io.github.jhipster.web.util.ResponseUtil;
+import io.swagger.annotations.ApiParam;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.annotation.Secured;
+import org.springframework.web.bind.annotation.*;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.*;
+
+/**
+ * REST controller for managing users.
+ *
+ *
This class accesses the User entity, and needs to fetch its collection of authorities.
+ *
+ * For a normal use-case, it would be better to have an eager relationship between User and Authority,
+ * and send everything to the client side: there would be no View Model and DTO, a lot less code, and an outer-join
+ * which would be good for performance.
+ *
+ *
+ * We use a View Model and a DTO for 3 reasons:
+ *
+ *
We want to keep a lazy association between the user and the authorities, because people will
+ * quite often do relationships with the user, and we don't want them to get the authorities all
+ * the time for nothing (for performance reasons). This is the #1 goal: we should not impact our users'
+ * application because of this use-case.
+ *
Not having an outer join causes n+1 requests to the database. This is not a real issue as
+ * we have by default a second-level cache. This means on the first HTTP call we do the n+1 requests,
+ * but then all authorities come from the cache, so in fact it's much better than doing an outer join
+ * (which will get lots of data from the database, for each HTTP call).
+ *
As this manages users, for security reasons, we'd rather have a DTO layer.
+ *
+ *
Another option would be to have a specific JPA entity graph to handle this case.
+ */
+@RestController
+@RequestMapping("/api")
+public class UserResource {
+
+ private final Logger log = LoggerFactory.getLogger(UserResource.class);
+
+ private static final String ENTITY_NAME = "userManagement";
+
+ private final UserRepository userRepository;
+
+ private final MailService mailService;
+
+ private final UserService userService;
+
+ public UserResource(UserRepository userRepository, MailService mailService,
+ UserService userService) {
+
+ this.userRepository = userRepository;
+ this.mailService = mailService;
+ this.userService = userService;
+ }
+
+ /**
+ * POST /users : Creates a new user.
+ *
+ * Creates a new user if the login and email are not already used, and sends an
+ * mail with an activation link.
+ * The user needs to be activated on creation.
+ *
+ *
+ * @param managedUserVM the user to create
+ * @return the ResponseEntity with status 201 (Created) and with body the new user, or with status 400 (Bad Request) if the login or email is already in use
+ * @throws URISyntaxException if the Location URI syntax is incorrect
+ */
+ @PostMapping("/users")
+ @Timed
+ @Secured(AuthoritiesConstants.ADMIN)
+ public ResponseEntity createUser(@RequestBody ManagedUserVM managedUserVM) throws URISyntaxException {
+ log.debug("REST request to save User : {}", managedUserVM);
+
+ if (managedUserVM.getId() != null) {
+ return ResponseEntity.badRequest()
+ .headers(HeaderUtil.createFailureAlert(ENTITY_NAME, "idexists", "A new user cannot already have an ID"))
+ .body(null);
+ // Lowercase the user login before comparing with database
+ } else if (userRepository.findOneByLogin(managedUserVM.getLogin().toLowerCase()).isPresent()) {
+ return ResponseEntity.badRequest()
+ .headers(HeaderUtil.createFailureAlert(ENTITY_NAME, "userexists", "Login already in use"))
+ .body(null);
+ } else if (userRepository.findOneByEmail(managedUserVM.getEmail()).isPresent()) {
+ return ResponseEntity.badRequest()
+ .headers(HeaderUtil.createFailureAlert(ENTITY_NAME, "emailexists", "Email already in use"))
+ .body(null);
+ } else {
+ User newUser = userService.createUser(managedUserVM);
+ mailService.sendCreationEmail(newUser);
+ return ResponseEntity.created(new URI("/api/users/" + newUser.getLogin()))
+ .headers(HeaderUtil.createAlert( "A user is created with identifier " + newUser.getLogin(), newUser.getLogin()))
+ .body(newUser);
+ }
+ }
+
+ /**
+ * PUT /users : Updates an existing User.
+ *
+ * @param managedUserVM the user to update
+ * @return the ResponseEntity with status 200 (OK) and with body the updated user,
+ * or with status 400 (Bad Request) if the login or email is already in use,
+ * or with status 500 (Internal Server Error) if the user couldn't be updated
+ */
+ @PutMapping("/users")
+ @Timed
+ @Secured(AuthoritiesConstants.ADMIN)
+ public ResponseEntity updateUser(@RequestBody ManagedUserVM managedUserVM) {
+ log.debug("REST request to update User : {}", managedUserVM);
+ Optional existingUser = userRepository.findOneByEmail(managedUserVM.getEmail());
+ if (existingUser.isPresent() && (!existingUser.get().getId().equals(managedUserVM.getId()))) {
+ return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert(ENTITY_NAME, "emailexists", "E-mail already in use")).body(null);
+ }
+ existingUser = userRepository.findOneByLogin(managedUserVM.getLogin().toLowerCase());
+ if (existingUser.isPresent() && (!existingUser.get().getId().equals(managedUserVM.getId()))) {
+ return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert(ENTITY_NAME, "userexists", "Login already in use")).body(null);
+ }
+ Optional updatedUser = userService.updateUser(managedUserVM);
+
+ return ResponseUtil.wrapOrNotFound(updatedUser,
+ HeaderUtil.createAlert("A user is updated with identifier " + managedUserVM.getLogin(), managedUserVM.getLogin()));
+ }
+
+ /**
+ * GET /users : get all users.
+ *
+ * @param pageable the pagination information
+ * @return the ResponseEntity with status 200 (OK) and with body all users
+ */
+ @GetMapping("/users")
+ @Timed
+ public ResponseEntity> getAllUsers(@ApiParam Pageable pageable) {
+ final Page page = userService.getAllManagedUsers(pageable);
+ HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/users");
+ return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
+ }
+
+ /**
+ * GET /users/:login : get the "login" user.
+ *
+ * @param login the login of the user to find
+ * @return the ResponseEntity with status 200 (OK) and with body the "login" user, or with status 404 (Not Found)
+ */
+ @GetMapping("/users/{login:" + Constants.LOGIN_REGEX + "}")
+ @Timed
+ public ResponseEntity getUser(@PathVariable String login) {
+ log.debug("REST request to get User : {}", login);
+ return ResponseUtil.wrapOrNotFound(
+ userService.getUserWithAuthoritiesByLogin(login)
+ .map(UserDTO::new));
+ }
+
+ /**
+ * DELETE /users/:login : delete the "login" User.
+ *
+ * @param login the login of the user to delete
+ * @return the ResponseEntity with status 200 (OK)
+ */
+ @DeleteMapping("/users/{login:" + Constants.LOGIN_REGEX + "}")
+ @Timed
+ @Secured(AuthoritiesConstants.ADMIN)
+ public ResponseEntity deleteUser(@PathVariable String login) {
+ log.debug("REST request to delete User: {}", login);
+ userService.deleteUser(login);
+ return ResponseEntity.ok().headers(HeaderUtil.createAlert( "A user is deleted with identifier " + login, login)).build();
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/errors/CustomParameterizedException.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/errors/CustomParameterizedException.java
new file mode 100644
index 0000000000..30a341880a
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/errors/CustomParameterizedException.java
@@ -0,0 +1,34 @@
+package com.gateway.web.rest.errors;
+
+/**
+ * Custom, parameterized exception, which can be translated on the client side.
+ * For example:
+ *
+ *
+ * throw new CustomParameterizedException("myCustomError", "hello", "world");
+ *
+ *
+ * Can be translated with:
+ *
+ *
+ * "error.myCustomError" : "The server says {{params[0]}} to {{params[1]}}"
+ *
+ */
+public class CustomParameterizedException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String message;
+ private final String[] params;
+
+ public CustomParameterizedException(String message, String... params) {
+ super(message);
+ this.message = message;
+ this.params = params;
+ }
+
+ public ParameterizedErrorVM getErrorVM() {
+ return new ParameterizedErrorVM(message, params);
+ }
+
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/errors/ErrorConstants.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/errors/ErrorConstants.java
new file mode 100644
index 0000000000..2b2b6216e0
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/errors/ErrorConstants.java
@@ -0,0 +1,14 @@
+package com.gateway.web.rest.errors;
+
+public final class ErrorConstants {
+
+ public static final String ERR_CONCURRENCY_FAILURE = "error.concurrencyFailure";
+ public static final String ERR_ACCESS_DENIED = "error.accessDenied";
+ public static final String ERR_VALIDATION = "error.validation";
+ public static final String ERR_METHOD_NOT_SUPPORTED = "error.methodNotSupported";
+ public static final String ERR_INTERNAL_SERVER_ERROR = "error.internalServerError";
+
+ private ErrorConstants() {
+ }
+
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/errors/ErrorVM.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/errors/ErrorVM.java
new file mode 100644
index 0000000000..a7d93c535a
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/errors/ErrorVM.java
@@ -0,0 +1,52 @@
+package com.gateway.web.rest.errors;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * View Model for transferring error message with a list of field errors.
+ */
+public class ErrorVM implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String message;
+ private final String description;
+
+ private List fieldErrors;
+
+ public ErrorVM(String message) {
+ this(message, null);
+ }
+
+ public ErrorVM(String message, String description) {
+ this.message = message;
+ this.description = description;
+ }
+
+ public ErrorVM(String message, String description, List fieldErrors) {
+ this.message = message;
+ this.description = description;
+ this.fieldErrors = fieldErrors;
+ }
+
+ public void add(String objectName, String field, String message) {
+ if (fieldErrors == null) {
+ fieldErrors = new ArrayList<>();
+ }
+ fieldErrors.add(new FieldErrorVM(objectName, field, message));
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public List getFieldErrors() {
+ return fieldErrors;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/errors/ExceptionTranslator.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/errors/ExceptionTranslator.java
new file mode 100644
index 0000000000..adff52d310
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/errors/ExceptionTranslator.java
@@ -0,0 +1,85 @@
+package com.gateway.web.rest.errors;
+
+import java.util.List;
+
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.dao.ConcurrencyFailureException;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.ResponseEntity.BodyBuilder;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.FieldError;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * Controller advice to translate the server side exceptions to client-friendly json structures.
+ */
+@ControllerAdvice
+public class ExceptionTranslator {
+
+ @ExceptionHandler(ConcurrencyFailureException.class)
+ @ResponseStatus(HttpStatus.CONFLICT)
+ @ResponseBody
+ public ErrorVM processConcurrencyError(ConcurrencyFailureException ex) {
+ return new ErrorVM(ErrorConstants.ERR_CONCURRENCY_FAILURE);
+ }
+
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ResponseBody
+ public ErrorVM processValidationError(MethodArgumentNotValidException ex) {
+ BindingResult result = ex.getBindingResult();
+ List fieldErrors = result.getFieldErrors();
+
+ return processFieldErrors(fieldErrors);
+ }
+
+ @ExceptionHandler(CustomParameterizedException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ResponseBody
+ public ParameterizedErrorVM processParameterizedValidationError(CustomParameterizedException ex) {
+ return ex.getErrorVM();
+ }
+
+ @ExceptionHandler(AccessDeniedException.class)
+ @ResponseStatus(HttpStatus.FORBIDDEN)
+ @ResponseBody
+ public ErrorVM processAccessDeniedException(AccessDeniedException e) {
+ return new ErrorVM(ErrorConstants.ERR_ACCESS_DENIED, e.getMessage());
+ }
+
+ private ErrorVM processFieldErrors(List fieldErrors) {
+ ErrorVM dto = new ErrorVM(ErrorConstants.ERR_VALIDATION);
+
+ for (FieldError fieldError : fieldErrors) {
+ dto.add(fieldError.getObjectName(), fieldError.getField(), fieldError.getCode());
+ }
+
+ return dto;
+ }
+
+ @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
+ @ResponseBody
+ @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
+ public ErrorVM processMethodNotSupportedException(HttpRequestMethodNotSupportedException exception) {
+ return new ErrorVM(ErrorConstants.ERR_METHOD_NOT_SUPPORTED, exception.getMessage());
+ }
+
+ @ExceptionHandler(Exception.class)
+ public ResponseEntity processRuntimeException(Exception ex) {
+ BodyBuilder builder;
+ ErrorVM errorVM;
+ ResponseStatus responseStatus = AnnotationUtils.findAnnotation(ex.getClass(), ResponseStatus.class);
+ if (responseStatus != null) {
+ builder = ResponseEntity.status(responseStatus.value());
+ errorVM = new ErrorVM("error." + responseStatus.value().value(), responseStatus.reason());
+ } else {
+ builder = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR);
+ errorVM = new ErrorVM(ErrorConstants.ERR_INTERNAL_SERVER_ERROR, "Internal server error");
+ }
+ return builder.body(errorVM);
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/errors/FieldErrorVM.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/errors/FieldErrorVM.java
new file mode 100644
index 0000000000..0b2eef36d3
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/errors/FieldErrorVM.java
@@ -0,0 +1,33 @@
+package com.gateway.web.rest.errors;
+
+import java.io.Serializable;
+
+public class FieldErrorVM implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String objectName;
+
+ private final String field;
+
+ private final String message;
+
+ public FieldErrorVM(String dto, String field, String message) {
+ this.objectName = dto;
+ this.field = field;
+ this.message = message;
+ }
+
+ public String getObjectName() {
+ return objectName;
+ }
+
+ public String getField() {
+ return field;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/errors/ParameterizedErrorVM.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/errors/ParameterizedErrorVM.java
new file mode 100644
index 0000000000..aaac23d165
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/errors/ParameterizedErrorVM.java
@@ -0,0 +1,27 @@
+package com.gateway.web.rest.errors;
+
+import java.io.Serializable;
+
+/**
+ * View Model for sending a parameterized error message.
+ */
+public class ParameterizedErrorVM implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ private final String message;
+ private final String[] params;
+
+ public ParameterizedErrorVM(String message, String... params) {
+ this.message = message;
+ this.params = params;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public String[] getParams() {
+ return params;
+ }
+
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/package-info.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/package-info.java
new file mode 100644
index 0000000000..14a62c0429
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Spring MVC REST controllers.
+ */
+package com.gateway.web.rest;
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/util/HeaderUtil.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/util/HeaderUtil.java
new file mode 100644
index 0000000000..399d8741dc
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/util/HeaderUtil.java
@@ -0,0 +1,43 @@
+package com.gateway.web.rest.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpHeaders;
+
+/**
+ * Utility class for HTTP headers creation.
+ */
+public final class HeaderUtil {
+
+ private static final Logger log = LoggerFactory.getLogger(HeaderUtil.class);
+
+ private HeaderUtil() {
+ }
+
+ public static HttpHeaders createAlert(String message, String param) {
+ HttpHeaders headers = new HttpHeaders();
+ headers.add("X-gatewayApp-alert", message);
+ headers.add("X-gatewayApp-params", param);
+ return headers;
+ }
+
+ public static HttpHeaders createEntityCreationAlert(String entityName, String param) {
+ return createAlert("A new " + entityName + " is created with identifier " + param, param);
+ }
+
+ public static HttpHeaders createEntityUpdateAlert(String entityName, String param) {
+ return createAlert("A " + entityName + " is updated with identifier " + param, param);
+ }
+
+ public static HttpHeaders createEntityDeletionAlert(String entityName, String param) {
+ return createAlert("A " + entityName + " is deleted with identifier " + param, param);
+ }
+
+ public static HttpHeaders createFailureAlert(String entityName, String errorKey, String defaultMessage) {
+ log.error("Entity creation failed, {}", defaultMessage);
+ HttpHeaders headers = new HttpHeaders();
+ headers.add("X-gatewayApp-error", defaultMessage);
+ headers.add("X-gatewayApp-params", entityName);
+ return headers;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/util/PaginationUtil.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/util/PaginationUtil.java
new file mode 100644
index 0000000000..59ca9cb386
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/util/PaginationUtil.java
@@ -0,0 +1,47 @@
+package com.gateway.web.rest.util;
+
+import org.springframework.data.domain.Page;
+import org.springframework.http.HttpHeaders;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import java.net.URISyntaxException;
+
+/**
+ * Utility class for handling pagination.
+ *
+ *
+ * Pagination uses the same principles as the Github API,
+ * and follow RFC 5988 (Link header).
+ */
+public final class PaginationUtil {
+
+ private PaginationUtil() {
+ }
+
+ public static HttpHeaders generatePaginationHttpHeaders(Page page, String baseUrl) {
+
+ HttpHeaders headers = new HttpHeaders();
+ headers.add("X-Total-Count", "" + Long.toString(page.getTotalElements()));
+ String link = "";
+ if ((page.getNumber() + 1) < page.getTotalPages()) {
+ link = "<" + generateUri(baseUrl, page.getNumber() + 1, page.getSize()) + ">; rel=\"next\",";
+ }
+ // prev link
+ if ((page.getNumber()) > 0) {
+ link += "<" + generateUri(baseUrl, page.getNumber() - 1, page.getSize()) + ">; rel=\"prev\",";
+ }
+ // last and first link
+ int lastPage = 0;
+ if (page.getTotalPages() > 0) {
+ lastPage = page.getTotalPages() - 1;
+ }
+ link += "<" + generateUri(baseUrl, lastPage, page.getSize()) + ">; rel=\"last\",";
+ link += "<" + generateUri(baseUrl, 0, page.getSize()) + ">; rel=\"first\"";
+ headers.add(HttpHeaders.LINK, link);
+ return headers;
+ }
+
+ private static String generateUri(String baseUrl, int page, int size) {
+ return UriComponentsBuilder.fromUriString(baseUrl).queryParam("page", page).queryParam("size", size).toUriString();
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/vm/KeyAndPasswordVM.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/vm/KeyAndPasswordVM.java
new file mode 100644
index 0000000000..6c23d40755
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/vm/KeyAndPasswordVM.java
@@ -0,0 +1,27 @@
+package com.gateway.web.rest.vm;
+
+/**
+ * View Model object for storing the user's key and password.
+ */
+public class KeyAndPasswordVM {
+
+ private String key;
+
+ private String newPassword;
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public String getNewPassword() {
+ return newPassword;
+ }
+
+ public void setNewPassword(String newPassword) {
+ this.newPassword = newPassword;
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/vm/LoggerVM.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/vm/LoggerVM.java
new file mode 100644
index 0000000000..6ade2e5e9c
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/vm/LoggerVM.java
@@ -0,0 +1,48 @@
+package com.gateway.web.rest.vm;
+
+import ch.qos.logback.classic.Logger;
+import com.fasterxml.jackson.annotation.JsonCreator;
+
+/**
+ * View Model object for storing a Logback logger.
+ */
+public class LoggerVM {
+
+ private String name;
+
+ private String level;
+
+ public LoggerVM(Logger logger) {
+ this.name = logger.getName();
+ this.level = logger.getEffectiveLevel().toString();
+ }
+
+ @JsonCreator
+ public LoggerVM() {
+ // Empty public constructor used by Jackson.
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getLevel() {
+ return level;
+ }
+
+ public void setLevel(String level) {
+ this.level = level;
+ }
+
+ @Override
+ public String toString() {
+ return "LoggerVM{" +
+ "name='" + name + '\'' +
+ ", level='" + level + '\'' +
+ '}';
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/vm/LoginVM.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/vm/LoginVM.java
new file mode 100644
index 0000000000..c49f202378
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/vm/LoginVM.java
@@ -0,0 +1,55 @@
+package com.gateway.web.rest.vm;
+
+import com.gateway.config.Constants;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+
+/**
+ * View Model object for storing a user's credentials.
+ */
+public class LoginVM {
+
+ @Pattern(regexp = Constants.LOGIN_REGEX)
+ @NotNull
+ @Size(min = 1, max = 50)
+ private String username;
+
+ @NotNull
+ @Size(min = ManagedUserVM.PASSWORD_MIN_LENGTH, max = ManagedUserVM.PASSWORD_MAX_LENGTH)
+ private String password;
+
+ private Boolean rememberMe;
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public Boolean isRememberMe() {
+ return rememberMe;
+ }
+
+ public void setRememberMe(Boolean rememberMe) {
+ this.rememberMe = rememberMe;
+ }
+
+ @Override
+ public String toString() {
+ return "LoginVM{" +
+ "username='" + username + '\'' +
+ ", rememberMe=" + rememberMe +
+ '}';
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/vm/ManagedUserVM.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/vm/ManagedUserVM.java
new file mode 100644
index 0000000000..d40cea8573
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/vm/ManagedUserVM.java
@@ -0,0 +1,45 @@
+package com.gateway.web.rest.vm;
+
+import com.gateway.service.dto.UserDTO;
+import javax.validation.constraints.Size;
+
+import java.time.ZonedDateTime;
+import java.util.Set;
+
+/**
+ * View Model extending the UserDTO, which is meant to be used in the user management UI.
+ */
+public class ManagedUserVM extends UserDTO {
+
+ public static final int PASSWORD_MIN_LENGTH = 4;
+
+ public static final int PASSWORD_MAX_LENGTH = 100;
+
+ @Size(min = PASSWORD_MIN_LENGTH, max = PASSWORD_MAX_LENGTH)
+ private String password;
+
+ public ManagedUserVM() {
+ // Empty constructor needed for Jackson.
+ }
+
+ public ManagedUserVM(Long id, String login, String password, String firstName, String lastName,
+ String email, boolean activated, String imageUrl, String langKey,
+ String createdBy, ZonedDateTime createdDate, String lastModifiedBy, ZonedDateTime lastModifiedDate,
+ Set authorities) {
+
+ super(id, login, firstName, lastName, email, activated, imageUrl, langKey,
+ createdBy, createdDate, lastModifiedBy, lastModifiedDate, authorities);
+
+ this.password = password;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ @Override
+ public String toString() {
+ return "ManagedUserVM{" +
+ "} " + super.toString();
+ }
+}
diff --git a/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/vm/RouteVM.java b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/vm/RouteVM.java
new file mode 100644
index 0000000000..236924557a
--- /dev/null
+++ b/jhipster/jhipster-microservice/gateway-app/src/main/java/com/gateway/web/rest/vm/RouteVM.java
@@ -0,0 +1,41 @@
+package com.gateway.web.rest.vm;
+
+import java.util.List;
+
+import org.springframework.cloud.client.ServiceInstance;
+
+/**
+ * View Model that stores a route managed by the Gateway.
+ */
+public class RouteVM {
+
+ private String path;
+
+ private String serviceId;
+
+ private List serviceInstances;
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ public String getServiceId() {
+ return serviceId;
+ }
+
+ public void setServiceId(String serviceId) {
+ this.serviceId = serviceId;
+ }
+
+ public List