2

I'm trying to combine two concepts:

  • Store Enums, which are in a one-to-many relationship of an entity (using @ElementCollection, @CollectionTable)
  • Persist the Enums not by String or Ordinal, but by a unique ID (using @AttributeConverter)

Individually they should to work fine (judging by the docs), but when I combine them, I get errors during build.

Here's the entity:

@Entity
@Table(name = "push_tokens")
public class PushTokenDAO implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long idx;

    @ElementCollection(targetClass = NotificationType.class, fetch = FetchType.EAGER)
    @Convert(converter = NotificationTypeConverter.class)
    @CollectionTable(
            name = "notificationtypes_of_tokens",
            joinColumns = @JoinColumn(name = "fk_tokenIdx")
    )
    @Column(name = "notificationType")
    private List<NotificationType> notificationTypes;

    /* ... */

}

This is the Enum:

public enum NotificationType {
    NEW_TRANSFER(10),
    DELIVERY_REPORT(20),
    UPLOAD_CONFIRMATION(30),
    EXPIRY_WARNING(40);

    private final int code;

    NotificationType(int code) {
        this.code = code;
    }

    public static NotificationType parse(int code) {
        for (NotificationType t : NotificationType.values()) {
            if (t.code == code) {
                return t;
            }
        }
        throw new IllegalArgumentException("No such NotificationType");
    }

    public int getCode() {
        return code;
    }
}

The converter:

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

@Converter(autoApply = true)
public class NotificationTypeConverter implements AttributeConverter<NotificationType, Integer> {

    @Override
    public Integer convertToDatabaseColumn(NotificationType x) {
        return x.getCode();
    }

    @Override
    public NotificationType convertToEntityAttribute(Integer y) {
        return NotificationType.parse(y);
    }

}

The collection-table notificationtypes_of_tokens has just the two numeric columns in it:

CREATE TABLE `notificationtypes_of_tokens` (
  `fk_tokenIdx` bigint(11) unsigned NOT NULL,
  `notificationType` int(11) unsigned NOT NULL,
  PRIMARY KEY (`fk_tokenIdx`,`notificationType`),
  KEY `fk_tokenIdx` (`fk_tokenIdx`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

The problem occurs during EclipseLink's static weaving, which is part of the build process:

Failed to execute goal de.empulse.eclipselink:staticweave-maven-plugin:1.0.0:weave (default) 
on project skp-server: Execution default of goal de.empulse.eclipselink:staticweave-maven-plugin:1.0.0:weave 
failed: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070):
    org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [skp-server-PU] failed.
Internal Exception: Exception [EclipseLink-7351] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070):
    org.eclipse.persistence.exceptions.ValidationException
Exception Description: The converter class [com.skalio.skaliopush.db.NotificationTypeConverter] 
    specified on the mapping attribute [notificationTypes] from the class 
    [com.skalio.skaliopush.db.entity.PushTokenDAO] was not found. Please ensure the converter 
    class name is correct and exists with the persistence unit definition.

If I don't specifically reference the converter in the entity (leave out @Convert), the conversion is not done; the Enum is mapped to its ordinal. This is not what I want.

FYI: The code runs on a Java SE VM, not an application server or something. I have to specify each entity class in persistence.xml.

Hank
  • 4,597
  • 5
  • 42
  • 84

1 Answers1

0

The solution has nothing to do with @ElementCollection, Enums or the combination with an @AttributeConverter.

Instead, the answer lies in the question what has to be specified in persistence.xml when running on Java SE. The error message was hinting in that way as well ('converter not found...').

After specifying the converter class in persistence.xml, weaving works fine, the code builds, and it runs as expected. In summary: Combining @ElementCollection, Enum and @AttributeConverter works just fine, as per the code above.

Community
  • 1
  • 1
Hank
  • 4,597
  • 5
  • 42
  • 84