diff --git a/spring-petclinic-api-gateway/pom.xml b/spring-petclinic-api-gateway/pom.xml index 3a8cab7c282b98d25d45bc7dc8fff9c03fb8ac84..6c63f47722fe56bcdf7d37c2039e6adceed43367 100644 --- a/spring-petclinic-api-gateway/pom.xml +++ b/spring-petclinic-api-gateway/pom.xml @@ -70,7 +70,11 @@ <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> - + <!-- Third parties --> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + </dependency> </dependencies> <build> diff --git a/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/ApiGatewayApplication.java b/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/ApiGatewayApplication.java index ed03d9940fff8c76544c08ba7a42c81383a41e2d..984884e11091e73dc8864a347c8b92e9aaf3e52a 100644 --- a/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/ApiGatewayApplication.java +++ b/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/ApiGatewayApplication.java @@ -3,14 +3,23 @@ package org.springframework.samples.petclinic.api; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; +import org.springframework.context.annotation.Bean; +import org.springframework.web.client.RestTemplate; @EnableZuulProxy @EnableDiscoveryClient @SpringBootApplication public class ApiGatewayApplication { - public static void main(String[] args) { - SpringApplication.run(ApiGatewayApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(ApiGatewayApplication.class, args); + } + + @Bean + @LoadBalanced + RestTemplate loadBalancedRestTemplate() { + return new RestTemplate(); + } } diff --git a/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/application/CustomersServiceClient.java b/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/application/CustomersServiceClient.java new file mode 100644 index 0000000000000000000000000000000000000000..30bf8c8ffed795c0dfb2497d7abedb08f57fdd15 --- /dev/null +++ b/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/application/CustomersServiceClient.java @@ -0,0 +1,20 @@ +package org.springframework.samples.petclinic.api.application; + +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +/** + * @author Maciej Szarlinski + */ +@Component +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class CustomersServiceClient { + + private final RestTemplate loadBalancedRestTemplate; + + public OwnerDetails getOwner(final int ownerId) { + return loadBalancedRestTemplate.getForObject("http://customers-service/owners/{ownerId}", OwnerDetails.class, ownerId); + } +} diff --git a/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/application/OwnerDetails.java b/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/application/OwnerDetails.java new file mode 100644 index 0000000000000000000000000000000000000000..40357482f0909fc9419e75908bda26da6f32f379 --- /dev/null +++ b/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/application/OwnerDetails.java @@ -0,0 +1,37 @@ +package org.springframework.samples.petclinic.api.application; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.stream.Collectors.toList; + +/** + * @author Maciej Szarlinski + */ +@Data +public class OwnerDetails { + + private final int id; + + private final String firstName; + + private final String lastName; + + private final String address; + + private final String city; + + private final String telephone; + + private final List<PetDetails> pets = new ArrayList<>(); + + @JsonIgnore + public List<Integer> getPetIds() { + return pets.stream() + .map(PetDetails::getId) + .collect(toList()); + } +} diff --git a/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/application/PetDetails.java b/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/application/PetDetails.java new file mode 100644 index 0000000000000000000000000000000000000000..53c9055dd76c6af2c144afffd2dcedcc85ad13d1 --- /dev/null +++ b/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/application/PetDetails.java @@ -0,0 +1,24 @@ +package org.springframework.samples.petclinic.api.application; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Maciej Szarlinski + */ +@Data +public class PetDetails { + + private final int id; + + private final String name; + + private final String birthDate; + + private final PetType type; + + private final List<VisitDetails> visits = new ArrayList<>(); + +} diff --git a/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/application/PetType.java b/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/application/PetType.java new file mode 100644 index 0000000000000000000000000000000000000000..fe956fc13544e3803361c3ead582121c82689357 --- /dev/null +++ b/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/application/PetType.java @@ -0,0 +1,12 @@ +package org.springframework.samples.petclinic.api.application; + +import lombok.Data; + +/** + * @author Maciej Szarlinski + */ +@Data +public class PetType { + + private final String name; +} diff --git a/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/application/VisitDetails.java b/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/application/VisitDetails.java new file mode 100644 index 0000000000000000000000000000000000000000..200e1c51448175c22923e39b88201550612282b1 --- /dev/null +++ b/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/application/VisitDetails.java @@ -0,0 +1,18 @@ +package org.springframework.samples.petclinic.api.application; + +import lombok.Data; + +/** + * @author Maciej Szarlinski + */ +@Data +public class VisitDetails { + + private final int id; + + private final int petId; + + private final String date; + + private final String description; +} diff --git a/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/application/VisitsServiceClient.java b/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/application/VisitsServiceClient.java new file mode 100644 index 0000000000000000000000000000000000000000..2539a0647865810531ebf810fa9cfe129351cc9a --- /dev/null +++ b/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/application/VisitsServiceClient.java @@ -0,0 +1,33 @@ +package org.springframework.samples.petclinic.api.application; + +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import java.util.List; +import java.util.Map; + +import static java.util.stream.Collectors.groupingBy; + +/** + * @author Maciej Szarlinski + */ +@Component +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class VisitsServiceClient { + + private final RestTemplate loadBalancedRestTemplate; + + public Map<Integer, List<VisitDetails>> getVisitsForPets(final List<Integer> petIds, final int ownerId) { + //TODO: expose batch interface in Visit Service + final ParameterizedTypeReference<List<VisitDetails>> responseType = new ParameterizedTypeReference<List<VisitDetails>>() { + }; + return petIds.parallelStream() + .flatMap(petId -> loadBalancedRestTemplate.exchange("http://visits-service/owners/{ownerId}/pets/{petId}/visits", HttpMethod.GET, null, + responseType, ownerId, petId).getBody().stream()) + .collect(groupingBy(VisitDetails::getPetId)); + } +} diff --git a/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/boundary/web/ApiGatewayController.java b/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/boundary/web/ApiGatewayController.java new file mode 100644 index 0000000000000000000000000000000000000000..02931fd0723b357ee17dd3b6a44a3ec765d61c64 --- /dev/null +++ b/spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/boundary/web/ApiGatewayController.java @@ -0,0 +1,41 @@ +package org.springframework.samples.petclinic.api.boundary.web; + +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.samples.petclinic.api.application.CustomersServiceClient; +import org.springframework.samples.petclinic.api.application.OwnerDetails; +import org.springframework.samples.petclinic.api.application.VisitDetails; +import org.springframework.samples.petclinic.api.application.VisitsServiceClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static java.util.Collections.emptyList; + +/** + * @author Maciej Szarlinski + */ +@RestController +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class ApiGatewayController { + + private final CustomersServiceClient customersServiceClient; + + private final VisitsServiceClient visitsServiceClient; + + @GetMapping(value = "owners/{ownerId}") + public OwnerDetails getOwnerDetails(final @PathVariable int ownerId) { + final OwnerDetails owner = customersServiceClient.getOwner(ownerId); + supplyVisits(owner, visitsServiceClient.getVisitsForPets(owner.getPetIds(), ownerId)); + return owner; + } + + private void supplyVisits(final OwnerDetails owner, final Map<Integer, List<VisitDetails>> visitsMapping) { + owner.getPets().forEach(pet -> + pet.getVisits().addAll(Optional.ofNullable(visitsMapping.get(pet.getId())).orElse(emptyList()))); + } +} diff --git a/spring-petclinic-customers-service/src/main/java/org/springframework/samples/petclinic/customers/application/OwnerService.java b/spring-petclinic-customers-service/src/main/java/org/springframework/samples/petclinic/customers/application/OwnerService.java index f1505fda180532bcf032e7a5e07d63c3a6e14de9..ac363749e5e00a43fb52080ac7f62dc3e9901d56 100644 --- a/spring-petclinic-customers-service/src/main/java/org/springframework/samples/petclinic/customers/application/OwnerService.java +++ b/spring-petclinic-customers-service/src/main/java/org/springframework/samples/petclinic/customers/application/OwnerService.java @@ -13,7 +13,7 @@ import org.springframework.transaction.annotation.Transactional; import java.util.Collection; /** - * @author mszarlinski on 2016-10-30. + * @author Maciej Szarlinski */ @Service public class OwnerService { diff --git a/spring-petclinic-customers-service/src/main/java/org/springframework/samples/petclinic/customers/application/PetService.java b/spring-petclinic-customers-service/src/main/java/org/springframework/samples/petclinic/customers/application/PetService.java index b1e820f3e7450e47d7f0cd13106e0fcb3f6977a2..54d97ca9230df20763cbe19a0398e92756748512 100644 --- a/spring-petclinic-customers-service/src/main/java/org/springframework/samples/petclinic/customers/application/PetService.java +++ b/spring-petclinic-customers-service/src/main/java/org/springframework/samples/petclinic/customers/application/PetService.java @@ -14,7 +14,7 @@ import java.util.Collection; import java.util.Optional; /** - * @author mszarlinski on 2016-10-30. + * @author Maciej Szarlinski */ @Service public class PetService { diff --git a/spring-petclinic-customers-service/src/test/java/org/springframework/samples/petclinic/customers/boundary/web/pet/PetResourceTest.java b/spring-petclinic-customers-service/src/test/java/org/springframework/samples/petclinic/customers/boundary/web/pet/PetResourceTest.java index f8219d6630f548c5a66a519ffb0e296d8d5cdb6b..0151d114bc066869bd77364b1b2dc9b3b2e20baa 100644 --- a/spring-petclinic-customers-service/src/test/java/org/springframework/samples/petclinic/customers/boundary/web/pet/PetResourceTest.java +++ b/spring-petclinic-customers-service/src/test/java/org/springframework/samples/petclinic/customers/boundary/web/pet/PetResourceTest.java @@ -20,7 +20,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; /** - * @author mszarlinski on 2016-11-05. + * @author Maciej Szarlinski */ @RunWith(SpringRunner.class) @WebMvcTest(PetResource.class) diff --git a/spring-petclinic-monitoring/src/main/java/org/springframework/samples/petclinic/monitoring/Monitored.java b/spring-petclinic-monitoring/src/main/java/org/springframework/samples/petclinic/monitoring/Monitored.java index ab760985a5db26409e8c850f01d9221390cc31c3..42e24a7161bb9da24136d987435eca6ec42f2790 100644 --- a/spring-petclinic-monitoring/src/main/java/org/springframework/samples/petclinic/monitoring/Monitored.java +++ b/spring-petclinic-monitoring/src/main/java/org/springframework/samples/petclinic/monitoring/Monitored.java @@ -6,7 +6,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * @author mszarlinski on 2016-11-09. + * @author Maciej Szarlinski */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) diff --git a/spring-petclinic-monitoring/src/main/java/org/springframework/samples/petclinic/monitoring/MonitoringConfig.java b/spring-petclinic-monitoring/src/main/java/org/springframework/samples/petclinic/monitoring/MonitoringConfig.java index 5fc83365ec8739427f0cc300507cc43a7dd40914..e322fd16330b64aea4fb386e5171135c09bffb76 100644 --- a/spring-petclinic-monitoring/src/main/java/org/springframework/samples/petclinic/monitoring/MonitoringConfig.java +++ b/spring-petclinic-monitoring/src/main/java/org/springframework/samples/petclinic/monitoring/MonitoringConfig.java @@ -5,7 +5,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; /** - * @author mszarlinski on 2016-11-09. + * @author Maciej Szarlinski */ @Configuration @EnableAspectJAutoProxy diff --git a/spring-petclinic-tracing-server/pom.xml b/spring-petclinic-tracing-server/pom.xml index f6197cf91c976cfc75ffd1b7296ff6b0f2330cbb..f8dd04fbaf9980684f15cedb0241bccae9b23484 100644 --- a/spring-petclinic-tracing-server/pom.xml +++ b/spring-petclinic-tracing-server/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> - <groupId>org.springframework.samples.petclinic.visits</groupId> - <artifactId>spring-petclinic-zipkin-server</artifactId> + <groupId>org.springframework.samples.petclinic.tracing</groupId> + <artifactId>spring-petclinic-tracing-server</artifactId> <version>1.4.2</version> <packaging>jar</packaging> <description>Zipkin server with UI</description> diff --git a/spring-petclinic-ui/src/scripts/owner-details/owner-details.controller.js b/spring-petclinic-ui/src/scripts/owner-details/owner-details.controller.js index 2dd8f63372fb3e75c007e92d648fc2e75fae7669..d164378dc96668c512ec501496ee3938853cbde2 100644 --- a/spring-petclinic-ui/src/scripts/owner-details/owner-details.controller.js +++ b/spring-petclinic-ui/src/scripts/owner-details/owner-details.controller.js @@ -4,7 +4,7 @@ angular.module('ownerDetails') .controller('OwnerDetailsController', ['$http', '$stateParams', function ($http, $stateParams) { var self = this; - $http.get('api/customer/owners/' + $stateParams.ownerId).then(function (resp) { + $http.get('api/gateway/owners/' + $stateParams.ownerId).then(function (resp) { self.owner = resp.data; }); }]); diff --git a/spring-petclinic-ui/src/scripts/owner-details/owner-details.template.html b/spring-petclinic-ui/src/scripts/owner-details/owner-details.template.html index 7c93a518d4eb6abe6450a6dfc4365988494bb5b7..ed2810f9caef70346a734b3d560ad9da0713d59f 100644 --- a/spring-petclinic-ui/src/scripts/owner-details/owner-details.template.html +++ b/spring-petclinic-ui/src/scripts/owner-details/owner-details.template.html @@ -43,7 +43,6 @@ </td> <td valign="top"> <table class="table-condensed"> - <!-- TODO: no visits in pet resource --> <thead> <tr> <th>Visit Date</th> diff --git a/spring-petclinic-vets-service/pom.xml b/spring-petclinic-vets-service/pom.xml index b5c2c4c7410abb4ac58c4e907d3a5c58d0a261a9..b8796ace30b2fdc222abab6c060cb852fc9932a6 100644 --- a/spring-petclinic-vets-service/pom.xml +++ b/spring-petclinic-vets-service/pom.xml @@ -59,6 +59,10 @@ </dependency> <!-- Third parties--> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + </dependency> <dependency> <groupId>javax.cache</groupId> <artifactId>cache-api</artifactId> diff --git a/spring-petclinic-vets-service/src/main/java/org/springframework/samples/petclinic/vets/application/VetService.java b/spring-petclinic-vets-service/src/main/java/org/springframework/samples/petclinic/vets/application/VetService.java index 2227eab65dc892e69bdd037cf0f2bfd17d96d6ce..4dab7955541e0b32f8d8343ef064bd902c112ae9 100644 --- a/spring-petclinic-vets-service/src/main/java/org/springframework/samples/petclinic/vets/application/VetService.java +++ b/spring-petclinic-vets-service/src/main/java/org/springframework/samples/petclinic/vets/application/VetService.java @@ -11,7 +11,7 @@ import javax.cache.annotation.CacheResult; import java.util.Collection; /** - * @author mszarlinski on 2016-10-30. + * @author Maciej Szarlinski */ @Service public class VetService { diff --git a/spring-petclinic-vets-service/src/main/java/org/springframework/samples/petclinic/vets/infrastructure/config/VetsProperties.java b/spring-petclinic-vets-service/src/main/java/org/springframework/samples/petclinic/vets/infrastructure/config/VetsProperties.java index 679de115bac1d992b82b9279aacab4be579c1525..33df8f8f92ee448c49ac1e84df5fabc6438d8fe9 100644 --- a/spring-petclinic-vets-service/src/main/java/org/springframework/samples/petclinic/vets/infrastructure/config/VetsProperties.java +++ b/spring-petclinic-vets-service/src/main/java/org/springframework/samples/petclinic/vets/infrastructure/config/VetsProperties.java @@ -1,46 +1,25 @@ package org.springframework.samples.petclinic.vets.infrastructure.config; +import lombok.Data; + import org.springframework.boot.context.properties.ConfigurationProperties; /** * Typesafe custom configuration. * - * @author mszarlinski on 2016-11-08. + * @author Maciej Szarlinski */ -//TODO: Lombok +@Data @ConfigurationProperties(prefix = "vets") public class VetsProperties { private Cache cache; + @Data public static class Cache { private int ttl; private int heapSize; - - public int getTtl() { - return ttl; - } - - public void setTtl(int ttl) { - this.ttl = ttl; - } - - public int getHeapSize() { - return heapSize; - } - - public void setHeapSize(int heapSize) { - this.heapSize = heapSize; - } - } - - public Cache getCache() { - return cache; - } - - public void setCache(Cache cache) { - this.cache = cache; } } diff --git a/spring-petclinic-vets-service/src/test/java/org/springframework/samples/petclinic/vets/web/boundary/VetResourceTest.java b/spring-petclinic-vets-service/src/test/java/org/springframework/samples/petclinic/vets/web/boundary/VetResourceTest.java index 957f8121f916d04989739b2d0fd5e9f5cec13034..60172bf097ff6ca483a8cb0637908a835fbb8f14 100644 --- a/spring-petclinic-vets-service/src/test/java/org/springframework/samples/petclinic/vets/web/boundary/VetResourceTest.java +++ b/spring-petclinic-vets-service/src/test/java/org/springframework/samples/petclinic/vets/web/boundary/VetResourceTest.java @@ -19,7 +19,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** - * @author mszarlinski on 2016-11-05. + * @author Maciej Szarlinski */ @RunWith(SpringRunner.class) @WebMvcTest(VetResource.class) diff --git a/spring-petclinic-visits-service/src/main/java/org/springframework/samples/petclinic/visits/application/VisitService.java b/spring-petclinic-visits-service/src/main/java/org/springframework/samples/petclinic/visits/application/VisitService.java index e0c065208ec813c8457c6a20b8007edbc1fc78e8..cdb066236d5f715df771ce44524e340cd1cb792c 100644 --- a/spring-petclinic-visits-service/src/main/java/org/springframework/samples/petclinic/visits/application/VisitService.java +++ b/spring-petclinic-visits-service/src/main/java/org/springframework/samples/petclinic/visits/application/VisitService.java @@ -12,7 +12,7 @@ import org.springframework.transaction.annotation.Transactional; import java.util.List; /** - * @author mszarlinski on 2016-10-30. + * @author Maciej Szarlinski */ @Service public class VisitService { diff --git a/spring-petclinic-visits-service/src/main/java/org/springframework/samples/petclinic/visits/boundary/web/visit/VisitResource.java b/spring-petclinic-visits-service/src/main/java/org/springframework/samples/petclinic/visits/boundary/web/VisitResource.java similarity index 99% rename from spring-petclinic-visits-service/src/main/java/org/springframework/samples/petclinic/visits/boundary/web/visit/VisitResource.java rename to spring-petclinic-visits-service/src/main/java/org/springframework/samples/petclinic/visits/boundary/web/VisitResource.java index e67519ea19518a31f04457812e8e0012996082b0..b0b9a7d1e832c70559772a45399a002fc6051272 100644 --- a/spring-petclinic-visits-service/src/main/java/org/springframework/samples/petclinic/visits/boundary/web/visit/VisitResource.java +++ b/spring-petclinic-visits-service/src/main/java/org/springframework/samples/petclinic/visits/boundary/web/VisitResource.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.samples.petclinic.visits.boundary.web.visit; +package org.springframework.samples.petclinic.visits.boundary.web; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus;