diff --git a/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/AlbumClient.java b/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/AlbumClient.java new file mode 100644 index 0000000000..b1db2dbcab --- /dev/null +++ b/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/AlbumClient.java @@ -0,0 +1,15 @@ +package com.baeldung.cloud.openfeign.client; + +import com.baeldung.cloud.openfeign.model.Album; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; + +@FeignClient(name = "albumClient", url = "https://jsonplaceholder.typicode.com/albums/") +public interface AlbumClient { + @GetMapping(value = "/{id}") + Album getAlbumById(@PathVariable(value = "id") Integer id); + + @GetMapping(value = "/{id}") + Album getAlbumByIdAndDynamicUrl(@PathVariable(name = "id") Integer id); +} diff --git a/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/PostClient.java b/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/PostClient.java new file mode 100644 index 0000000000..e8e773b6a1 --- /dev/null +++ b/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/PostClient.java @@ -0,0 +1,12 @@ +package com.baeldung.cloud.openfeign.client; + +import com.baeldung.cloud.openfeign.model.Post; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; + +@FeignClient(name = "postClient", url = "${spring.cloud.openfeign.client.config.postClient.url}") +public interface PostClient { + @GetMapping(value = "/{id}") + Post getPostById(@PathVariable(value = "id") Integer id); +} diff --git a/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/TodoClient.java b/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/TodoClient.java new file mode 100644 index 0000000000..c768ef6b5f --- /dev/null +++ b/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/TodoClient.java @@ -0,0 +1,13 @@ +package com.baeldung.cloud.openfeign.client; + +import com.baeldung.cloud.openfeign.model.Todo; +import feign.RequestLine; +import org.springframework.cloud.openfeign.FeignClient; + +import java.net.URI; + +@FeignClient(name = "todoClient") +public interface TodoClient { + @RequestLine(value = "GET") + Todo getTodoById(URI uri); +} diff --git a/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/DynamicUrlInterceptor.java b/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/DynamicUrlInterceptor.java new file mode 100644 index 0000000000..286426edb3 --- /dev/null +++ b/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/DynamicUrlInterceptor.java @@ -0,0 +1,23 @@ +package com.baeldung.cloud.openfeign.config; + +import feign.RequestInterceptor; +import feign.RequestTemplate; + +import java.util.function.Supplier; + +public class DynamicUrlInterceptor implements RequestInterceptor { + + private final Supplier urlSupplier; + + public DynamicUrlInterceptor(Supplier urlSupplier) { + this.urlSupplier = urlSupplier; + } + + @Override + public void apply(RequestTemplate template) { + String url = urlSupplier.get(); + if (url != null) { + template.target(url); + } + } +} diff --git a/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/controller/ConfigureFeignUrlController.java b/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/controller/ConfigureFeignUrlController.java new file mode 100644 index 0000000000..ca49bca605 --- /dev/null +++ b/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/controller/ConfigureFeignUrlController.java @@ -0,0 +1,82 @@ +package com.baeldung.cloud.openfeign.controller; + +import com.baeldung.cloud.openfeign.config.DynamicUrlInterceptor; +import com.baeldung.cloud.openfeign.client.AlbumClient; +import com.baeldung.cloud.openfeign.client.PostClient; +import com.baeldung.cloud.openfeign.client.TodoClient; +import com.baeldung.cloud.openfeign.model.Album; +import com.baeldung.cloud.openfeign.model.Post; +import com.baeldung.cloud.openfeign.model.Todo; +import feign.Feign; +import feign.Target; +import feign.codec.Decoder; +import feign.codec.Encoder; +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.http.HttpMessageConverters; +import org.springframework.cloud.openfeign.FeignClientsConfiguration; +import org.springframework.cloud.openfeign.support.HttpMessageConverterCustomizer; +import org.springframework.cloud.openfeign.support.SpringDecoder; +import org.springframework.cloud.openfeign.support.SpringEncoder; +import org.springframework.cloud.openfeign.support.SpringMvcContract; +import org.springframework.context.annotation.Import; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +import java.net.URI; + +@RestController +@Import(FeignClientsConfiguration.class) +public class ConfigureFeignUrlController { + private final AlbumClient albumClient; + + private final PostClient postClient; + + private final TodoClient todoClient; + + private final ObjectFactory messageConverters; + + private final ObjectProvider customizers; + + public ConfigureFeignUrlController(AlbumClient albumClient, + PostClient postClient, + Decoder decoder, + Encoder encoder, + ObjectFactory messageConverters, ObjectProvider customizers) { + this.albumClient = albumClient; + this.postClient = postClient; + this.messageConverters = messageConverters; + this.customizers = customizers; + this.todoClient = Feign.builder().encoder(encoder).decoder(decoder).target(Target.EmptyTarget.create(TodoClient.class)); + } + + @GetMapping(value = "albums/{id}") + public Album getAlbumById(@PathVariable(value = "id") Integer id) { + return albumClient.getAlbumById(id); + } + + @GetMapping(value = "posts/{id}") + public Post getPostById(@PathVariable(value = "id") Integer id) { + return postClient.getPostById(id); + } + + @GetMapping(value = "todos/{id}") + public Todo getTodoById(@PathVariable(value = "id") Integer id) { + return todoClient.getTodoById(URI.create("https://jsonplaceholder.typicode.com/todos/" + id)); + } + + @GetMapping(value = "/dynamicAlbums/{id}") + public Album getAlbumByIdAndDynamicUrl(@PathVariable(value = "id") Integer id) { + AlbumClient client = Feign.builder() + .requestInterceptor(new DynamicUrlInterceptor(() -> "https://jsonplaceholder.typicode.com/albums/")) + .contract(new SpringMvcContract()) + .encoder(new SpringEncoder(messageConverters)) + .decoder(new SpringDecoder(messageConverters, customizers)) + .target(Target.EmptyTarget.create(AlbumClient.class)); + + return client.getAlbumByIdAndDynamicUrl(id); + } +} + + diff --git a/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Album.java b/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Album.java new file mode 100644 index 0000000000..ae9c01f3b1 --- /dev/null +++ b/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Album.java @@ -0,0 +1,32 @@ +package com.baeldung.cloud.openfeign.model; + +public class Album { + + private Integer id; + private Integer userId; + private String title; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getUserId() { + return userId; + } + + public void setUserId(Integer userId) { + this.userId = userId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } +} diff --git a/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Todo.java b/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Todo.java new file mode 100644 index 0000000000..887a3496c5 --- /dev/null +++ b/spring-cloud-modules/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Todo.java @@ -0,0 +1,40 @@ +package com.baeldung.cloud.openfeign.model; + +public class Todo { + private Integer id; + private Integer userId; + private String title; + private Boolean completed; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getUserId() { + return userId; + } + + public void setUserId(Integer userId) { + this.userId = userId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Boolean getCompleted() { + return completed; + } + + public void setCompleted(Boolean completed) { + this.completed = completed; + } +} diff --git a/spring-cloud-modules/spring-cloud-openfeign/src/main/resources/application.properties b/spring-cloud-modules/spring-cloud-openfeign/src/main/resources/application.properties index a0d9d89934..f4ea32483d 100644 --- a/spring-cloud-modules/spring-cloud-openfeign/src/main/resources/application.properties +++ b/spring-cloud-modules/spring-cloud-openfeign/src/main/resources/application.properties @@ -8,3 +8,5 @@ spring.security.oauth2.client.registration.keycloak.authorization-grant-type=cli spring.security.oauth2.client.registration.keycloak.client-id=payment-app spring.security.oauth2.client.registration.keycloak.client-secret=863e9de4-33d4-4471-b35e-f8d2434385bb spring.security.oauth2.client.provider.keycloak.token-uri=http://localhost:8083/auth/realms/master/protocol/openid-connect/token + +spring.cloud.openfeign.client.config.postClient.url=https://jsonplaceholder.typicode.com/posts/ \ No newline at end of file