Good day,

I have made some progress in answering my question, but I'm facing a new problem. Please see the updated Q on SO - http://stackoverflow.com/questions/41057116/deltaspike-data-cdi-jpa-custom-prepersistauditlistener-and-preupdateauditlis

Thank you

Kind regards,
Nico Schlebusch
[email protected] <mailto:[email protected]>


On 07/12/2016 12:22, Nico Schlebusch wrote:
Good day,

I'm using the @EntityListeners(AuditEntityListener.class) and @CreatedOn, @ModifiedOn and @ModifiedBy annotations on an Entity bean with the difference that I have a custom implementation of java.time.ChronoLocalDateTime which converts any LocalDateTime + ZoneOffset OR a ZonedDateTime to be the UTC date & time.

    public class UTCDateTime implements
    ChronoLocalDateTime<LocalDate>, Serializable {

      private static final long serialVersionUID = 6492792765662073566L;
      private static final ZoneOffset UTC = ZoneOffset.UTC;
      private final LocalDateTime datetime;

      // a lot of other details left out
    }

The entity bean parts

    @MappedSuperclass
    public class InsertableAuditableBean extends BaseBean implements
    InsertableAuditable {

      @NotNull
      @Size(min = 1, max = 50)
      @Column(name = "zz_inserted_by", length = 50, nullable = false)
      private String insertedBy;

    @CreatedOn
      @NotNull
      @Temporal(value = TemporalType.TIMESTAMP)
      @Column(name = "zz_inserted_on", nullable = false)
      private UTCDateTime insertedOn;

      // getters & setters
    }

    @MappedSuperclass
    public class UpdateableAuditableBean extends
    InsertableAuditableBean implements UpdateableAuditable {

    @ModifiedBy
      @Size(min = 1, max = 50)
      @Column(name = "zz_updated_by", length = 50, nullable = true)
      private String updatedBy;

    @ModifiedOn
      @Temporal(value = TemporalType.TIMESTAMP)
      @Column(name = "zz_updated_on", nullable = true)
      private UTCDateTime updatedOn;

      // getters & setters
    }

    @Entity
    @EntityListeners(AuditEntityListener.class)
    @Table(schema = "data", name = "manufacturer", uniqueConstraints = {
        @UniqueConstraint(columnNames = { "man_name", "man_country" })
    })
    @AttributeOverrides({
        @AttributeOverride(name = "primaryKey", column = @Column(name
    = "man_serial")),
        @AttributeOverride(name = "insertedBy", column = @Column(name
    = "man_inserted_by")),
        @AttributeOverride(name = "insertedOn", column = @Column(name
    = "man_inserted_on")),
        @AttributeOverride(name = "updatedBy", column = @Column(name =
    "man_updated_by")),
        @AttributeOverride(name = "updatedOn", column = @Column(name =
    "man_updated_on"))
    })
    @SequenceGenerator(name = "default_seq", schema = "data",
    sequenceName = "manufacturer_man_serial_seq",
        allocationSize = 1)
    public class Manufacturer extends MirroredUpdateableAuditableBean
    implements IManufacturer {
      // nothing special here
    }

There is also a custom AttributeConverter for the UTCDateTime class because the epoch value is saved in the database.

    @Converter(autoApply = true)
    public class UTCDateTimePersistenceConverter implements
    AttributeConverter<UTCDateTime, Long> {

      @Override
      public Long convertToDatabaseColumn(final UTCDateTime entityValue) {
        Long res = null;
        if (entityValue != null) {
          res = entityValue.toMillis();
        }
        return res;
      }

      @Override
      public UTCDateTime convertToEntityAttribute(final Long
    databaseValue) {
        UTCDateTime res = null;
        if (databaseValue != null) {
          res = new UTCDateTime(Instant.ofEpochMilli(databaseValue));
        }
        return res;
      }
    }

Now when I persist the entity I get the following exception (the last bit with the real cause):

    Caused by:
    org.apache.deltaspike.data.api.QueryInvocationException: Failed
    calling Repository:
    
[Repository=systems.apace.data.manufacturer.model.dao.ManufacturerDAO,entity=systems.apace.data.manufacturer.model.Manufacturer,method=persist,exception=class
    java.lang.reflect.InvocationTargetException,message=null
            at
    
systems.apace.data.manufacturer.services.ManufacturerServiceBeanIntegrationTest.testInsertBean(ManufacturerServiceBeanIntegrationTest.java:55)
    Caused by: java.lang.reflect.InvocationTargetException
            at
    
systems.apace.data.manufacturer.services.ManufacturerServiceBeanIntegrationTest.testInsertBean(ManufacturerServiceBeanIntegrationTest.java:55)
    Caused by:
    org.apache.deltaspike.data.impl.audit.AuditPropertyException:
    Failed to set property Manufacturer.insertedOn, is this a temporal
    type?
            at
    
systems.apace.data.manufacturer.services.ManufacturerServiceBeanIntegrationTest.testInsertBean(ManufacturerServiceBeanIntegrationTest.java:55)
    Caused by: java.lang.IllegalArgumentException: Annotated field is
    not a date class: class za.co.t9.common.utils.time.UTCDateTime
            at
    
systems.apace.data.manufacturer.services.ManufacturerServiceBeanIntegrationTest.testInsertBean(ManufacturerServiceBeanIntegrationTest.java:55)

Is there a way to implement my own org.apache.deltaspike.data.impl.audit.PrePersistAuditListener and org.apache.deltaspike.data.impl.audit.PreUpdateAuditListener and use them to create the instance of UTCDateTime?

Would it be correct to write my own EntityListener --> UTCDateTimeAuditListener and use it @EntityListeners(UTCDateTimeAuditEntityListener.class) where UTCDateTimeAuditListener follows the org.apache.deltaspike.data.impl.audit.AuditEntityListener approach? Secondly, do I need to use a CDI Qualifier somewhere to make sure that my UTCDateTimeAuditEntityListener gets a reference to the correct PrePersistAuditListener and PreUpdateAuditListener that knows how to construct the UTCDateTime instance?

Lastly, I don't know if it is relevant, but where does org.apache.deltaspike.data.impl.audit.TimestampsProvider fit into this scenario?

Thank you for your time

Kind regards,
Nico Schlebusch
[email protected] <mailto:[email protected]>




Reply via email to