仕様で説明されているように、JPA 2.2 は でサポート@Inject
する必要があります。AttributeConverter
Java EE 環境の属性コンバーター クラスは、CDI が有効な場合 [51]、Contexts and Dependency Injection API (CDI) [7] による依存性注入をサポートします。CDI インジェクションを利用する属性コンバーター クラスは、PostConstruct および PreDestroy アノテーションが付けられたライフサイクル コールバック メソッドを定義することもできます。これらのメソッドは、注入が行われた後、属性コンバーターのインスタンスが破棄される前にそれぞれ呼び出されます。
しかし、JPA 2.1 コンバーター サンプルを JPA 2.2 に変換すると、機能しません。
元のConverter は、Glassfish v4 と v5 の両方で機能しました。
@Converter
public class ListToStringConveter implements AttributeConverter<List<String>, String> {
//@Inject Logger log;
@Override
public String convertToDatabaseColumn(List<String> attribute) {
if (attribute == null || attribute.isEmpty()) {
return "";
}
return StringUtils.join(attribute, ",");
}
@Override
public List<String> convertToEntityAttribute(String dbData) {
if (dbData == null || dbData.trim().length() == 0) {
return new ArrayList<String>();
}
String[] data = dbData.split(",");
return Arrays.asList(data);
}
}
AttributeConverter
JPA 2.2 でのインジェクション サポートを味わうために、Anther CDI Bean への変換ロジックを抽出しました。Glassfish v5(Java EE 8 Reference implementation)でコードを実行しようとしました。
@Converter(autoApply = false)
public class TagsConverter implements AttributeConverter<List<String>, String> {
// private static final Logger LOG = Logger.getLogger(TagsConverter.class.getName());
//
// @Override
// public String convertToDatabaseColumn(List<String> attribute) {
// if (attribute == null || attribute.isEmpty()) {
// return "";
// }
// return String.join( ",", attribute);
// }
//
// @Override
// public List<String> convertToEntityAttribute(String dbData) {
// if (dbData == null || dbData.trim().length() == 0) {
// return new ArrayList<>();
// }
//
// String[] data = dbData.split(",");
// return Arrays.asList(data);
// }
@Inject
Logger LOG;
@Inject
ConverterUtils utils;
@PostConstruct
public void postConstruct(){
LOG.log(Level.INFO, "calling @PostConstruct");
}
@PreDestroy
public void preDestroy(){
LOG.log(Level.INFO, "calling @PreDestroy");
}
@Override
public String convertToDatabaseColumn(List<String> attribute) {
LOG.log(Level.FINEST, "utils injected: {0}", utils != null);
if (attribute == null || attribute.isEmpty()) {
return "";
}
return utils.listToString(attribute);
}
@Override
public List<String> convertToEntityAttribute(String dbData) {
if (dbData == null || dbData.trim().length() == 0) {
return Collections.<String>emptyList();
}
return utils.stringToList(dbData);
}
}
そしてConverterUtils
クラス。
@ApplicationScoped
public class ConverterUtils {
public String listToString(List<String> tags) {
return join(",", tags);
}
public List stringToList(String str) {
return Arrays.asList(str.split(","));
}
}
ではTagsConverter
、expectedConverterUtils
は注入されず、呼び出されると常に null を取得し、NPE がスローされました。
完全なコードはここにあります。
更新: 4 年前に EclipseLink bugzilla で問題を作成したことがわかりました。