Ok, that makes sense. I wanted to verify your behavior, which means
alternative makes no sense here.
So with that said, what I'm thinking is that you can forcibly veto the
class in a portable extension to disable its execution. It would be as
simple as
public void rejectDefaultClass(@Observes
ProcessAnnotatedType<TimestampsProvider> pat) {
pat.veto();
}
John
On Tue, Dec 20, 2016 at 9:54 AM Nico Schlebusch <[email protected]> wrote:
> 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]>
> >>>
> >>>
> >>
> >>
> >>
>
>
>