Проблемы @Inject в AttributeConverter в JPA 2.2/Java EE 8/Glassfish v5
JPA 2.2 должен поддерживать @Inject
в AttributeConverter
, как описано в спецификации:
Классы конвертера атрибутов в средах Java EE поддерживают внедрение зависимостей через контексты и API внедрения зависимостей (CDI) [ 7 ], когда CDI включен [51]. Класс преобразователя атрибутов, который использует внедрение CDI, может также определять методы обратного вызова жизненного цикла, аннотированные аннотациями PostConstruct и PreDestroy. Эти методы будут вызваны после внедрения и до уничтожения экземпляра преобразователя атрибутов соответственно.
Но когда я конвертирую свой образец конвектора JPA 2.1 в JPA 2.2, он не работает.
Оригинальный конвертер работал как 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 я извлек логику преобразования в другой компонент CDI. И попытался запустить коды в Glassfish v5(Реализация Java EE 8 Reference).
@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
ожидаемый ConverterUtils
не вводятся, и всегда становятся нулевыми, когда их вызывают, бросает NPE.
Полные коды можно найти здесь.
Обновление: я обнаружил, что создал проблему на EclipseLink bugzilla 4 года назад.