Hi John,
Thanks for the answer.
The AuditEntityListener is called once from my debugging sessions.
I'll definitely raise a feature request, it might just not be in the
next 2 weeks. Would the feature request be to take @Alternative beans
into considerations when looking up the beans that implements the 2
interfaces, PrePersistAuditListener & PreUpdateAuditListener? Meaning
that lines 40-41 and 53-54 from the link below, need to filter out the
@Default beans when an @Alternative is available? Or should I phrase it
differently?
Kind regards,
Nico Schlebusch
[email protected] <mailto:[email protected]>
On 20/12/2016 15:56, John D. Ament wrote:
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 <[email protected]
<mailto:[email protected]>> 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
[email protected] <mailto:[email protected]>
<mailto:[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]>
<mailto:[email protected] <mailto:[email protected]>>
>
>