Richard Zowalla created OPENJPA-3017:
----------------------------------------
Summary: @Convert on a collection attribute is ignored and the
attribute is silently not persisted
Key: OPENJPA-3017
URL: https://issues.apache.org/jira/browse/OPENJPA-3017
Project: OpenJPA
Issue Type: Bug
Affects Versions: 4.1.1
Reporter: Richard Zowalla
Assignee: Richard Zowalla
An {{@Convert}} annotation on a collection\-valued attribute is not honoured,
and the attribute is silently excluded from the mapping. Neither an exception
nor an error is raised, and the data is lost without notice.
Reduced case: an entity declaring
{code:java}
@Convert\(converter = ItemListConverter.class\)
private List items = new ArrayList<>\(\);
{code}
where {{ItemListConverter}} implements {{AttributeConverter, String>}} and
{{Item}} is a plain bean. Observed behaviour on 4.2.0\-SNAPSHOT with Derby:*
{{ClassMapping.getField\("items"\)}} returns {{null}}, so the field is not a
managed field at all;
* no column is generated for it;
* a {{persist\(\)}} followed by a {{find\(\)}} in a fresh context returns an
empty list, with no exception at any point;
* the sole trace is one warning stating that the field is "not a default
persistent type, and do not have any annotations indicating their persistence
strategy", from which it follows that {{@Convert}} is not counted as an
indication of a persistence strategy. In a run of the full test suite several
hundred such warnings are emitted, so the one that matters is easily missed.
Two defects follow. First, {{@Convert}} should be recognised as declaring a
persistence strategy. Second, where the conversion cannot be applied, the
attribute must not be dropped in silence; an error naming the attribute and the
reason is required.
On the specified semantics: {{@Convert}} applied to a collection attribute
other than a {{Map}}, with no {{attributeName}}, converts the _elements_ of the
collection, which would require {{AttributeConverter}} together with
{{@ElementCollection}}. A converter whose attribute type is the collection
itself, mapping the whole collection to a single column, is a provider
extension; Hibernate admits it. Whichever reading is implemented, the present
behaviour is wrong, because an unsupported mapping is accepted and then ignored.
Reported on the development list by Francesco Chicchiriccò while testing Apache
Syncope master against 4.2.0\-SNAPSHOT. In that configuration the attribute is
managed and the failure is instead
{noformat}
org.apache.openjpa.util.MetaDataException: You have supplied columns for
"...JPARealm.plainAttrs", but this mapping cannot
have columns in this context.
at
org.apache.openjpa.jdbc.meta.MappingInfo.assertNoSchemaComponents\(MappingInfo.java:384\)
at
org.apache.openjpa.jdbc.meta.strats.HandlerFieldStrategy.map\(HandlerFieldStrategy.java:84\)
{noformat}
which arises because the handler derived from the converter is installed and
the element mapping is then found to carry columns. That path did not reproduce
from the annotations alone, neither with a {{Serializable}} element type nor
with a non\-final field, and the configuration difference is still to be
established. The message is in any case opaque with respect to the cause.
A workaround exists and was verified: the converted form serves as the
persistent attribute, that is a {{String}} column holding the serialised value,
the collection is marked {{@Transient}}, and the two directions are carried out
in {{@PrePersist}}/{{@PreUpdate}} and {{@PostLoad}}. The OpenJPA extensions
{{@Externalizer}} and {{@Factory}} offer no alternative, as {{@Persistent}}
rejects a field of {{List}} type.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)