ExternalSkillClient.java
package fr.avenirsesr.portfolio.declaredskill.infrastructure.adapter.client;
import fr.avenirsesr.portfolio.common.externalskill.application.adapter.dto.ExternalSkillCategoryDTO;
import fr.avenirsesr.portfolio.common.externalskill.application.adapter.dto.ExternalSkillDTO;
import fr.avenirsesr.portfolio.common.externalskill.application.adapter.dto.ExternalSkillDetailsDTO;
import fr.avenirsesr.portfolio.common.security.infrastructure.adapter.model.AvenirsSecurityHeaders;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
@Slf4j
@Component
public class ExternalSkillClient {
private final WebClient webClient;
@Value("${avenirs.interoperability.api-key}")
private String apiKey;
@Value("${avenirs.interoperability.external-skill.endpoint}")
private String externalSkillEndpoint;
@Value("${avenirs.interoperability.actuator.health}")
private String healthEndpoint;
public ExternalSkillClient(WebClient webClient) {
this.webClient = webClient;
}
@Cacheable(value = "externalSkillById", key = "#externalSkillId")
public Optional<ExternalSkillDTO> getById(UUID externalSkillId) {
try {
log.debug("Fetching external skill from interoperability: {}", externalSkillId);
ExternalSkillDetailsDTO details =
webClient
.get()
.uri(externalSkillEndpoint + "/" + externalSkillId)
.header(AvenirsSecurityHeaders.API_KEY, apiKey)
.retrieve()
.bodyToMono(ExternalSkillDetailsDTO.class)
.block();
if (details == null) {
return Optional.empty();
}
ExternalSkillDTO result =
new ExternalSkillDTO(
details.id(),
details.title(),
details.categoryPath().stream().map(ExternalSkillCategoryDTO::libelle).toList(),
details.type());
return Optional.of(result);
} catch (Exception e) {
log.error(
"Failed to fetch external skill {} from interoperability at '{}'. Error: {}",
externalSkillId,
externalSkillEndpoint,
e.getMessage());
log.debug("Full error details:", e);
return Optional.empty();
}
}
@Cacheable(value = "externalSkillDetails", key = "#externalSkillId")
public Optional<ExternalSkillDetailsDTO> getExternalSkillDetails(UUID externalSkillId) {
try {
log.debug("Fetching external skill details from interoperability: {}", externalSkillId);
ExternalSkillDetailsDTO result =
webClient
.get()
.uri(externalSkillEndpoint + "/" + externalSkillId)
.header(AvenirsSecurityHeaders.API_KEY, apiKey)
.retrieve()
.bodyToMono(ExternalSkillDetailsDTO.class)
.block();
return Optional.ofNullable(result);
} catch (Exception e) {
log.error(
"Failed to fetch external skill details {} from interoperability at '{}'. Error: {}",
externalSkillId,
externalSkillEndpoint,
e.getMessage());
log.debug("Full error details:", e);
return Optional.empty();
}
}
public List<ExternalSkillDTO> getRandomSkills(int count) {
try {
log.debug("Fetching {} random external skills from interoperability", count);
List<ExternalSkillDTO> result =
webClient
.get()
.uri(externalSkillEndpoint + "/random?count=" + count)
.header(AvenirsSecurityHeaders.API_KEY, apiKey)
.retrieve()
.bodyToMono(new ParameterizedTypeReference<List<ExternalSkillDTO>>() {})
.block();
return result != null ? result : List.of();
} catch (Exception e) {
log.error(
"Failed to fetch random external skills from interoperability at '{}'. Error: {}",
externalSkillEndpoint,
e.getMessage());
log.debug("Full error details:", e);
return List.of();
}
}
public boolean checkInteroperabilityMicroservice() {
try {
log.debug("Checking interoperability microservice health at: {}", healthEndpoint);
String response =
webClient.get().uri(healthEndpoint).retrieve().bodyToMono(String.class).block();
log.info("Interoperability microservice is UP");
return response != null && response.contains("\"status\":\"UP\"");
} catch (Exception e) {
log.error(
"Interoperability microservice health check failed at '{}'. Error: {}",
healthEndpoint,
e.getMessage());
log.debug("Full error details:", e);
return false;
}
}
}