Thanks. It looks like I was doing it right, but it just wasn't working for me
using Cayenne 3.1M2.
For now I'm generating code in the validation methods. Which given the
operations I'm doing, might actually be a better place. What I'm doing is
automatically setting or updating fields used internally but in the external
business logic: creationDate, lastModDate, and modCount. The more I think about
it the more putting these specific operations into the generated superclass
template makes sense.
Joe
On Aug 4, 2011, at 5:03 AM, Dzmitry Kazimirchyk wrote:
> Hi Joe,
>
> Behaviour that you've described seems little bit strange to me. Trying to
> reproduce it I've written following:
>
> ObjEntity in my map.xml:
>
> <obj-entity name="Artist" className="org.test.cayenne.persistent.Artist"
> dbEntityName="Artist">
> <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
> <entity-listener class="org.test.cayenne.listen.TestListener">
> <pre-persist method-name="onPrePersist"/>
> <pre-update method-name="onPreUpdate"/>
> </entity-listener>
> </obj-entity>
>
> Also I registered same listener for DataMap.
>
> <entity-listener class="org.test.cayenne.listen.TestListener">
> <pre-persist method-name="onPrePersist"/>
> <pre-update method-name="onPreUpdate"/>
> </entity-listener>
>
> The listener class itself:
>
> public class TestListener {
>
> void onPrePersist (Object object) {
> System.out.println("pre-persist");
> }
>
> void onPreUpdate (Object object) {
> System.out.println("pre-update");
> }
> }
>
> Place where events are actually triggered:
>
> ServerRuntime cayenneRuntime = new
> ServerRuntime("cayenne-testDomain.xml");
>
> ObjectContext context = cayenneRuntime.getContext();
>
> // testing persist events
> Artist a = context.newObject(Artist.class);
> context.commitChanges();
>
> //testing update events
> a.setName("name");
> context.commitChanges();
>
> Both pre-persist and pre-update events were triggered correctly calling
> corresponding listener methods. I've tried this also for other events but got
> the same result.
> Am I missing something important in your particular case?
>
> On 08/03/2011 11:04 PM, Joseph Senecal wrote:
>> Perhaps I'm just missing something simple. I've tried using individual
>> listener configurations, and they don't work either.
>>
>> Here is a sample entry:
>> <entity-listener class="com.apple.mqm.db.PDCAListener">
>> <pre-persist method-name="onPrePersist"/>
>> <pre-update method-name="onPreUpdate"/>
>> </entity-listener>
>>
>>
>> And here is my listener class:
>> package com.apple.mqm.db;
>>
>> import java.util.Date;
>>
>> import org.apache.cayenne.CayenneDataObject;
>>
>> public class PDCAListener {
>>
>> void onPrePersist (Object object) {
>> CayenneDataObject dataObject = (CayenneDataObject) object;
>> if (dataObject.readProperty(Product.CREATION_DATE_PROPERTY) ==
>> null) {
>>
>> dataObject.writeProperty(Product.CREATION_DATE_PROPERTY, new Date());
>> }
>> if (dataObject.readProperty(Product.LAST_MOD_DATE_PROPERTY) ==
>> null) {
>>
>> dataObject.writeProperty(Product.LAST_MOD_DATE_PROPERTY, new Date());
>> }
>> dataObject.writeProperty(Product.MOD_COUNT_PROPERTY, 1);
>> }
>>
>> void onPreUpdate (Object object) {
>> CayenneDataObject dataObject = (CayenneDataObject) object;
>> dataObject.writeProperty(Product.LAST_MOD_DATE_PROPERTY, new
>> Date());
>> dataObject.writeProperty(Product.MOD_COUNT_PROPERTY,
>> ((Integer)dataObject.readProperty(Product.LAST_MOD_DATE_PROPERTY))+1);
>> }
>> }
>>
>>
>> I don't have any code to activate the listeners. When testing I'm getting a
>> validation error that for a field that this listener sets onPrePersist. And
>> I never reach a breakpoint in the listener code.
>>
>> Joe
>>
>>
>> On Aug 3, 2011, at 11:12 AM, Andrus Adamchik wrote:
>>
>>> Ok, we'll need to re-test this case, and implement the missing registration
>>> API.
>>>
>>> On Aug 3, 2011, at 9:09 PM, Joseph Senecal wrote:
>>>> Andrus,
>>>>
>>>> Yes, I was using a per DataMap listener.
>>>>
>>>> I'll try using individual class listeners for the prototype and see how
>>>> that works.
>>>>
>>>> These listeners are really part of the basic operation of the DB
>>>> interface, so they are common to all programs using the database.
>>>> Currently I'm considering having the template generate the listener
>>>> methods in each class, along with code that will install the listener for
>>>> that class the first time the class is referenced (probably using a static
>>>> initializer). This will allow the listener methods to be customized for
>>>> each class instead of having to check the model. Annotations will help
>>>> there.
>>>>
>>>> Joe
>>>>
>>>> On Aug 3, 2011, at 10:50 AM, Andrus Adamchik wrote:
>>>>
>>>>> Hi Joe,
>>>>>
>>>>> On Aug 3, 2011, at 10:29 AM, Joseph Senecal wrote:
>>>>>
>>>>>> I'm trying to configure a single listener object to listen to a couple
>>>>>> of events for all objects. This is to update modCounts and lastModTimes
>>>>>> just before the commit.
>>>>>>
>>>>>> The documentation says this is configured in the Cayenne modeler, but
>>>>>> doesn't explain how. I found how to specify a class and methods, but it
>>>>>> doesn't seem to be getting called.
>>>>> This is odd. This certainly works for me. Here is an example from one of
>>>>> my map.xml files (created by the Modeler) :
>>>>>
>>>>> This part is a listener within<obj-enntity> tags:
>>>>>
>>>>> <entity-listener class="com.foo.listener.MyListener">
>>>>> <post-persist method-name="objectPostPersistCallback"/>
>>>>> </entity-listener>
>>>>>
>>>>> This part is callbacks on persistent objects themselves:
>>>>>
>>>>> <post-add method-name="onPostAdd"/>
>>>>> <pre-update method-name="onPreUpdate"/>
>>>>>
>>>>> These are per-entity callbacks/listeners. Are you setting a listener per
>>>>> DataMap? (I personally haven't used "global" listeners, but those should
>>>>> work too). Could you confirm - we'll re-test this case then.
>>>>>
>>>>>> I can see how to do it programmatically, but is there a cleaner solution
>>>>>> that I'm missing?
>>>>> Personally I am moving to setting everything programmatically, as it
>>>>> allows me to have different listeners for the same shared entities in
>>>>> different Java projects. So my preferred method is the latest 3.1M2 API
>>>>> based on annotations:
>>>>>
>>>>> runtime.getChannel().getEntityResolver().getCallbackRegistry().addListener(listener)
>>>>>
>>>>> But again - this is for per-entity listeners. Not per-DataMap. (Which
>>>>> reminds me - we need to support this flavor in per-DataMap case).
>>>>>
>>>>> Cheers,
>>>>> Andrus
>>>>
>