Web サービスに Feign を使用して REST クライアントを構築しようとしています。Web サービスは、xml Bean 構成を使用して Spring 4 で構築されています。
プロジェクトはMavenで構築され、サブモジュールを使用して構造化されています
foo-api
--- foo-api-client
------ src/main/java/foo/client
--------- FooClientFactory.java
------ pom.xml
--- foo-api-shared
------ src/main/java/foo/shared
--------- FooClient.java
------ pom.xml
--- foo-api-service
------ src/main
--------- /java/foo/service
------------ /config
--------------- FeignConfiguration.java
------------ /controller
--------------- FooController.java
--------- /webapp/WEB-INF
------------ spring.xml
------------ web.xml
--- pom.xml
Feign クライアントを有効にするために、Spring xml 構成で有効な注釈付きクラスを作成しました。
spring.xml
...
<context:component-scan base-package="foo.service"/>
<context:annotation-config/>
<bean class="foo.service.config.FeignConfiguration" />
...
FeignConfiguration.java
package foo.service.config;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
@EnableFeignClients
public class FeignConfiguration {
}
次に、Feign クライアントを作成し、アノテーションを使用して構成しました
FooClient.java
package foo.shared;
import feign.Headers;
import feign.RequestLine;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient("foo")
public interface FooClient {
@RequestLine("GET /foo/v2/{id}")
@Headers("Accept: " + MediaType.APPLICATION_JSON_VALUE)
Object get(@PathVariable("id") String id);
}
API コントローラーは、次のように Feign クライアントを実装します。
FooController.java
package foo.service.controller;
@Controller
@RequestMapping("/foo")
public class FooController implements FooClient {
@Override
@RequestMapping(value = "/v2/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody Object get(@PathVariable("id") String id) {
...
}
...
}
foo-api-client モジュール jar は、外部クライアントが foo-api-service REST サービスに接続するための依存関係として使用されます。これらのクライアントが API を簡単に使用できるようにするために、FooClient のインスタンスを生成するファクトリ クラスが作成されています。
FooClientFactory.java
package foo.client;
import foo.shared.FooClient;
import feign.Feign;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
@Service
public class FooClientFactory {
@Autowired
private Environment env;
public static final String SERVER_URL_PROPERTY = "foo.api.url";
public FooClient build() {
return Feign.builder()
.encoder(new JacksonEncoder())
.decoder(new JacksonDecoder())
.target(FooClient.class, env.getProperty(SERVER_URL_PROPERTY));
}
}
問題 外部クライアントがFooClientFactory
を使用して foo Web サービスへのリクエストを実行するとfooClientFactory.build().get("id");
、405 エラーが返されます。クライアント コンソールの応答ログは次のとおりです。
ERROR [http-nio-8091-exec-1] --- [dispatcherServlet]: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is feign.FeignException: status 405 reading FooClient#get(String); content:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Error 405 Request method 'POST' not supported</title>
</head>
<body><h2>HTTP ERROR 405</h2>
<p>Problem accessing /foo/v2/{id}. Reason:
<pre> Request method 'POST' not supported</pre></p><hr><a href="http://eclipse.org/jetty">Powered by Jetty:// 9.3.7.v20160115</a><hr/>
</body>
</html>
] with root cause
feign.FeignException: status 405 reading FooClient#getOrder(String); content:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Error 405 Request method 'POST' not supported</title>
</head>
<body><h2>HTTP ERROR 405</h2>
<p>Problem accessing /foo/v2/{id}. Reason:
<pre> Request method 'POST' not supported</pre></p><hr><a href="http://eclipse.org/jetty">Powered by Jetty:// 9.3.7.v20160115</a><hr/>
</body>
</html>
stackoverflow や他のブログでこの種の問題を検索しましたが、セットアップ全体の何が問題なのか理解できませんでした。
何か案が?
ありがとう、アンドレア