I've written a simple Feign client, for calling an external API (running on a different server):
@FeignClient(
name = "test-service",
url = "https://some-test-server.com/api"
)
public interface TestClient {
@RequestMapping(method = RequestMethod.POST, value = "/test")
TestResponse test(TestRequest request);
}
I wrote some simple bean classes, TestRequest
& TestResponse
to model the request / response - I'm expecting them to be serialized & deserialized as json.
I want to just test that its able to make the HTTP call and receive a response, so I wrote a test:
@SpringBootTest
@EnableFeignClients(clients = TestClient.class)
class ClientApplicationTests {
@Autowired
private TestClient client;
@Test
void contextLoads() {
System.out.println(client.test(TestRequest.builder().foo("foo").build()));
}
But Intellij warns me that no Beans were found to autowire TestClient
, and running this gives a similar exception:
java.lang.NoClassDefFoundError: org/springframework/cloud/context/named/NamedContextFactory$Specification
at java.base/java.lang.ClassLoader.defineClass1(Native Method) ~[na:na]
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1012) ~[na:na]
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639) ~[na:na]
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[na:na]
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[na:na]
at org.springframework.cloud.openfeign.FeignClientsRegistrar.registerClientConfiguration(FeignClientsRegistrar.java:410) ~[spring-cloud-openfeign-core-3.1.3.jar:3.1.3]
What am I doing wrong?
CodePudding user response:
Try giving your Feign client class name in this format and check whether this works,
@EnableFeignClients(basePackageClasses=com.abc.xxx.client.TestClient.class)
This parameter accept single or multiple class name. You can also give the base package of the same,
@EnableFeignClients(basePackages = {"my.external.feign.client.package", "my.local.package"})
CodePudding user response:
From the javadoc of @EnableFeignClients
:
Scans for interfaces that declare they are feign clients (via FeignClient
@FeignClient
). Configures component scanning directives for use with org.springframework.context.annotation.Configuration@Configuration
classes.
Generally this is placed on a @SpringBootApplication
annotated class so that your Feign clients are available in production as well as your @SpringBootTest
's.
If you really want to enable your Feign client only in your test, it should look something like this:
@SpringBootTest
class ClientApplicationTests {
@EnableFeignClients(clients = TestClient.class)
@Configuration
protected static class ClientApplicationTestsConfig {
}
@Autowired
private TestClient client;
@Test
void contextLoads() {
System.out.println(client.test(TestRequest.builder().foo("foo").build()));
}
}
This way your test will use the nested @Configuration
instead of the automatically found @SpringBootConfiguration
/@SpringBootApplication
.