John,

That loop executes the number of times there are implementations of the PrePersistAuditListener. When I have my own implementation deployed it executes 3 times. The PrincipalProvider, my custom implementation (UTCDateTimeAuditProvider) and then TimestampsProvider are executed in that order.

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


On 20/12/2016 16:33, John D. Ament wrote:
Nico,

There's a for loop here
https://github.com/apache/deltaspike/blob/master/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/AuditEntityListener.java#L38

How many times does this for loop execute?

John

On Tue, Dec 20, 2016 at 9:23 AM Nico Schlebusch <[email protected]> wrote:

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]


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]>
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]>


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