You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@deltaspike.apache.org by Nico Schlebusch <ni...@gmail.com> on 2016/12/07 10:22:26 UTC
DeltaSpike Data - Custom PrePersistAuditListener and
PreUpdateAuditListener
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 <ma...@gmail.com>
Re: DeltaSpike Data - Custom PrePersistAuditListener and
PreUpdateAuditListener
Posted by Nico Schlebusch <ni...@gmail.com>.
Hi John,
Issue raised - https://issues.apache.org/jira/browse/DELTASPIKE-1229
Kind regards,
Nico Schlebusch
nicoschl@gmail.com <ma...@gmail.com>
On 20/12/2016 23:13, Nico Schlebusch wrote:
> No problem, thanks for your help. I'll raise the issue in JIRA.
>
> Kind regards,
> Nico Schlebusch
> nicoschl@gmail.com <ma...@gmail.com>
>
>
> On 20/12/2016 23:11, John D. Ament wrote:
>> Gah shoot, sorry about that. It won't work because its a package private
>> class, and the classloader will block it.
>>
>> I'll get something in to fix this, unfortunately it won't work until my
>> change is in. Please do make sure to raise an issue in JIRA so I don't
>> lose track. Thanks for checking it out.
>>
>> John
>>
>> On Tue, Dec 20, 2016 at 4:07 PM Nico Schlebusch<ni...@gmail.com> wrote:
>>
>>> Hi John,
>>>
>>> Thanks for the suggestion on vetoing the TimestampsProvider, but there is
>>> a new problem with my approach or lack of understanding of Portable
>>> Extensions.
>>>
>>> I first created the portable extension inside my own package structure,
>>> but then the compiler fails to resolve TimestampsProvider because it is a
>>> package protected class. I then moved my extension into the same package
>>> (org.apache.deltaspike.data.impl.audit) as TimestampsProvider but then got
>>> this exception on deployment
>>>
>>> Caused by: java.lang.IllegalAccessError: tried to access class
>>> org.apache.deltaspike.data.impl.audit.PrincipalProvider from class
>>> org.apache.deltaspike.data.impl.audit.VetoDeltaSpikeAuditProvidersExtension
>>> at
>>> org.apache.deltaspike.data.impl.audit.VetoDeltaSpikeAuditProvidersExtension.rejectPrincipalProvider(VetoDeltaSpikeAuditProvidersExtension.java:43)
>>> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>>> at
>>> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
>>> at
>>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>>> at java.lang.reflect.Method.invoke(Method.java:498)
>>> at
>>> org.jboss.weld.injection.StaticMethodInjectionPoint.invoke(StaticMethodInjectionPoint.java:88)
>>>
>>> I read somewhere that happens when the classes aren't loaded with the same
>>> classloader.
>>>
>>> Any other ideas on how to veto the TimestampsProvider?
>>>
>>>
>>> Kind regards,
>>> Nico Schlebusch
>>> nicoschl@gmail.com
>>>
>>>
>>> On 20/12/2016 17:23, John D. Ament wrote:
>>>
>>> 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<ni...@gmail.com>
>>> 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
>>> nicoschl@gmail.com <ma...@gmail.com>
>>>
>>>
>>> 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<ni...@gmail.com>
>>> 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
>>>>> nicoschl@gmail.com
>>>>>
>>>>>
>>>>> 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
>>>>>
>
>
Re: DeltaSpike Data - Custom PrePersistAuditListener and
PreUpdateAuditListener
Posted by Nico Schlebusch <ni...@gmail.com>.
No problem, thanks for your help. I'll raise the issue in JIRA.
Kind regards,
Nico Schlebusch
nicoschl@gmail.com <ma...@gmail.com>
On 20/12/2016 23:11, John D. Ament wrote:
> Gah shoot, sorry about that. It won't work because its a package private
> class, and the classloader will block it.
>
> I'll get something in to fix this, unfortunately it won't work until my
> change is in. Please do make sure to raise an issue in JIRA so I don't
> lose track. Thanks for checking it out.
>
> John
>
> On Tue, Dec 20, 2016 at 4:07 PM Nico Schlebusch <ni...@gmail.com> wrote:
>
>> Hi John,
>>
>> Thanks for the suggestion on vetoing the TimestampsProvider, but there is
>> a new problem with my approach or lack of understanding of Portable
>> Extensions.
>>
>> I first created the portable extension inside my own package structure,
>> but then the compiler fails to resolve TimestampsProvider because it is a
>> package protected class. I then moved my extension into the same package
>> (org.apache.deltaspike.data.impl.audit) as TimestampsProvider but then got
>> this exception on deployment
>>
>> Caused by: java.lang.IllegalAccessError: tried to access class
>> org.apache.deltaspike.data.impl.audit.PrincipalProvider from class
>> org.apache.deltaspike.data.impl.audit.VetoDeltaSpikeAuditProvidersExtension
>> at
>> org.apache.deltaspike.data.impl.audit.VetoDeltaSpikeAuditProvidersExtension.rejectPrincipalProvider(VetoDeltaSpikeAuditProvidersExtension.java:43)
>> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>> at
>> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
>> at
>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>> at java.lang.reflect.Method.invoke(Method.java:498)
>> at
>> org.jboss.weld.injection.StaticMethodInjectionPoint.invoke(StaticMethodInjectionPoint.java:88)
>>
>> I read somewhere that happens when the classes aren't loaded with the same
>> classloader.
>>
>> Any other ideas on how to veto the TimestampsProvider?
>>
>>
>> Kind regards,
>> Nico Schlebusch
>> nicoschl@gmail.com
>>
>>
>> On 20/12/2016 17:23, John D. Ament wrote:
>>
>> 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 <ni...@gmail.com>
>> 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
>> nicoschl@gmail.com <ma...@gmail.com>
>>
>>
>> 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 <ni...@gmail.com>
>> 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
>>>> nicoschl@gmail.com
>>>>
>>>>
>>>> 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
>>>>
>>
Re: DeltaSpike Data - Custom PrePersistAuditListener and PreUpdateAuditListener
Posted by "John D. Ament" <jo...@apache.org>.
Gah shoot, sorry about that. It won't work because its a package private
class, and the classloader will block it.
I'll get something in to fix this, unfortunately it won't work until my
change is in. Please do make sure to raise an issue in JIRA so I don't
lose track. Thanks for checking it out.
John
On Tue, Dec 20, 2016 at 4:07 PM Nico Schlebusch <ni...@gmail.com> wrote:
> Hi John,
>
> Thanks for the suggestion on vetoing the TimestampsProvider, but there is
> a new problem with my approach or lack of understanding of Portable
> Extensions.
>
> I first created the portable extension inside my own package structure,
> but then the compiler fails to resolve TimestampsProvider because it is a
> package protected class. I then moved my extension into the same package
> (org.apache.deltaspike.data.impl.audit) as TimestampsProvider but then got
> this exception on deployment
>
> Caused by: java.lang.IllegalAccessError: tried to access class
> org.apache.deltaspike.data.impl.audit.PrincipalProvider from class
> org.apache.deltaspike.data.impl.audit.VetoDeltaSpikeAuditProvidersExtension
> at
> org.apache.deltaspike.data.impl.audit.VetoDeltaSpikeAuditProvidersExtension.rejectPrincipalProvider(VetoDeltaSpikeAuditProvidersExtension.java:43)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.lang.reflect.Method.invoke(Method.java:498)
> at
> org.jboss.weld.injection.StaticMethodInjectionPoint.invoke(StaticMethodInjectionPoint.java:88)
>
> I read somewhere that happens when the classes aren't loaded with the same
> classloader.
>
> Any other ideas on how to veto the TimestampsProvider?
>
>
> Kind regards,
> Nico Schlebusch
> nicoschl@gmail.com
>
>
> On 20/12/2016 17:23, John D. Ament wrote:
>
> 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 <ni...@gmail.com>
> 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
> nicoschl@gmail.com <ma...@gmail.com>
>
>
> 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 <ni...@gmail.com>
> 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
> >> nicoschl@gmail.com
> >>
> >>
> >> 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
> >>
>
>
>
Re: DeltaSpike Data - Custom PrePersistAuditListener and
PreUpdateAuditListener
Posted by Nico Schlebusch <ni...@gmail.com>.
Hi John,
Thanks for the suggestion on vetoing the TimestampsProvider, but there
is a new problem with my approach or lack of understanding of Portable
Extensions.
I first created the portable extension inside my own package structure,
but then the compiler fails to resolve TimestampsProvider because it is
a package protected class. I then moved my extension into the same
package (org.apache.deltaspike.data.impl.audit) as TimestampsProvider
but then got this exception on deployment
Caused by: java.lang.IllegalAccessError: tried to access class
org.apache.deltaspike.data.impl.audit.PrincipalProvider from class
org.apache.deltaspike.data.impl.audit.VetoDeltaSpikeAuditProvidersExtension
at
org.apache.deltaspike.data.impl.audit.VetoDeltaSpikeAuditProvidersExtension.rejectPrincipalProvider(VetoDeltaSpikeAuditProvidersExtension.java:43)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at
org.jboss.weld.injection.StaticMethodInjectionPoint.invoke(StaticMethodInjectionPoint.java:88)
I read somewhere that happens when the classes aren't loaded with the
same classloader.
Any other ideas on how to veto the TimestampsProvider?
Kind regards,
Nico Schlebusch
nicoschl@gmail.com <ma...@gmail.com>
On 20/12/2016 17:23, John D. Ament wrote:
> 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 <nicoschl@gmail.com
> <ma...@gmail.com>> 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
> nicoschl@gmail.com <ma...@gmail.com>
> <mailto:nicoschl@gmail.com <ma...@gmail.com>>
>
>
> 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
> <nicoschl@gmail.com <ma...@gmail.com>> 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
> >> nicoschl@gmail.com <ma...@gmail.com>
> >>
> >>
> >> 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
> >>
>
Re: DeltaSpike Data - Custom PrePersistAuditListener and PreUpdateAuditListener
Posted by "John D. Ament" <jo...@apache.org>.
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 <ni...@gmail.com> 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
> nicoschl@gmail.com <ma...@gmail.com>
>
>
> 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 <ni...@gmail.com>
> 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
> >> nicoschl@gmail.com
> >>
> >>
> >> 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 <ni...@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 <ma...@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 <ma...@gmail.com>
> >>>
> >>>
> >>
> >>
> >>
>
>
>
Re: DeltaSpike Data - Custom PrePersistAuditListener and
PreUpdateAuditListener
Posted by Nico Schlebusch <ni...@gmail.com>.
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
nicoschl@gmail.com <ma...@gmail.com>
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 <ni...@gmail.com> 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
>> nicoschl@gmail.com
>>
>>
>> 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 <ni...@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 <ma...@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 <ma...@gmail.com>
>>>
>>>
>>
>>
>>
Re: DeltaSpike Data - Custom PrePersistAuditListener and PreUpdateAuditListener
Posted by "John D. Ament" <jo...@apache.org>.
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 <ni...@gmail.com> 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
> nicoschl@gmail.com
>
>
> 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 <ni...@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 <ma...@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 <ma...@gmail.com>
> >
> >
>
>
>
>
>
Re: DeltaSpike Data - Custom PrePersistAuditListener and
PreUpdateAuditListener
Posted by Nico Schlebusch <ni...@gmail.com>.
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
nicoschl@gmail.com <ma...@gmail.com>
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 <nicoschl@gmail.com
> <ma...@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 <ma...@gmail.com>
> <mailto:nicoschl@gmail.com <ma...@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 <ma...@gmail.com>
> <mailto:nicoschl@gmail.com <ma...@gmail.com>>
> >
> >
>
>
Re: DeltaSpike Data - Custom PrePersistAuditListener and PreUpdateAuditListener
Posted by "John D. Ament" <jo...@apache.org>.
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 <ni...@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 <ma...@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 <ma...@gmail.com>
> >
> >
>
>
>
Re: DeltaSpike Data - Custom PrePersistAuditListener and
PreUpdateAuditListener
Posted by Nico Schlebusch <ni...@gmail.com>.
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 <ma...@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 <ma...@gmail.com>
>
>