概要
SpringBootでエラーが出たので投稿します。
この辺りはまだ自信が無いので話半分程度で聞くかご指摘お願いします。
エラー内容
@Autowiredのアノテーションを付けたクラスでエラーが発生。
ビルドは成功します。実行するとエラーになります。
@Autowired
CsvMapper mapper;
実行すると以下のエラーメッセージが発生。
Description
Field mapper in com.example.spring_boot_memo.csv.CsvService required a bean of type 'com.fasterxml.jackson.dataformat.csv.CsvMapper' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.fasterxml.jackson.dataformat.csv.CsvMapper' in your configuration.
原因
CsvMapperがSpringコンテナに登録されていないことが原因です。
@AutowiredはSpringコンテナに入っているCsvMapperクラスを呼び出します。
SpringコンテナにはCsvMapperクラスが登録されていませんでした。
そのため@AutowiredでCsvMapperを呼ぶことができずエラーが発生しました。
CsvMapperのソースコード見ると自動的にSpringコンテナに登録してくれる@Service @Controllerといったアノテーションはありません。
(SpringBoot特化のクラスではないので、そりゃそうですよね…)
私はいつもアノテーションに頼ってばっかでしたので、原因を探すのに苦労しました…
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
// (一部抜粋)です RYA234
package com.fasterxml.jackson.dataformat.csv;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.AnnotationIntrospector;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.cfg.MapperBuilder;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
import com.fasterxml.jackson.databind.util.NameTransformer;
import com.fasterxml.jackson.databind.util.ViewMatcher;
import com.fasterxml.jackson.dataformat.csv.CsvSchema.ColumnType;
import com.fasterxml.jackson.dataformat.csv.impl.LRUMap;
import java.util.Collection;
import java.util.Iterator;
// アノテーションが無い RYA234
public class CsvMapper extends ObjectMapper {
private static final long serialVersionUID = 1L;
protected final LRUMap<JavaType, CsvSchema> _untypedSchemas;
protected final LRUMap<JavaType, CsvSchema> _typedSchemas;
public CsvMapper() {
this(new CsvFactory());
}
対処方法
方法は2つあります。
1.CsvMapperクラスに@Serviceを追記してSpringコンテナに登録する。
2.Beanを使って、CsvmapperクラスをSpringコンテナに登録します。実装方法としては@ConfigurationがあるクラスにBean登録する。
CsvMapper.javaは読み取り専用なので1の方法は使えません。
よって今回は2の方法を採用します。
実装
package com.example.spring_boot_memo.csv;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BeanConfig {
@Bean
public CsvMapper getCsvMapper()
{
return new CsvMapper();
}
}
まとめ
外部のクラスに対して@Autowiredを使うときはSpringコンテナに登録しよう!
参考資料