diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml b/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml index 3d8c40afdd..84dc2a6ca9 100644 --- a/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml @@ -44,6 +44,10 @@ org.springframework.cloud spring-cloud-starter-zipkin + + org.springframework.cloud + spring-cloud-starter-feign + diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java index 16aae66cab..10ed66bfd4 100644 --- a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java +++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java @@ -1,5 +1,7 @@ package com.baeldung.spring.cloud.bootstrap.gateway; +import com.baeldung.spring.cloud.bootstrap.gateway.client.book.BooksClient; +import com.baeldung.spring.cloud.bootstrap.gateway.client.rating.RatingsClient; import com.netflix.appinfo.InstanceInfo; import com.netflix.discovery.EurekaClient; import org.springframework.beans.factory.annotation.Autowired; @@ -8,6 +10,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +import org.springframework.cloud.netflix.feign.EnableFeignClients; import org.springframework.cloud.netflix.ribbon.RibbonClientSpecification; import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @@ -16,6 +19,8 @@ import org.springframework.cloud.sleuth.zipkin.HttpZipkinSpanReporter; import org.springframework.cloud.sleuth.zipkin.ZipkinProperties; import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.FilterType; import org.springframework.web.client.RestTemplate; import zipkin.Span; @@ -25,6 +30,7 @@ import java.util.List; @SpringBootApplication @EnableZuulProxy @EnableEurekaClient +@EnableFeignClients public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/book/Book.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/book/Book.java new file mode 100644 index 0000000000..d6a4d9269b --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/book/Book.java @@ -0,0 +1,46 @@ +package com.baeldung.spring.cloud.bootstrap.gateway.client.book; + +import com.baeldung.spring.cloud.bootstrap.gateway.client.rating.Rating; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Book { + private Long id; + private String author; + private String title; + private List ratings; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public List getRatings() { + return ratings; + } + + public void setRatings(List ratings) { + this.ratings = ratings; + } +} diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/book/BooksClient.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/book/BooksClient.java new file mode 100644 index 0000000000..beba760f10 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/book/BooksClient.java @@ -0,0 +1,10 @@ +package com.baeldung.spring.cloud.bootstrap.gateway.client.book; + +import org.springframework.cloud.netflix.feign.FeignClient; +import org.springframework.web.bind.annotation.*; + +@FeignClient(value = "book-service") +public interface BooksClient { + @RequestMapping(method = RequestMethod.GET, value="/books/{bookId}") + Book getBookById(@PathVariable("bookId") Long bookId); +} diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/rating/Rating.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/rating/Rating.java new file mode 100644 index 0000000000..21f9db2d98 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/rating/Rating.java @@ -0,0 +1,34 @@ +package com.baeldung.spring.cloud.bootstrap.gateway.client.rating; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Rating { + private Long id; + private Long bookId; + private int stars; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getBookId() { + return bookId; + } + + public void setBookId(Long bookId) { + this.bookId = bookId; + } + + public int getStars() { + return stars; + } + + public void setStars(int stars) { + this.stars = stars; + } +} diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/rating/RatingsClient.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/rating/RatingsClient.java new file mode 100644 index 0000000000..e82202e5a7 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/rating/RatingsClient.java @@ -0,0 +1,15 @@ +package com.baeldung.spring.cloud.bootstrap.gateway.client.rating; + +import org.springframework.cloud.netflix.feign.FeignClient; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.List; + +@FeignClient(value = "rating-service") +public interface RatingsClient { + @RequestMapping(method = RequestMethod.GET, value="/ratings") + List getRatingsByBookId(@RequestParam("bookId") Long bookId, @RequestHeader("Cookie") String session); +} diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/controller/CombinedController.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/controller/CombinedController.java new file mode 100644 index 0000000000..f04991f81d --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/controller/CombinedController.java @@ -0,0 +1,32 @@ +package com.baeldung.spring.cloud.bootstrap.gateway.controller; + +import com.baeldung.spring.cloud.bootstrap.gateway.client.book.Book; +import com.baeldung.spring.cloud.bootstrap.gateway.client.book.BooksClient; +import com.baeldung.spring.cloud.bootstrap.gateway.client.rating.Rating; +import com.baeldung.spring.cloud.bootstrap.gateway.client.rating.RatingsClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/combined") +public class CombinedController { + + private final BooksClient booksClient; + private final RatingsClient ratingsClient; + + @Autowired + public CombinedController(BooksClient booksClient, RatingsClient ratingsClient) { + this.booksClient = booksClient; + this.ratingsClient = ratingsClient; + } + + @GetMapping + public Book getCombinedResponse(@RequestParam Long bookId, @CookieValue("SESSION") String session){ + Book book = booksClient.getBookById(bookId); + List ratings = ratingsClient.getRatingsByBookId(bookId, "SESSION="+session); + book.setRatings(ratings); + return book; + } +} diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/test/java/com/baeldung/spring/cloud/bootstrap/gateway/LiveTest.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/test/java/com/baeldung/spring/cloud/bootstrap/gateway/LiveTest.java index 04ddc0ee7a..2bef67934b 100644 --- a/spring-cloud/spring-cloud-bootstrap/gateway/src/test/java/com/baeldung/spring/cloud/bootstrap/gateway/LiveTest.java +++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/test/java/com/baeldung/spring/cloud/bootstrap/gateway/LiveTest.java @@ -1,5 +1,7 @@ package com.baeldung.spring.cloud.bootstrap.gateway; +import com.baeldung.spring.cloud.bootstrap.gateway.client.book.Book; +import com.baeldung.spring.cloud.bootstrap.gateway.client.rating.Rating; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import io.restassured.RestAssured; import io.restassured.authentication.FormAuthConfig; @@ -80,7 +82,9 @@ public class LiveTest { @Test public void whenAddnewRating_thenSuccess() { - final Rating rating = new Rating(1L, 4); + final Rating rating = new Rating(); + rating.setBookId(1L); + rating.setStars(4); // request the protected resource final Response ratingResponse = RestAssured.given() @@ -98,7 +102,9 @@ public class LiveTest { @Test public void whenAddnewBook_thenSuccess() { - final Book book = new Book("Baeldung", "How to spring cloud"); + final Book book = new Book(); + book.setTitle("How to spring cloud"); + book.setAuthor("Baeldung"); // request the protected resource final Response bookResponse = RestAssured.given() @@ -115,83 +121,17 @@ public class LiveTest { } - @JsonIgnoreProperties(ignoreUnknown = true) - public static class Book { - - private Long id; - private String author; - private String title; - - public Book() { - } - - public Book(String author, String title) { - this.author = author; - this.title = title; - } - - public String getAuthor() { - return author; - } - - public void setAuthor(String author) { - this.author = author; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } + @Test + public void accessCombinedEndpoint() { + final Response response = RestAssured.given() + .auth() + .form("user", "password", formConfig) + .get(ROOT_URI + "/combined?bookId=1"); + Assert.assertEquals(HttpStatus.OK.value(), response.getStatusCode()); + Assert.assertNotNull(response.getBody()); + final Book result = response.as(Book.class); + Assert.assertEquals(new Long(1), result.getId()); + Assert.assertNotNull(result.getRatings()); + Assert.assertTrue(result.getRatings().size() > 0); } - - @JsonIgnoreProperties(ignoreUnknown = true) - public static class Rating { - private Long id; - private Long bookId; - private int stars; - - public Rating() { - } - - public Rating(Long bookId, int stars) { - this.bookId = bookId; - this.stars = stars; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public Long getBookId() { - return bookId; - } - - public void setBookId(Long bookId) { - this.bookId = bookId; - } - - public int getStars() { - return stars; - } - - public void setStars(int stars) { - this.stars = stars; - } - } - } \ No newline at end of file