I'm not giving up on them, just running out of time to work on the issue. I
have a tight deadline for delivering a working prototype to test the concept.
After that's done I can figure out what the best way to do something is, and go
back and make that work. Listeners do look like a great way for separate code
sections to watch what's happening to each other.
Right now, I'm fighting against the caching hanging on to empty results
(separate thread). Trying to find a workaround.
Joe
On Aug 4, 2011, at 10:45 AM, Andrus Adamchik wrote:
> Still odd. We were using trunk builds of Cayenne to test it, that are fairly
> close to M2 (and I don't see any recent listener-related bugfixes). So there
> has to be something else.
>
> Glad you found a workaround, still don't give up on the listeners in general
> - they do work. There has to be some simple reason why they didn't.
>
> Andrus
>
>
> On Aug 4, 2011, at 8:21 PM, Joseph Senecal wrote:
>> 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
>>>>>>
>>>
>>
>>
>