diff --git a/spring-boot-modules/spring-boot-libraries/README.md b/spring-boot-modules/spring-boot-libraries/README.md
index 8cd3db9c93..10c56ca576 100644
--- a/spring-boot-modules/spring-boot-libraries/README.md
+++ b/spring-boot-modules/spring-boot-libraries/README.md
@@ -12,3 +12,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Generating Barcodes and QR Codes in Java](https://www.baeldung.com/java-generating-barcodes-qr-codes)
- [Rate Limiting a Spring API Using Bucket4j](https://www.baeldung.com/spring-bucket4j)
- [Spring Boot and Caffeine Cache](https://www.baeldung.com/spring-boot-caffeine-cache)
+- [Spring Boot and Togglz Aspect](https://www.baeldung.com/spring-togglz)
+- [Getting Started with GraphQL and Spring Boot](https://www.baeldung.com/spring-graphql)
+- [An Introduction to Kong](https://www.baeldung.com/kong)
diff --git a/spring-boot-modules/spring-boot-libraries/pom.xml b/spring-boot-modules/spring-boot-libraries/pom.xml
index 05ab59aab7..3913babaa8 100644
--- a/spring-boot-modules/spring-boot-libraries/pom.xml
+++ b/spring-boot-modules/spring-boot-libraries/pom.xml
@@ -37,6 +37,36 @@
spring-boot-starter-test
test
+
+
+
+ org.togglz
+ togglz-spring-boot-starter
+ ${togglz.version}
+
+
+
+ org.togglz
+ togglz-spring-security
+ ${togglz.version}
+
+
+
+
+ com.graphql-java
+ graphql-spring-boot-starter
+ ${graphql-spring-boot-starter.version}
+
+
+ com.graphql-java
+ graphql-java-tools
+ ${graphql-java-tools.version}
+
+
+ com.graphql-java
+ graphiql-spring-boot-starter
+ ${graphql-spring-boot-starter.version}
+
@@ -216,7 +246,6 @@
1.9.0
2.0.0
5.0.2
- 5.0.2
5.2.4
18.0
2.2.4
diff --git a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/demo/DemoApplication.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/demo/DemoApplication.java
new file mode 100644
index 0000000000..eb091b4695
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/demo/DemoApplication.java
@@ -0,0 +1,18 @@
+package com.baeldung.demo;
+
+import com.baeldung.graphql.GraphqlConfiguration;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+import org.springframework.context.annotation.Import;
+
+@SpringBootApplication
+@Import(GraphqlConfiguration.class)
+public class DemoApplication {
+
+ public static void main(String[] args) {
+ System.setProperty("spring.config.name", "demo");
+ SpringApplication.run(DemoApplication.class, args);
+ }
+
+}
diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/graphql/Author.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/Author.java
similarity index 100%
rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/graphql/Author.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/Author.java
diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/graphql/AuthorDao.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/AuthorDao.java
similarity index 100%
rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/graphql/AuthorDao.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/AuthorDao.java
diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/graphql/AuthorResolver.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/AuthorResolver.java
similarity index 100%
rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/graphql/AuthorResolver.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/AuthorResolver.java
diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/graphql/GraphqlConfiguration.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/GraphqlConfiguration.java
similarity index 100%
rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/graphql/GraphqlConfiguration.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/GraphqlConfiguration.java
diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/graphql/Mutation.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/Mutation.java
similarity index 100%
rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/graphql/Mutation.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/Mutation.java
diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/graphql/Post.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/Post.java
similarity index 100%
rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/graphql/Post.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/Post.java
diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/graphql/PostDao.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/PostDao.java
similarity index 100%
rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/graphql/PostDao.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/PostDao.java
diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/graphql/PostResolver.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/PostResolver.java
similarity index 100%
rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/graphql/PostResolver.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/PostResolver.java
diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/graphql/Query.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/Query.java
similarity index 100%
rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/graphql/Query.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/Query.java
diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/kong/QueryController.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/kong/QueryController.java
similarity index 100%
rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/kong/QueryController.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/kong/QueryController.java
diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/kong/StockApp.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/kong/StockApp.java
similarity index 100%
rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/kong/StockApp.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/kong/StockApp.java
diff --git a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/toggle/Employee.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/toggle/Employee.java
new file mode 100644
index 0000000000..64a8b3ce5b
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/toggle/Employee.java
@@ -0,0 +1,37 @@
+package com.baeldung.toggle;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+@Entity
+public class Employee {
+
+ @Id
+ private long id;
+ private double salary;
+
+ public Employee() {
+ }
+
+ public Employee(long id, double salary) {
+ this.id = id;
+ this.salary = salary;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public double getSalary() {
+ return salary;
+ }
+
+ public void setSalary(double salary) {
+ this.salary = salary;
+ }
+
+}
diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/toggle/EmployeeRepository.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/toggle/EmployeeRepository.java
similarity index 100%
rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/toggle/EmployeeRepository.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/toggle/EmployeeRepository.java
diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/toggle/FeatureAssociation.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/toggle/FeatureAssociation.java
similarity index 100%
rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/toggle/FeatureAssociation.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/toggle/FeatureAssociation.java
diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/toggle/FeaturesAspect.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/toggle/FeaturesAspect.java
similarity index 100%
rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/toggle/FeaturesAspect.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/toggle/FeaturesAspect.java
diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/toggle/MyFeatures.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/toggle/MyFeatures.java
similarity index 100%
rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/toggle/MyFeatures.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/toggle/MyFeatures.java
diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/toggle/SalaryController.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/toggle/SalaryController.java
similarity index 100%
rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/toggle/SalaryController.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/toggle/SalaryController.java
diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/toggle/SalaryService.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/toggle/SalaryService.java
similarity index 100%
rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/toggle/SalaryService.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/toggle/SalaryService.java
diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/toggle/ToggleApplication.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/toggle/ToggleApplication.java
similarity index 100%
rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/toggle/ToggleApplication.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/toggle/ToggleApplication.java
diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/toggle/ToggleConfiguration.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/toggle/ToggleConfiguration.java
similarity index 100%
rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/toggle/ToggleConfiguration.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/toggle/ToggleConfiguration.java
diff --git a/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/KongAdminAPILiveTest.java b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/KongAdminAPILiveTest.java
new file mode 100644
index 0000000000..92d2286518
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/KongAdminAPILiveTest.java
@@ -0,0 +1,170 @@
+package com.baeldung.kong;
+
+import com.baeldung.kong.domain.APIObject;
+import com.baeldung.kong.domain.ConsumerObject;
+import com.baeldung.kong.domain.KeyAuthObject;
+import com.baeldung.kong.domain.PluginObject;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.http.*;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.net.URI;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT;
+
+/**
+ * @author aiet
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = DEFINED_PORT, classes = StockApp.class)
+public class KongAdminAPILiveTest {
+
+ private String getStockPrice(String code) {
+ try {
+ return restTemplate.getForObject(new URI("http://localhost:8080/stock/" + code), String.class);
+ } catch (Exception ignored) {
+ }
+ return null;
+ }
+
+ @Before
+ public void init() {
+ System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
+ }
+
+ @Autowired
+ TestRestTemplate restTemplate;
+
+ @Test
+ public void givenEndpoint_whenQueryStockPrice_thenPriceCorrect() {
+ String response = getStockPrice("btc");
+ assertEquals("10000", response);
+
+ response = getStockPrice("eth");
+ assertEquals("N/A", response);
+ }
+
+ @Test
+ public void givenKongAdminAPI_whenAddAPI_thenAPIAccessibleViaKong() throws Exception {
+ restTemplate.delete("http://localhost:8001/apis/stock-api");
+
+ APIObject stockAPI = new APIObject("stock-api", "stock.api", "http://localhost:9090", "/");
+ HttpEntity apiEntity = new HttpEntity<>(stockAPI);
+ ResponseEntity addAPIResp = restTemplate.postForEntity("http://localhost:8001/apis", apiEntity, String.class);
+
+ assertEquals(HttpStatus.CREATED, addAPIResp.getStatusCode());
+
+ addAPIResp = restTemplate.postForEntity("http://localhost:8001/apis", apiEntity, String.class);
+ assertEquals(HttpStatus.CONFLICT, addAPIResp.getStatusCode());
+ String apiListResp = restTemplate.getForObject("http://localhost:8001/apis/", String.class);
+
+ assertTrue(apiListResp.contains("stock-api"));
+
+ HttpHeaders headers = new HttpHeaders();
+ headers.set("Host", "stock.api");
+ RequestEntity requestEntity = new RequestEntity<>(headers, HttpMethod.GET, new URI("http://localhost:8000/springbootapp/stock/btc"));
+ ResponseEntity stockPriceResp = restTemplate.exchange(requestEntity, String.class);
+
+ assertEquals("10000", stockPriceResp.getBody());
+ }
+
+ @Test
+ public void givenKongAdminAPI_whenAddAPIConsumer_thenAdded() {
+ restTemplate.delete("http://localhost:8001/consumers/eugenp");
+
+ ConsumerObject consumer = new ConsumerObject("eugenp");
+ HttpEntity addConsumerEntity = new HttpEntity<>(consumer);
+ ResponseEntity addConsumerResp = restTemplate.postForEntity("http://localhost:8001/consumers/", addConsumerEntity, String.class);
+
+ assertEquals(HttpStatus.CREATED, addConsumerResp.getStatusCode());
+
+ addConsumerResp = restTemplate.postForEntity("http://localhost:8001/consumers", addConsumerEntity, String.class);
+ assertEquals(HttpStatus.CONFLICT, addConsumerResp.getStatusCode());
+
+ String consumerListResp = restTemplate.getForObject("http://localhost:8001/consumers/", String.class);
+ assertTrue(consumerListResp.contains("eugenp"));
+ }
+
+ @Test
+ public void givenAPI_whenEnableAuth_thenAnonymousDenied() throws Exception {
+ String apiListResp = restTemplate.getForObject("http://localhost:8001/apis/", String.class);
+ if (!apiListResp.contains("stock-api")) {
+ givenKongAdminAPI_whenAddAPI_thenAPIAccessibleViaKong();
+ }
+
+ PluginObject authPlugin = new PluginObject("key-auth");
+ ResponseEntity enableAuthResp = restTemplate.postForEntity("http://localhost:8001/apis/stock-api/plugins", new HttpEntity<>(authPlugin), String.class);
+
+ assertTrue(HttpStatus.CREATED == enableAuthResp.getStatusCode() || HttpStatus.CONFLICT == enableAuthResp.getStatusCode());
+
+ String pluginsResp = restTemplate.getForObject("http://localhost:8001/apis/stock-api/plugins", String.class);
+ assertTrue(pluginsResp.contains("key-auth"));
+
+ HttpHeaders headers = new HttpHeaders();
+ headers.set("Host", "stock.api");
+ RequestEntity requestEntity = new RequestEntity<>(headers, HttpMethod.GET, new URI("http://localhost:8000/stock/btc"));
+ ResponseEntity stockPriceResp = restTemplate.exchange(requestEntity, String.class);
+ assertEquals(HttpStatus.UNAUTHORIZED, stockPriceResp.getStatusCode());
+ }
+
+ @Test
+ public void givenAPIAuthEnabled_whenAddKey_thenAccessAllowed() throws Exception {
+ String apiListResp = restTemplate.getForObject("http://localhost:8001/apis/", String.class);
+ if (!apiListResp.contains("stock-api")) {
+ givenKongAdminAPI_whenAddAPI_thenAPIAccessibleViaKong();
+ }
+
+ String consumerListResp = restTemplate.getForObject("http://localhost:8001/consumers/", String.class);
+ if (!consumerListResp.contains("eugenp")) {
+ givenKongAdminAPI_whenAddAPIConsumer_thenAdded();
+ }
+
+ PluginObject authPlugin = new PluginObject("key-auth");
+ ResponseEntity enableAuthResp = restTemplate.postForEntity("http://localhost:8001/apis/stock-api/plugins", new HttpEntity<>(authPlugin), String.class);
+ assertTrue(HttpStatus.CREATED == enableAuthResp.getStatusCode() || HttpStatus.CONFLICT == enableAuthResp.getStatusCode());
+
+ final String consumerKey = "eugenp.pass";
+ KeyAuthObject keyAuth = new KeyAuthObject(consumerKey);
+ ResponseEntity keyAuthResp = restTemplate.postForEntity("http://localhost:8001/consumers/eugenp/key-auth", new HttpEntity<>(keyAuth), String.class);
+
+ assertTrue(HttpStatus.CREATED == keyAuthResp.getStatusCode() || HttpStatus.CONFLICT == keyAuthResp.getStatusCode());
+
+ HttpHeaders headers = new HttpHeaders();
+ headers.set("Host", "stock.api");
+ headers.set("apikey", consumerKey);
+ RequestEntity requestEntity = new RequestEntity<>(headers, HttpMethod.GET, new URI("http://localhost:8000/springbootapp/stock/btc"));
+ ResponseEntity stockPriceResp = restTemplate.exchange(requestEntity, String.class);
+
+ assertEquals("10000", stockPriceResp.getBody());
+
+ headers.set("apikey", "wrongpass");
+ requestEntity = new RequestEntity<>(headers, HttpMethod.GET, new URI("http://localhost:8000/springbootapp/stock/btc"));
+ stockPriceResp = restTemplate.exchange(requestEntity, String.class);
+ assertEquals(HttpStatus.FORBIDDEN, stockPriceResp.getStatusCode());
+ }
+
+ @Test
+ public void givenAdminAPIProxy_whenAddAPIViaProxy_thenAPIAdded() throws Exception {
+ APIObject adminAPI = new APIObject("admin-api", "admin.api", "http://localhost:8001", "/admin-api");
+ HttpEntity apiEntity = new HttpEntity<>(adminAPI);
+ ResponseEntity addAPIResp = restTemplate.postForEntity("http://localhost:8001/apis", apiEntity, String.class);
+
+ assertTrue(HttpStatus.CREATED == addAPIResp.getStatusCode() || HttpStatus.CONFLICT == addAPIResp.getStatusCode());
+
+ HttpHeaders headers = new HttpHeaders();
+ headers.set("Host", "admin.api");
+ APIObject baeldungAPI = new APIObject("baeldung-api", "baeldung.com", "http://ww.baeldung.com", "/");
+ RequestEntity requestEntity = new RequestEntity<>(baeldungAPI, headers, HttpMethod.POST, new URI("http://localhost:8000/admin-api/apis"));
+ addAPIResp = restTemplate.exchange(requestEntity, String.class);
+
+ assertTrue(HttpStatus.CREATED == addAPIResp.getStatusCode() || HttpStatus.CONFLICT == addAPIResp.getStatusCode());
+ }
+
+}
diff --git a/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/KongLoadBalanceLiveTest.java b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/KongLoadBalanceLiveTest.java
new file mode 100644
index 0000000000..7cf67453a6
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/KongLoadBalanceLiveTest.java
@@ -0,0 +1,75 @@
+package com.baeldung.kong;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT;
+
+import java.net.URI;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.RequestEntity;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.baeldung.kong.domain.APIObject;
+import com.baeldung.kong.domain.TargetObject;
+import com.baeldung.kong.domain.UpstreamObject;
+
+/**
+ * @author aiet
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = DEFINED_PORT, classes = StockApp.class, properties = "server.servlet.contextPath=/springbootapp")
+public class KongLoadBalanceLiveTest {
+
+ @Before
+ public void init() {
+ System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
+ }
+
+ @Autowired
+ TestRestTemplate restTemplate;
+
+ @Test
+ public void givenKongAdminAPI_whenAddAPI_thenAPIAccessibleViaKong() throws Exception {
+ UpstreamObject upstream = new UpstreamObject("stock.api.service");
+ ResponseEntity addUpstreamResp = restTemplate.postForEntity("http://localhost:8001/upstreams", new HttpEntity<>(upstream), String.class);
+ assertTrue(HttpStatus.CREATED == addUpstreamResp.getStatusCode() || HttpStatus.CONFLICT == addUpstreamResp.getStatusCode());
+
+ TargetObject testTarget = new TargetObject("localhost:8080", 10);
+ ResponseEntity addTargetResp = restTemplate.postForEntity("http://localhost:8001/upstreams/stock.api.service/targets", new HttpEntity<>(testTarget), String.class);
+ assertTrue(HttpStatus.CREATED == addTargetResp.getStatusCode() || HttpStatus.CONFLICT == addTargetResp.getStatusCode());
+
+ TargetObject releaseTarget = new TargetObject("localhost:9090", 40);
+ addTargetResp = restTemplate.postForEntity("http://localhost:8001/upstreams/stock.api.service/targets", new HttpEntity<>(releaseTarget), String.class);
+ assertTrue(HttpStatus.CREATED == addTargetResp.getStatusCode() || HttpStatus.CONFLICT == addTargetResp.getStatusCode());
+
+ APIObject stockAPI = new APIObject("balanced-stock-api", "balanced.stock.api", "http://stock.api.service", "/");
+ HttpEntity apiEntity = new HttpEntity<>(stockAPI);
+ ResponseEntity addAPIResp = restTemplate.postForEntity("http://localhost:8001/apis", apiEntity, String.class);
+ assertTrue(HttpStatus.CREATED == addAPIResp.getStatusCode() || HttpStatus.CONFLICT == addAPIResp.getStatusCode());
+
+ HttpHeaders headers = new HttpHeaders();
+ headers.set("Host", "balanced.stock.api");
+ for (int i = 0; i < 1000; i++) {
+ RequestEntity requestEntity = new RequestEntity<>(headers, HttpMethod.GET, new URI("http://localhost:8000/springbootapp/stock/btc"));
+ ResponseEntity stockPriceResp = restTemplate.exchange(requestEntity, String.class);
+ assertEquals("10000", stockPriceResp.getBody());
+ }
+
+ int releaseCount = restTemplate.getForObject("http://localhost:9090/springbootapp/stock/reqcount", Integer.class);
+ int testCount = restTemplate.getForObject("http://localhost:8080/springbootapp/stock/reqcount", Integer.class);
+
+ assertTrue(Math.round(releaseCount * 1.0 / testCount) == 4);
+ }
+
+}
diff --git a/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/APIObject.java b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/APIObject.java
new file mode 100644
index 0000000000..f386712444
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/APIObject.java
@@ -0,0 +1,54 @@
+package com.baeldung.kong.domain;
+
+/**
+ * @author aiet
+ */
+public class APIObject {
+
+ public APIObject() {
+ }
+
+ public APIObject(String name, String hosts, String upstream_url, String uris) {
+ this.name = name;
+ this.hosts = hosts;
+ this.upstream_url = upstream_url;
+ this.uris = uris;
+ }
+
+ private String name;
+ private String hosts;
+ private String upstream_url;
+ private String uris;
+
+ public String getUris() {
+ return uris;
+ }
+
+ public void setUris(String uris) {
+ this.uris = uris;
+ }
+
+ public String getUpstream_url() {
+ return upstream_url;
+ }
+
+ public void setUpstream_url(String upstream_url) {
+ this.upstream_url = upstream_url;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getHosts() {
+ return hosts;
+ }
+
+ public void setHosts(String hosts) {
+ this.hosts = hosts;
+ }
+}
diff --git a/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/ConsumerObject.java b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/ConsumerObject.java
new file mode 100644
index 0000000000..74bef8f2d1
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/ConsumerObject.java
@@ -0,0 +1,35 @@
+package com.baeldung.kong.domain;
+
+/**
+ * @author aiet
+ */
+public class ConsumerObject {
+
+ private String username;
+ private String custom_id;
+
+ public ConsumerObject(String username) {
+ this.username = username;
+ }
+
+ public ConsumerObject(String username, String custom_id) {
+ this.username = username;
+ this.custom_id = custom_id;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getCustom_id() {
+ return custom_id;
+ }
+
+ public void setCustom_id(String custom_id) {
+ this.custom_id = custom_id;
+ }
+}
diff --git a/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/KeyAuthObject.java b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/KeyAuthObject.java
new file mode 100644
index 0000000000..80de6bfcd9
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/KeyAuthObject.java
@@ -0,0 +1,21 @@
+package com.baeldung.kong.domain;
+
+/**
+ * @author aiet
+ */
+public class KeyAuthObject {
+
+ public KeyAuthObject(String key) {
+ this.key = key;
+ }
+
+ private String key;
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+}
diff --git a/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/PluginObject.java b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/PluginObject.java
new file mode 100644
index 0000000000..c161fc9b54
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/PluginObject.java
@@ -0,0 +1,30 @@
+package com.baeldung.kong.domain;
+
+/**
+ * @author aiet
+ */
+public class PluginObject {
+
+ private String name;
+ private String consumer_id;
+
+ public PluginObject(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getConsumer_id() {
+ return consumer_id;
+ }
+
+ public void setConsumer_id(String consumer_id) {
+ this.consumer_id = consumer_id;
+ }
+}
diff --git a/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/TargetObject.java b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/TargetObject.java
new file mode 100644
index 0000000000..79653e2846
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/TargetObject.java
@@ -0,0 +1,31 @@
+package com.baeldung.kong.domain;
+
+/**
+ * @author aiet
+ */
+public class TargetObject {
+
+ public TargetObject(String target, int weight) {
+ this.target = target;
+ this.weight = weight;
+ }
+
+ private String target;
+ private int weight;
+
+ public String getTarget() {
+ return target;
+ }
+
+ public void setTarget(String target) {
+ this.target = target;
+ }
+
+ public int getWeight() {
+ return weight;
+ }
+
+ public void setWeight(int weight) {
+ this.weight = weight;
+ }
+}
diff --git a/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/UpstreamObject.java b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/UpstreamObject.java
new file mode 100644
index 0000000000..6461381ac5
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/kong/domain/UpstreamObject.java
@@ -0,0 +1,21 @@
+package com.baeldung.kong.domain;
+
+/**
+ * @author aiet
+ */
+public class UpstreamObject {
+
+ public UpstreamObject(String name) {
+ this.name = name;
+ }
+
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/toggle/ToggleIntegrationTest.java b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/toggle/ToggleIntegrationTest.java
new file mode 100644
index 0000000000..3213a10df9
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/toggle/ToggleIntegrationTest.java
@@ -0,0 +1,62 @@
+package com.baeldung.toggle;
+
+import static org.junit.Assert.assertEquals;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK, classes = ToggleApplication.class)
+@AutoConfigureMockMvc
+public class ToggleIntegrationTest {
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @Autowired
+ private WebApplicationContext wac;
+
+ @Before
+ public void setup() {
+ this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
+ }
+
+ @Test
+ public void givenFeaturePropertyFalse_whenIncreaseSalary_thenNoIncrease() throws Exception {
+ Employee emp = new Employee(1, 2000);
+ employeeRepository.save(emp);
+
+ System.setProperty("employee.feature", "false");
+
+ mockMvc.perform(post("/increaseSalary").param("id", emp.getId() + "")).andExpect(status().is(200));
+
+ emp = employeeRepository.findById(1L).orElse(null);
+ assertEquals("salary incorrect", 2000, emp.getSalary(), 0.5);
+ }
+
+ @Test
+ public void givenFeaturePropertyTrue_whenIncreaseSalary_thenIncrease() throws Exception {
+ Employee emp = new Employee(1, 2000);
+ employeeRepository.save(emp);
+
+ System.setProperty("employee.feature", "true");
+
+ mockMvc.perform(post("/increaseSalary").param("id", emp.getId() + "")).andExpect(status().is(200));
+
+ emp = employeeRepository.findById(1L).orElse(null);
+ assertEquals("salary incorrect", 2200, emp.getSalary(), 0.5);
+ }
+}
diff --git a/spring-boot-modules/spring-boot/pom.xml b/spring-boot-modules/spring-boot/pom.xml
index e1299a6a16..5efcffdf03 100644
--- a/spring-boot-modules/spring-boot/pom.xml
+++ b/spring-boot-modules/spring-boot/pom.xml
@@ -44,22 +44,6 @@
spring-boot-starter-actuator
-
- com.graphql-java
- graphql-spring-boot-starter
- ${graphql-spring-boot-starter.version}
-
-
- com.graphql-java
- graphql-java-tools
- ${graphql-java-tools.version}
-
-
- com.graphql-java
- graphiql-spring-boot-starter
- ${graphiql-spring-boot-starter.version}
-
-
org.springframework.boot
spring-boot-starter-tomcat
@@ -104,18 +88,6 @@
provided
-
- org.togglz
- togglz-spring-boot-starter
- ${togglz.version}
-
-
-
- org.togglz
- togglz-spring-security
- ${togglz.version}
-
-
org.apache.activemq
artemis-server
@@ -204,11 +176,7 @@
com.baeldung.intro.App
8.5.11
- 2.4.1.Final
1.9.0
- 5.0.2
- 5.0.2
- 5.2.4
18.0
@