diff --git a/repository/mappings/pl/devoxx/aggregatr/aggregation/shouldGetHop.groovy b/repository/mappings/pl/devoxx/aggregatr/aggregation/shouldGetHop.groovy new file mode 100644 index 0000000..976c96d --- /dev/null +++ b/repository/mappings/pl/devoxx/aggregatr/aggregation/shouldGetHop.groovy @@ -0,0 +1,20 @@ +io.codearte.accurest.dsl.GroovyDsl.make { + request { + method 'POST' + url '/ingredients' + headers { + header 'Content-Type': 'application/vnd.pl.devoxx.aggregatr.v1+json' + } + body(''' + { "items" : ["HOP"] } + ''') + } + response { + status 200 + body( + ingredients: [ + [type: 'HOP', quantity: 200] + ] + ) + } +} \ No newline at end of file diff --git a/repository/mappings/pl/devoxx/aggregatr/aggregation/shouldGetIngredients.groovy b/repository/mappings/pl/devoxx/aggregatr/aggregation/shouldGetIngredients.groovy index c098d1b..f1330eb 100644 --- a/repository/mappings/pl/devoxx/aggregatr/aggregation/shouldGetIngredients.groovy +++ b/repository/mappings/pl/devoxx/aggregatr/aggregation/shouldGetIngredients.groovy @@ -1,19 +1,22 @@ io.codearte.accurest.dsl.GroovyDsl.make { request { - method 'GET' + method 'POST' url '/ingredients' headers { header 'Content-Type': 'application/vnd.pl.devoxx.aggregatr.v1+json' } + body(''' + { "items" : ["MALT","WATER","HOP","YIEST"] } + ''') } response { status 200 body( ingredients: [ - [type: 'MALT', quantity: 100], + [type: 'MALT', quantity: 200], [type: 'WATER', quantity: 200], - [type: 'HOP', quantity: 300], - [type: 'YIEST', quantity: 400] + [type: 'HOP', quantity: 200], + [type: 'YIEST', quantity: 200] ] ) } diff --git a/repository/mappings/pl/devoxx/aggregatr/aggregation/shouldGetMalt.groovy b/repository/mappings/pl/devoxx/aggregatr/aggregation/shouldGetMalt.groovy new file mode 100644 index 0000000..86a5422 --- /dev/null +++ b/repository/mappings/pl/devoxx/aggregatr/aggregation/shouldGetMalt.groovy @@ -0,0 +1,20 @@ +io.codearte.accurest.dsl.GroovyDsl.make { + request { + method 'POST' + url '/ingredients' + headers { + header 'Content-Type': 'application/vnd.pl.devoxx.aggregatr.v1+json' + } + body(''' + { "items" : ["MALT"] } + ''') + } + response { + status 200 + body( + ingredients: [ + [type: 'MALT', quantity: 200] + ] + ) + } +} \ No newline at end of file diff --git a/repository/mappings/pl/devoxx/aggregatr/aggregation/shouldGetWater.groovy b/repository/mappings/pl/devoxx/aggregatr/aggregation/shouldGetWater.groovy new file mode 100644 index 0000000..d8eab64 --- /dev/null +++ b/repository/mappings/pl/devoxx/aggregatr/aggregation/shouldGetWater.groovy @@ -0,0 +1,20 @@ +io.codearte.accurest.dsl.GroovyDsl.make { + request { + method 'POST' + url '/ingredients' + headers { + header 'Content-Type': 'application/vnd.pl.devoxx.aggregatr.v1+json' + } + body(''' + { "items" : ["WATER"] } + ''') + } + response { + status 200 + body( + ingredients: [ + [type: 'WATER', quantity: 200] + ] + ) + } +} \ No newline at end of file diff --git a/repository/mappings/pl/devoxx/aggregatr/aggregation/shouldGetYiest.groovy b/repository/mappings/pl/devoxx/aggregatr/aggregation/shouldGetYiest.groovy new file mode 100644 index 0000000..0799b6d --- /dev/null +++ b/repository/mappings/pl/devoxx/aggregatr/aggregation/shouldGetYiest.groovy @@ -0,0 +1,20 @@ +io.codearte.accurest.dsl.GroovyDsl.make { + request { + method 'POST' + url '/ingredients' + headers { + header 'Content-Type': 'application/vnd.pl.devoxx.aggregatr.v1+json' + } + body(''' + { "items" : ["YIEST"] } + ''') + } + response { + status 200 + body( + ingredients: [ + [type: 'YIEST', quantity: 200] + ] + ) + } +} \ No newline at end of file diff --git a/src/main/java/pl/devoxx/aggregatr/aggregation/IngredientsAggregator.java b/src/main/java/pl/devoxx/aggregatr/aggregation/IngredientsAggregator.java index 1e35a8c..0caf6dc 100644 --- a/src/main/java/pl/devoxx/aggregatr/aggregation/IngredientsAggregator.java +++ b/src/main/java/pl/devoxx/aggregatr/aggregation/IngredientsAggregator.java @@ -14,6 +14,7 @@ import pl.devoxx.aggregatr.aggregation.model.Ingredient; import pl.devoxx.aggregatr.aggregation.model.IngredientType; import pl.devoxx.aggregatr.aggregation.model.Ingredients; +import pl.devoxx.aggregatr.aggregation.model.Order; import java.lang.invoke.MethodHandles; import java.util.Arrays; @@ -51,14 +52,14 @@ private String getMetricName(IngredientType ingredientType) { return "ingredients." + ingredientType.toString().toLowerCase(); } - Ingredients fetchIngredients() { - final List> futures = ingredientsProperties - .getListOfServiceNames() + Ingredients fetchIngredients(Order order) { + List> futures = ingredientsProperties + .getListOfServiceNames(order) .stream() .map(ingredientHarvester::harvest) .collect(Collectors.toList()); - final ListenableFuture> allDoneFuture = Futures.allAsList(futures); - final List allIngredients = Futures.getUnchecked(allDoneFuture); + ListenableFuture> allDoneFuture = Futures.allAsList(futures); + List allIngredients = Futures.getUnchecked(allDoneFuture); allIngredients.forEach(this::updateIngredientCache); return getIngredientsStatus(); } diff --git a/src/main/java/pl/devoxx/aggregatr/aggregation/IngredientsController.java b/src/main/java/pl/devoxx/aggregatr/aggregation/IngredientsController.java index 9602c99..1e92578 100644 --- a/src/main/java/pl/devoxx/aggregatr/aggregation/IngredientsController.java +++ b/src/main/java/pl/devoxx/aggregatr/aggregation/IngredientsController.java @@ -2,13 +2,16 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import pl.devoxx.aggregatr.aggregation.model.Ingredients; +import pl.devoxx.aggregatr.aggregation.model.Order; +import pl.devoxx.aggregatr.aggregation.model.Version; @RestController -@RequestMapping("/ingredients") +@RequestMapping(value = "/ingredients", consumes = Version.V1, produces = MediaType.APPLICATION_JSON_VALUE) public class IngredientsController { private final IngredientsAggregator ingredientsAggregator; @@ -18,9 +21,9 @@ public IngredientsController(IngredientsAggregator ingredientsAggregator) { this.ingredientsAggregator = ingredientsAggregator; } - @RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET) - public Ingredients distributeIngredients() { - return ingredientsAggregator.fetchIngredients(); + @RequestMapping(method = RequestMethod.POST) + public Ingredients distributeIngredients(@RequestBody Order order) { + return ingredientsAggregator.fetchIngredients(order); } } diff --git a/src/main/java/pl/devoxx/aggregatr/aggregation/IngredientsProperties.java b/src/main/java/pl/devoxx/aggregatr/aggregation/IngredientsProperties.java index 87d7721..825845f 100644 --- a/src/main/java/pl/devoxx/aggregatr/aggregation/IngredientsProperties.java +++ b/src/main/java/pl/devoxx/aggregatr/aggregation/IngredientsProperties.java @@ -1,20 +1,33 @@ package pl.devoxx.aggregatr.aggregation; -import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableMap; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; +import pl.devoxx.aggregatr.aggregation.model.IngredientType; +import pl.devoxx.aggregatr.aggregation.model.Order; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @ConfigurationProperties("ingredients") @Data public class IngredientsProperties { - private String serviceNames = "chmieleo,slodeo,wodeo,drozdzeo"; + private Map serviceNames = ImmutableMap.builder() + .put(IngredientType.WATER, "wodeo") + .put(IngredientType.MALT, "slodeo") + .put(IngredientType.HOP, "chmieleo") + .put(IngredientType.YIEST, "drozdzeo") + .build(); private String rootUrl = "http://localhost:8030/"; private Integer threshold = 1000; - public List getListOfServiceNames() { - return Splitter.on(',').omitEmptyStrings().trimResults().splitToList(serviceNames); + public List getListOfServiceNames(Order order) { + return serviceNames.entrySet() + .stream() + .filter((entry -> order.getItems().contains(entry.getKey()))) + .map((Map.Entry::getValue)) + .collect(Collectors.toList()); } } diff --git a/src/main/java/pl/devoxx/aggregatr/aggregation/model/Order.java b/src/main/java/pl/devoxx/aggregatr/aggregation/model/Order.java new file mode 100644 index 0000000..448b375 --- /dev/null +++ b/src/main/java/pl/devoxx/aggregatr/aggregation/model/Order.java @@ -0,0 +1,11 @@ +package pl.devoxx.aggregatr.aggregation.model; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +@Data +public class Order { + private List items = new ArrayList<>(); +} diff --git a/src/main/java/pl/devoxx/aggregatr/aggregation/model/Version.java b/src/main/java/pl/devoxx/aggregatr/aggregation/model/Version.java new file mode 100644 index 0000000..398f79f --- /dev/null +++ b/src/main/java/pl/devoxx/aggregatr/aggregation/model/Version.java @@ -0,0 +1,5 @@ +package pl.devoxx.aggregatr.aggregation.model; + +public class Version { + public static final String V1 = "application/vnd.pl.devoxx.aggregatr.v1+json"; +} diff --git a/src/test/groovy/pl/devoxx/aggregatr/acceptance/AcceptanceSpec.groovy b/src/test/groovy/pl/devoxx/aggregatr/acceptance/AcceptanceSpec.groovy index b371e2b..330aa1b 100644 --- a/src/test/groovy/pl/devoxx/aggregatr/acceptance/AcceptanceSpec.groovy +++ b/src/test/groovy/pl/devoxx/aggregatr/acceptance/AcceptanceSpec.groovy @@ -1,12 +1,12 @@ package pl.devoxx.aggregatr.acceptance - import groovy.json.JsonSlurper import org.springframework.test.context.ContextConfiguration import org.springframework.test.web.servlet.MvcResult +import pl.devoxx.aggregatr.aggregation.model.Version import pl.devoxx.aggregatr.base.MicroserviceMvcWiremockSpec import static java.net.URI.create -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print @ContextConfiguration @@ -20,7 +20,11 @@ class AcceptanceSpec extends MicroserviceMvcWiremockSpec { } private MvcResult getting_ingredients() { - return mockMvc.perform(get(create('/ingredients'))).andDo(print()).andReturn() + return mockMvc.perform(post(create('/ingredients')) + .header('Content-Type', Version.V1) + .content('{"items":["WATER","HOP","YIEST","MALT"]}')) + .andDo(print()) + .andReturn() } private void aggregated_ingredients_are_present(MvcResult result) { diff --git a/src/test/groovy/pl/devoxx/aggregatr/aggregation/BaseMockMvcSpec.groovy b/src/test/groovy/pl/devoxx/aggregatr/aggregation/BaseMockMvcSpec.groovy index c61ee90..fadc6b3 100644 --- a/src/test/groovy/pl/devoxx/aggregatr/aggregation/BaseMockMvcSpec.groovy +++ b/src/test/groovy/pl/devoxx/aggregatr/aggregation/BaseMockMvcSpec.groovy @@ -1,12 +1,14 @@ package pl.devoxx.aggregatr.aggregation import com.jayway.restassured.module.mockmvc.RestAssuredMockMvc import pl.devoxx.aggregatr.aggregation.model.Ingredient -import pl.devoxx.aggregatr.aggregation.model.IngredientType import pl.devoxx.aggregatr.aggregation.model.Ingredients +import pl.devoxx.aggregatr.aggregation.model.Order import spock.lang.Specification abstract class BaseMockMvcSpec extends Specification { + protected static final int QUANTITY = 200 + IngredientsAggregator ingredientsAggregator = Stub() def setup() { @@ -15,12 +17,9 @@ abstract class BaseMockMvcSpec extends Specification { } void setupMocks() { - ingredientsAggregator.fetchIngredients() >> new Ingredients([ - new Ingredient(IngredientType.MALT, 100), - new Ingredient(IngredientType.WATER, 200), - new Ingredient(IngredientType.HOP, 300), - new Ingredient(IngredientType.YIEST, 400) - ]) + ingredientsAggregator.fetchIngredients(_) >> { Order order -> + return new Ingredients(order.items.collect { new Ingredient(it, QUANTITY)}) + } } } diff --git a/src/test/resources/application-test.yaml b/src/test/resources/application-test.yaml index db6dcd9..4889dc4 100644 --- a/src/test/resources/application-test.yaml +++ b/src/test/resources/application-test.yaml @@ -5,7 +5,4 @@ stubrunner.stubs: group: com.ofg module: stub-runner-examples -stubrunner.work-offline: true - -ingredients: - serviceNames: chmieleo,slodeo,wodeo,drozdzeo \ No newline at end of file +stubrunner.work-offline: true \ No newline at end of file