I'm trying to get my microservice java spring boot to communicate with another microservice using Feign but I'm getting this message when starting the application:
APPLICATION FAILED TO START
***************************
Description: Parameter 0 of constructor in ProductService required a bean of type ProductClientRepository' that could not be found.
Action: Consider defining a bean of type 'ProductClientRepository' in your configuration.
I don't know what could be wrong, I already checked if all the declared variables are in the project's properties and I already checked the imports, I don't know why it is saying that something is missing in the bean.
pom.xml:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
SaleService:
@Service
@RequiredArgsConstructor
public class SaleService {
private final ProductService productService;
@Transactional
public Sale createSale(Sale sale) {
Set<Long> codesFromRequest = sale.getProducts().stream().map(p -> p.getCode())
.collect(Collectors.toSet());
validateProduct(codesFromRequest);
return saleRepository.save(sale);
}
public void validateProduct(Set<Long> codesFromRequest) {
List<SaleProductDTO> products = productService.findProduct(codesFromRequest);
Set<Long> returnedCodes = products.stream().map(p -> p.getCode()).collect(Collectors.toSet());
throwExceptionIf(validateSizeList(codesFromRequest, returnedCodes),
new ProductNotFoundException());
}
public boolean validateSizeList(Collection<?> codesFromRequest, Collection<?> returnedCodes) {
return codesFromRequest.size() != returnedCodes.size();
}
}
ProductService:
@Service
@Slf4j
@AllArgsConstructor
public class ProductService {
private final ProductClientRepository productRepository;
@Retryable(value = { Exception.class }, maxAttempts = 3, backoff = @Backoff(delay = 50))
public List<SaleProductDTO> findProduct(Set<Long> codes) {
Page<SaleProductDTO> resultPage;
try {
var search = SearchProductDTO
.builder()
.codes(codes)
.build();
resultPage = productRepository.getProducts(search);
} catch (FeignException f) {
return Collections.emptyList();
}
return resultPage.getContent();
}
}
ProductClientRepository:
@FeignClient(name = "product-service", url = "${ms-product.url}", configuration = ProductOAuth2FeignConfig.class)
public interface ProductClientRepository {
@GetMapping(value = "/chunk")
Page<SaleProductDTO> getProducts(@RequestBody SearchProductDTO searchDTO);
}
ProductOAuth2FeignConfig:
public class ProductOAuth2FeignConfig {
@Autowired
private ProductConfig productConfig;
@Bean
public RequestInterceptor stockOAuth2RequestInterceptor() {
return new OAuth2FeignRequestInterceptor(new DefaultOAuth2ClientContext(), resource());
}
private OAuth2ProtectedResourceDetails resource() {
ClientCredentialsResourceDetails resource = new ClientCredentialsResourceDetails();
resource.setAccessTokenUri(productConfig.getTokenUri());
resource.setClientId(productConfig.getTokenClientId());
resource.setClientSecret(productConfig.getTokenClientSecret());
resource.setGrantType(productConfig.getTokenGrantType());
resource.setScope(List.of(productConfig.getTokenScope()));
return resource;
}
}
ProductConfig:
@Data
@Configuration
@ConfigurationProperties(prefix = "ms-product")
public class ProductConfig {
private String tokenUri;
private String tokenGrantType;
private String tokenClientId;
private String tokenClientSecret;
private String tokenScope;
}
application.properties:
external.api=https://myadress.com/api
ms-product.url=${external.api}/products
ms-product.token-uri=${external.api}/products/oauth2/token
ms-product.token-grant-type=client_credentials
ms-product.token-client-id=client-id-value
ms-product.token-client-secret=secret-value
ms-product.token-scope=read
feign.client.config.default.connect-timeout=3000
feign.client.config.default.read-timeout=7000
Seems you need to add @EnableFeignClients annotation. Please refer Spring Boot OpenFeign