エラーメッセージ:
org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class xxx] with preset Content-Type 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'
解決策
エラー内容は「指定されたContent-Typeに対応するコンバーターが見つからない」という意味です。この問題を解決するには以下の2つの方法があります。
- メソッドの戻り値型を
voidに変更する response.reset()を使ってレスポンスのContent-Typeをクリアし、適切なコンバーターを選択させる。ただし、これによりフロントエンド側にもContent-Typeが設定されず、ファイル形式を判別できなくなるため、フロントエンドで明示的に設定する必要がある
問題コード例
エクスポート機能自体は正常に動作しますが、ログには「戻り値の変換に失敗した」というエラーが出力されます。これは実際には機能に影響しませんが、ログの可読性を損ねます。
public MessageResp<String> exportExcel(@RequestBody Req req, HttpServletResponse response) throws Exception {
try (ServletOutputStream out = response.getOutputStream()) {
String fileName = URLEncoder.encode("導出テーブル.xlsx", "UTF-8");
response.reset();
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName);
DgExcelUtil.getXlsx("導出シート", exportClass, titleList, exportList).write(out);
} catch (Exception e) {
LOGGER.error("エクスポートエラー:", e);
throw new SmkException(ErrorCode.FAIL, "エクスポートエラー");
}
return new MessageResp<>(); // 問題の返却値
}
エラーログ詳細
エラーログのスタックトレースは以下の通りです:
org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class com.sk.financial.dg.supervision.response.MessageResp] with preset Content-Type 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:312)
...
原因分析
エラー発生箇所のAbstractMessageConverterMethodProcessor.writeWithMessageConvertersメソッドを見ると、以下のような処理が行われています。
- レスポンスヘッダーからContent-Typeを取得し、
selectedMediaTypeに設定 - もしContent-Typeが指定されていない場合、リクエストのAcceptヘッダーとサポートされているメディアタイプに基づいて自動選定
その後、選択されたselectedMediaTypeを使ってコンバーターを検索します。しかし、指定されたContent-Typeと返却値の型が一致しない場合、コンバーターが見つからないため例外がスローされます。
この問題を回避するには、以下のいずれかの方法をとります:
- 返却値を
voidに変更してSpringがコンバーター処理を行わないようにする - レスポンスのContent-Typeをクリアし、Springが自動的に適切なコンバーターを選ぶようにする