問題:
React フロントエンドを備えた動作中の Spring Boot バックエンド サーバー (Java 11、Spring Boot 2.2.4.RELEASE) があり、IntelliJを介して実行された場合、Dockerコンテナーで完全に実行されます。java -jar app.jar
ただし、Eclipse (Windows Server 2016 で実行) を介して実行されている場合、JSON 本文を含む POST を送信しようとすると、次のエラーが発生します。
2020-03-09 15:09:52.515 WARN 218960 --- [nio-8080-exec-1] .c.j.MappingJackson2HttpMessageConverter : Failed to evaluate Jackson deserialization for type [[simple type, class xxx.xxx.xxx.xxx.xxx.xxx.xxx]]: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Invalid type definition for type `xxx.xxx.xxx.xxx.xxx.xxx.xxx`: Argument #0 has no property name, is not Injectable: can not use as Creator [constructor for xxx.xxx.xxx.xxx.xxx.xxx.xxx, annotations: {interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson.annotation.JsonCreator(mode=DEFAULT)}]
2020-03-09 15:09:52.517 WARN 218960 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported]
このエラーは、フロントエンド コードで設定されたヘッダーに関係なく発生します。したがって、Content-Type: application/jsonを設定すると、同じエラーが発生します (以下のヘッダーを参照)。
Eclipse でのみ起こっているようなことに遭遇した人はいますか?
私はすでにエンコーディングをチェックし (Eclipse ですべてを UTF-8 に設定)、すべての環境が IntelliJ と Eclipse で同じ Java バージョン (SDKMan 経由でインストールされた AdoptOpenJDK 11.0.6.hs-adpt を使用しています) を使用していることを確認しました。
コンパイルされたクラス ファイルは同一に見えます。アプリケーションを実行するときのクラスパスには、同じ jackson ライブラリが含まれています (全体的に非常に似ています)。
Eclipse がアプリケーションを実行する方法に関係があると思います。この奇妙な動作が観察される理由について、誰かが考えを持っていますか? なぜEclipseだけ?また、Eclipse を使用している開発者が何人かいるので、どうすれば解決できるのでしょうか?
リクエストに関する詳細情報:
ブラウザーから見た要求ヘッダー:
POST /server/configure HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 510
Accept: application/json, text/plain, */*
Sec-Fetch-Dest: empty
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36
Content-Type: application/json
Origin: http://localhost:3000
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Referer: http://localhost:3000/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,de-DE;q=0.8,de;q=0.7
そして応答:
{"timestamp":"2020-03-09T14:00:27.285+0000","status":415,"error":"Unsupported Media Type","message":"Content type 'application/json;charset=UTF-8' not supported","path":"/server/configure"}
そして応答ヘッダー:
HTTP/1.1 415
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: http://localhost:3000
Content-Type: application/json
Transfer-Encoding: chunked
Date: Mon, 09 Mar 2020 13:53:05 GMT
Keep-Alive: timeout=60
Connection: keep-alive
アプリに関する詳細情報:
コントローラーは次のとおりです (簡略化)。
package xxx.xxx.xxx.xxx.xxx.xxx;
...
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
...
@Controller
@RequestMapping("/server")
@CrossOrigin(origins = "http://localhost:3000")
public class Controller {
private someService SomeService;
@Autowired
public Controller(SomeService someService) {
this.someService= someService;
}
@PostMapping(value = "/configure", consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String configureConnection(@RequestBody ConnectionConfiguration connectionConfiguration) throws MalformedURLException {
String serverId = someService.configureConnection(connectionConfiguration);
return serverId;
}
}
ConnectionConfiguration クラスは次のとおりです (ここでは少ないプロパティを示しています)。
package xxx.xxx.xxx.xxx.xxx.xxx;
import com.fasterxml.jackson.annotation.JsonCreator;
public class ConnectionConfiguration {
private String someProperty;
@JsonCreator
public ConnectionConfiguration(String someProperty) {
this.someProperty= someProperty;
}
public String getSomeProperty() {
return someProperty;
}
}
プロジェクト構造に関しては、バックエンド フォルダーとフロントエンドフォルダーを含むルート フォルダーがあります。それぞれ (ルート、バックエンド、フロントエンド) には build.gradle ファイルが含まれており、ルート フォルダー内の build.gradle を介してリンクされています。これにより、フロントエンドをビルドし、静的 HTML および JavaScript ファイルをバックエンドの resources/static フォルダーにコピーしてから、Spring Boot jar をビルドするプロダクション ビルドを作成できます。次に、本番モードでは、フロントエンドは Spring Boot の Tomcat を介して配信されます。
開発の場合、通常、フロントエンド用の Webpack 開発サーバーを開始しnpm run start
、IDE を介して main メソッドを含む Application.java クラスから Spring Boot アプリを開始します。
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}