Use @LoadBalanced
This commit is contained in:
@ -28,113 +28,8 @@
|
|||||||
<tag />
|
<tag />
|
||||||
<url />
|
<url />
|
||||||
</scm>
|
</scm>
|
||||||
<properties>
|
<properties></properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<dependencies></dependencies>
|
||||||
<java.version>1.8</java.version>
|
|
||||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
|
||||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
|
||||||
<swagger-annotations-version>1.6.3</swagger-annotations-version>
|
|
||||||
<jackson-databind-version>2.17.1</jackson-databind-version>
|
|
||||||
<jackson-version>2.17.1</jackson-version>
|
|
||||||
<jakarta.ws.rs-api-version>4.0.0</jakarta.ws.rs-api-version>
|
|
||||||
<retrofit-version>2.11.0</retrofit-version>
|
|
||||||
<jakarta-annotation-version>2.1.1</jakarta-annotation-version>
|
|
||||||
<beanvalidation-version>3.0.2</beanvalidation-version>
|
|
||||||
<oltu-version>1.0.1</oltu-version>
|
|
||||||
<junit-version>5.10.3</junit-version>
|
|
||||||
<javax-annotation-api.version>1.3.2</javax-annotation-api.version>
|
|
||||||
<jakarta-validation-api.version>3.1.1</jakarta-validation-api.version>
|
|
||||||
<jsr305.version>3.0.2</jsr305.version>
|
|
||||||
</properties>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.swagger</groupId>
|
|
||||||
<artifactId>swagger-annotations</artifactId>
|
|
||||||
<version>${swagger-annotations-version}</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- @Nullable annotation -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.code.findbugs</groupId>
|
|
||||||
<artifactId>jsr305</artifactId>
|
|
||||||
<version>${jsr305.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.squareup.retrofit2</groupId>
|
|
||||||
<artifactId>retrofit</artifactId>
|
|
||||||
<version>${retrofit-version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.squareup.retrofit2</groupId>
|
|
||||||
<artifactId>converter-scalars</artifactId>
|
|
||||||
<version>${retrofit-version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.oltu.oauth2</groupId>
|
|
||||||
<artifactId>org.apache.oltu.oauth2.client</artifactId>
|
|
||||||
<version>${oltu-version}</version>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.apache.oltu.oauth2</groupId>
|
|
||||||
<artifactId>common</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<!-- JSON processing: jackson -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.squareup.retrofit2</groupId>
|
|
||||||
<artifactId>converter-jackson</artifactId>
|
|
||||||
<version>${retrofit-version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
|
||||||
<artifactId>jackson-core</artifactId>
|
|
||||||
<version>${jackson-version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
|
||||||
<artifactId>jackson-annotations</artifactId>
|
|
||||||
<version>${jackson-version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
|
||||||
<artifactId>jackson-databind</artifactId>
|
|
||||||
<version>${jackson-databind-version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
|
||||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
|
||||||
<version>${jackson-version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>jakarta.ws.rs</groupId>
|
|
||||||
<artifactId>jakarta.ws.rs-api</artifactId>
|
|
||||||
<version>${jakarta.ws.rs-api-version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>jakarta.annotation</groupId>
|
|
||||||
<artifactId>jakarta.annotation-api</artifactId>
|
|
||||||
<version>${jakarta-annotation-version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>javax.annotation</groupId>
|
|
||||||
<artifactId>javax.annotation-api</artifactId>
|
|
||||||
<version>${javax-annotation-api.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- https://mvnrepository.com/artifact/jakarta.validation/jakarta.validation-api -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>jakarta.validation</groupId>
|
|
||||||
<artifactId>jakarta.validation-api</artifactId>
|
|
||||||
<version>${jakarta-validation-api.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- test dependencies -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.junit.jupiter</groupId>
|
|
||||||
<artifactId>junit-jupiter-api</artifactId>
|
|
||||||
<version>${junit-version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
@ -151,12 +46,11 @@
|
|||||||
<inputSpec>${project.basedir}/src/main/resources/openapi.json</inputSpec>
|
<inputSpec>${project.basedir}/src/main/resources/openapi.json</inputSpec>
|
||||||
<generatorName>java</generatorName>
|
<generatorName>java</generatorName>
|
||||||
<configOptions>
|
<configOptions>
|
||||||
<library>retrofit2</library>
|
<library>restclient</library>
|
||||||
<apiPackage>com.backend.search.kodik.api</apiPackage>
|
<apiPackage>com.backend.search.kodik.api</apiPackage>
|
||||||
<modelPackage>com.backend.search.kodik.model</modelPackage>
|
<modelPackage>com.backend.search.kodik.model</modelPackage>
|
||||||
<openApiNullable>false</openApiNullable>
|
<openApiNullable>false</openApiNullable>
|
||||||
<useJakartaEe>true</useJakartaEe>
|
<useJakartaEe>true</useJakartaEe>
|
||||||
<serializationLibrary>jackson</serializationLibrary>
|
|
||||||
</configOptions>
|
</configOptions>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
<version>3.5.5</version>
|
<version>3.5.5</version>
|
||||||
<relativePath /> <!-- lookup parent from repository -->
|
<relativePath /> <!-- lookup parent from repository -->
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>com.backend.vue.bff.service</groupId>
|
<groupId>com.backend.vue.bff.service</groupId>
|
||||||
<artifactId>anyame-vue-bff</artifactId>
|
<artifactId>anyame-vue-bff</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
@ -37,22 +38,6 @@
|
|||||||
<logstash-logback-encoder.version>8.1</logstash-logback-encoder.version>
|
<logstash-logback-encoder.version>8.1</logstash-logback-encoder.version>
|
||||||
</properties>
|
</properties>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-cache</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-validation</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
|
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
|
||||||
@ -61,7 +46,6 @@
|
|||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
|
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.squareup.retrofit2</groupId>
|
<groupId>com.squareup.retrofit2</groupId>
|
||||||
<artifactId>converter-jackson</artifactId>
|
<artifactId>converter-jackson</artifactId>
|
||||||
@ -87,7 +71,6 @@
|
|||||||
<artifactId>logstash-logback-encoder</artifactId>
|
<artifactId>logstash-logback-encoder</artifactId>
|
||||||
<version>${logstash-logback-encoder.version}</version>
|
<version>${logstash-logback-encoder.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
|||||||
@ -33,6 +33,7 @@ public class GlobalExceptionHandler {
|
|||||||
"API_CALL_FAILED",
|
"API_CALL_FAILED",
|
||||||
"Failed to communicate with external service: " + e.getMessage(),
|
"Failed to communicate with external service: " + e.getMessage(),
|
||||||
HttpStatus.INTERNAL_SERVER_ERROR.value());
|
HttpStatus.INTERNAL_SERVER_ERROR.value());
|
||||||
|
logger.error("API call failed", e);
|
||||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,66 +1,34 @@
|
|||||||
package com.backend.vue.bff.service.config;
|
package com.backend.vue.bff.service.config;
|
||||||
|
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
|
||||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
|
||||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||||
|
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.web.client.RestClient;
|
||||||
|
|
||||||
import com.backend.search.kodik.ApiClient;
|
import com.backend.search.kodik.ApiClient;
|
||||||
import com.backend.search.kodik.JSON;
|
|
||||||
import com.backend.search.kodik.api.SearchControllerApi;
|
import com.backend.search.kodik.api.SearchControllerApi;
|
||||||
import com.backend.vue.bff.service.factory.AbstractApiFactory;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
|
|
||||||
import retrofit2.Retrofit.Builder;
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableDiscoveryClient
|
@EnableDiscoveryClient
|
||||||
public class SearchApiClientConfiguration {
|
public class SearchApiClientConfiguration {
|
||||||
|
|
||||||
private final DiscoveryClient discoveryClient;
|
@LoadBalanced
|
||||||
|
@Bean
|
||||||
public SearchApiClientConfiguration(DiscoveryClient discoveryClient) {
|
public RestClient.Builder restClientBuilder() {
|
||||||
this.discoveryClient = discoveryClient;
|
return RestClient.builder();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Lazy
|
public ApiClient apiClient() {
|
||||||
public FactoryBean<ApiClient> apiClientFactory() {
|
return new ApiClient(restClientBuilder().build());
|
||||||
return new ApiClientFactoryBean(discoveryClient);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Lazy
|
@Lazy
|
||||||
public SearchControllerApi searchApi(ApiClient apiClient) {
|
public SearchControllerApi searchApi(ApiClient apiClient) {
|
||||||
return apiClient.createService(SearchControllerApi.class);
|
apiClient = apiClient.setBasePath("http://ANYAME-KODIK-SEARCH-BACKEND");
|
||||||
}
|
return new SearchControllerApi(apiClient);
|
||||||
|
|
||||||
private static class ApiClientFactoryBean extends AbstractApiFactory<ApiClient> {
|
|
||||||
public ApiClientFactoryBean(DiscoveryClient discoveryClient) {
|
|
||||||
super(discoveryClient, "ANYAME-KODIK-SEARCH-BACKEND");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getObjectType() {
|
|
||||||
return ApiClient.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ObjectMapper createObjectMapper() {
|
|
||||||
JSON json = new JSON();
|
|
||||||
return json.getMapper();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ApiClient createApiClient() {
|
|
||||||
return new ApiClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void updateAdapterBuilder(ApiClient instance, Builder adapterBuilder) {
|
|
||||||
instance.setAdapterBuilder(adapterBuilder);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,8 +4,8 @@ import java.io.IOException;
|
|||||||
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.backend.vue.bff.service.service.KodikService;
|
import com.backend.vue.bff.service.service.KodikService;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
|
|||||||
@ -1,68 +0,0 @@
|
|||||||
package com.backend.vue.bff.service.factory;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
|
||||||
import org.springframework.cloud.client.ServiceInstance;
|
|
||||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
|
||||||
|
|
||||||
import com.backend.vue.bff.service.exception.ServiceUnavailableException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
|
|
||||||
import retrofit2.Retrofit;
|
|
||||||
import retrofit2.converter.jackson.JacksonConverterFactory;
|
|
||||||
import retrofit2.converter.scalars.ScalarsConverterFactory;
|
|
||||||
|
|
||||||
public abstract class AbstractApiFactory<T> implements FactoryBean<T> {
|
|
||||||
private final DiscoveryClient discoveryClient;
|
|
||||||
private final String serviceId;
|
|
||||||
|
|
||||||
public AbstractApiFactory(DiscoveryClient discoveryClient, String serviceId) {
|
|
||||||
this.discoveryClient = discoveryClient;
|
|
||||||
this.serviceId = serviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T getObject() throws Exception {
|
|
||||||
T client = createApiClient();
|
|
||||||
|
|
||||||
String baseUrl = resolveServiceUrl(serviceId);
|
|
||||||
|
|
||||||
Retrofit.Builder adapterBuilder = new Retrofit.Builder()
|
|
||||||
.baseUrl(baseUrl)
|
|
||||||
.addConverterFactory(ScalarsConverterFactory.create())
|
|
||||||
.addConverterFactory(JacksonConverterFactory.create(createObjectMapper()));
|
|
||||||
|
|
||||||
updateAdapterBuilder(client, adapterBuilder);
|
|
||||||
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSingleton() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String resolveServiceUrl(String serviceName) {
|
|
||||||
List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);
|
|
||||||
|
|
||||||
if (instances.isEmpty()) {
|
|
||||||
throw new ServiceUnavailableException();
|
|
||||||
}
|
|
||||||
|
|
||||||
ServiceInstance instance = instances.get(0);
|
|
||||||
String baseUrl = instance.getUri().toString();
|
|
||||||
|
|
||||||
if (!baseUrl.endsWith("/")) {
|
|
||||||
baseUrl = baseUrl + "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
return baseUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract ObjectMapper createObjectMapper();
|
|
||||||
|
|
||||||
public abstract T createApiClient();
|
|
||||||
|
|
||||||
protected abstract void updateAdapterBuilder(T instance, Retrofit.Builder adapterBuilder);
|
|
||||||
}
|
|
||||||
@ -20,6 +20,6 @@ public class KodikService {
|
|||||||
|
|
||||||
@Cacheable("kodikSearch")
|
@Cacheable("kodikSearch")
|
||||||
public KodikResponse search(String title) throws BeansException, IOException {
|
public KodikResponse search(String title) throws BeansException, IOException {
|
||||||
return controllerApiFactory.getObject().search(title).execute().body();
|
return controllerApiFactory.getObject().search(title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
27
pom.xml
27
pom.xml
@ -4,6 +4,13 @@
|
|||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>3.5.5</version>
|
||||||
|
<relativePath /> <!-- lookup parent from repository -->
|
||||||
|
</parent>
|
||||||
|
|
||||||
<groupId>com.backend.vue.bff.service</groupId>
|
<groupId>com.backend.vue.bff.service</groupId>
|
||||||
<artifactId>anyame-bff-parent</artifactId>
|
<artifactId>anyame-bff-parent</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
@ -27,6 +34,26 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<java.version>21</java.version>
|
<java.version>21</java.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-cache</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module>anyame-kodik-search-api</module>
|
<module>anyame-kodik-search-api</module>
|
||||||
<module>main-app</module>
|
<module>main-app</module>
|
||||||
|
|||||||
Reference in New Issue
Block a user