deltaspike-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "John D. Ament" <johndam...@apache.org>
Subject Re: DeltaSpike Data - Custom PrePersistAuditListener and PreUpdateAuditListener
Date Tue, 20 Dec 2016 13:56:03 GMT
Nico,

Seems the logic in DeltaSpike is to loop through the beans.  Can you check
if you're seeing this loop is called multiple times?
https://github.com/apache/deltaspike/blob/master/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/AuditEntityListener.java

Anyways, would be good to have this support direct in deltaspike.  Mind
raising a feature request? https://issues.apache.org/jira/browse/DELTASPIKE

John

On Tue, Dec 13, 2016 at 2:58 AM Nico Schlebusch <nicoschl@gmail.com> wrote:

> 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
> nicoschl@gmail.com <mailto:nicoschl@gmail.com>
>
>
> 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
> > nicoschl@gmail.com <mailto:nicoschl@gmail.com>
> >
> >
>
>
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message