You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cayenne.apache.org by Andrey Razumovsky <ra...@gmail.com> on 2009/06/01 17:09:47 UTC
Non-physical delete... again
Hi,
We've discussed this time ago, but I'm back now with some ideas.
Current situation:
I have to use special boolean column named "deleted" in all DB tables. That
is, I never (or very rarely) do something like "DELETE FROM ..." or
"context.deleteObject()", instead I do "UPDATE... SET deleted=true" or
cdo.setDeleted(true). To select only undeleted records, I add qualifier like
"deleted=true" to every ObjEntity. Also I add pre-update listeners to all
entities which unregisters object and processes delete rules (also
respective to 'deleted' field) if 'deleted' flag is set.
It is obvious that Cayenne cannot completely handle this situation. One
example is CAY-1109, but it can be workarounded as described above. More
serious problems are:
- I cannot use properly flattened relationships, because 'deleted' qualifier
is not applied to DBEntities selection (e.g. in 'medium' table of
many-to-many relationship)
- flattened expressions, e.g. toArtist.name="Rublev" also miss that
qualifier
- there is no objects with DELETED state, only with MODIFIED
...and so on.
I faced this situation since the first days I used Cayenne. Now when I
thought about this a bit, I think I can handle it with two new features. I'm
not sure they completely match Cayenne paradigm, but...
1. DBEntity qualifier. This is same as ObjEntity qualifier, but applied
every time DBentity is being added to select sql. I will add DBEntity
qualifier 'deleted=false' and drop current ObjEntity's
2. Deletion strategy for DataDomain. This means I do not always fire
DeleteAction, but maybe something else (update action in my case).
Any comments much appreciated.
Thanks,
Andrey
Re: IOC container
Posted by Michael Gentry <mg...@masslight.net>.
I think getting rid of DataDomains (at least in the Modeler) ties into
my #1 here:
http://markmail.org/message/wf7y73rgorj4bi4h
mrg
On Mon, Nov 16, 2009 at 9:43 AM, Andrus Adamchik <an...@objectstyle.org> wrote:
> And finally, unrelated, but since DataDomains were mentioned... I've been
> thinking to do away with multiple DataDomains. They are really independent
> stacks, so why bother keeping them together in one project. The users can
> start multiple Cayenne stacks instead.
Re: IOC container
Posted by Andrus Adamchik <an...@objectstyle.org>.
Yeah, it's been briefly mentioned in this thread: http://markmail.org/message/xyyixpaolg45cj4x
The spec jar is just 4K. The annotations that I used are compatible
with it, so if during development we decide it makes sense to stay
standard-compliant in this case, it won't be a problem to switch.
(BTW, SVN is back up and I checked in the remaining provider code).
Andrus
On Nov 16, 2009, at 8:54 AM, Andrey Razumovsky wrote:
> Hi,
>
> I'm not sure it will be helpful, but there's JSR-330 spec for that
> (instead
> of borrowing straightly from Guice):
> http://jcp.org/aboutJava/communityprocess/final/jsr330/index.html
>
> It defines several useful classes and annotations, as @Inject and
> Provider<T>
>
> 2009/11/16 Andrus Adamchik <an...@objectstyle.org>
>
>> Just for kicks wrote a simple DI container for Cayenne. I checked
>> it in
>> partially to sanbdox folder until the ASF SVN repo went down (
>> http://monitoring.apache.org/), so I'll commit the rest on Monday, or
>> whenever SVN becomes available.
>>
>> This no-frills DI container took me only a couple of hours to write
>> (it
>> borrows some Guice API, but implementation is all mine). It supports
>>
>> * annotation-based field dependency injection
>> * binding interfaces to implementation classes via fluent API
>> * binding interfaces to "provider" (same as "factory") classes
>> * merging multiple DI "modules".
>>
>> The whole thing is only 14K after compilation (so it beats all full
>> featured DI containers in size). Of course that's because it
>> doesn't have
>> all the fancy stuff (of which we'll add at least a few more things)
>> such as
>> constructor injection, dependency cycle resolving, dynamic interface
>> proxies, bound object lifecycle, integration with Spring, etc.
>> Since we are
>> not planning a general purpose container, we might survive without
>> most of
>> those.
>>
>> Here is how the current Configuration class might look like when it
>> is
>> based on DI:
>>
>> public class Configuration {
>>
>> private Injector injector;
>>
>> public Configuration() {
>> this(new CayenneModule());
>> }
>>
>> public Configuration(Module... modules) {
>> this.injector = DIBootstrap.createInjector(modules);
>> }
>>
>> public DataChannel getDataChannel() {
>> return injector.getInstance(DataChannel.class);
>> }
>>
>> public ObjectContext getNewContext() {
>> return injector.getInstance(ObjectContext.class);
>> }
>>
>> // we may create getters for other "services" if we need to
>> }
>>
>> And the actual configuration class (aka "module") used above:
>>
>> public class CayenneModule implements Module {
>>
>> public void configure(Binder binder) {
>>
>> binder.bind(EventManager.class).to(EventManagerImpl.class);
>> binder.bind(DataChannel.class).to(DataDomain.class);
>>
>> binder.bind(QueryCache.class).toProvider(LRUCacheFactory.class);
>>
>> binder.bind(QueryLogger.class).toProvider(FancyLogger.class);
>> // an so on...
>> }
>> }
>>
>> "CayenneModule" is what users can override (e.g. simply subclass),
>> providing alternative implementations for some services.
>>
>> The next step in this prototype would be an attempt to define the
>> current
>> Cayenne stack in terms of DI.
>>
>> Andrus
>>
>>
>> On Oct 27, 2009, at 11:01 PM, Kevin Menard wrote:
>>
>> On Sun, Oct 25, 2009 at 5:05 PM, Andrus Adamchik <andrus@objectstyle.org
>> >
>>> wrote:
>>>
>>> And I just discovered that both Spring (3.0RC1) and Juice (trunk)
>>> support
>>>> the annotations from this JSR. So it could make sense for us to
>>>> use these
>>>> annotations internally as well. Couldn't dig any info on the
>>>> Tapestry IoC
>>>> support for this JSR, but they are on the JSR "support group", so
>>>> at
>>>> least
>>>> they are watching it.
>>>>
>>>
>>> Thiago, the Tapestry member on the support group, just learned
>>> that it
>>> had been approved. Howard didn't even know the JSR existed.
>>> There's
>>> no discussion on adding in the annotation support to Tapestry IoC
>>> and
>>> I suspect it will happen, but Tapestry is behind the ball on that
>>> one.
>>>
>>> --
>>> Kevin
>>>
>>>
>>
>
>
> --
> Andrey
Re: IOC container
Posted by Andrey Razumovsky <ra...@gmail.com>.
Hi,
I'm not sure it will be helpful, but there's JSR-330 spec for that (instead
of borrowing straightly from Guice):
http://jcp.org/aboutJava/communityprocess/final/jsr330/index.html
It defines several useful classes and annotations, as @Inject and
Provider<T>
2009/11/16 Andrus Adamchik <an...@objectstyle.org>
> Just for kicks wrote a simple DI container for Cayenne. I checked it in
> partially to sanbdox folder until the ASF SVN repo went down (
> http://monitoring.apache.org/), so I'll commit the rest on Monday, or
> whenever SVN becomes available.
>
> This no-frills DI container took me only a couple of hours to write (it
> borrows some Guice API, but implementation is all mine). It supports
>
> * annotation-based field dependency injection
> * binding interfaces to implementation classes via fluent API
> * binding interfaces to "provider" (same as "factory") classes
> * merging multiple DI "modules".
>
> The whole thing is only 14K after compilation (so it beats all full
> featured DI containers in size). Of course that's because it doesn't have
> all the fancy stuff (of which we'll add at least a few more things) such as
> constructor injection, dependency cycle resolving, dynamic interface
> proxies, bound object lifecycle, integration with Spring, etc. Since we are
> not planning a general purpose container, we might survive without most of
> those.
>
> Here is how the current Configuration class might look like when it is
> based on DI:
>
> public class Configuration {
>
> private Injector injector;
>
> public Configuration() {
> this(new CayenneModule());
> }
>
> public Configuration(Module... modules) {
> this.injector = DIBootstrap.createInjector(modules);
> }
>
> public DataChannel getDataChannel() {
> return injector.getInstance(DataChannel.class);
> }
>
> public ObjectContext getNewContext() {
> return injector.getInstance(ObjectContext.class);
> }
>
> // we may create getters for other "services" if we need to
> }
>
> And the actual configuration class (aka "module") used above:
>
> public class CayenneModule implements Module {
>
> public void configure(Binder binder) {
> binder.bind(EventManager.class).to(EventManagerImpl.class);
> binder.bind(DataChannel.class).to(DataDomain.class);
>
> binder.bind(QueryCache.class).toProvider(LRUCacheFactory.class);
>
> binder.bind(QueryLogger.class).toProvider(FancyLogger.class);
> // an so on...
> }
> }
>
> "CayenneModule" is what users can override (e.g. simply subclass),
> providing alternative implementations for some services.
>
> The next step in this prototype would be an attempt to define the current
> Cayenne stack in terms of DI.
>
> Andrus
>
>
> On Oct 27, 2009, at 11:01 PM, Kevin Menard wrote:
>
> On Sun, Oct 25, 2009 at 5:05 PM, Andrus Adamchik <an...@objectstyle.org>
>> wrote:
>>
>> And I just discovered that both Spring (3.0RC1) and Juice (trunk) support
>>> the annotations from this JSR. So it could make sense for us to use these
>>> annotations internally as well. Couldn't dig any info on the Tapestry IoC
>>> support for this JSR, but they are on the JSR "support group", so at
>>> least
>>> they are watching it.
>>>
>>
>> Thiago, the Tapestry member on the support group, just learned that it
>> had been approved. Howard didn't even know the JSR existed. There's
>> no discussion on adding in the annotation support to Tapestry IoC and
>> I suspect it will happen, but Tapestry is behind the ball on that one.
>>
>> --
>> Kevin
>>
>>
>
--
Andrey
Re: IOC container
Posted by Andrus Adamchik <an...@objectstyle.org>.
On Nov 16, 2009, at 4:43 PM, Andrus Adamchik wrote:
> I don't have all the details yet, but the container API will be
> extended as needed to fit our needs. For now I am thinking that all
> cases where we need to access objects by name, will be delegated to
> Configuration and other objects outside container. The container may
> store maps of all names, and Configuration will be a frontend to
> read from those maps.
I should also mention that I am not fully clear yet about a separation
between the "container services" and "model objects" defined in the
XML project. Certain things (such as JGroups configuration) do not
belong in the project and should be re-classified as container
services. DataDomain / DataNodes are somewhat in the middle. Their
structure is defined by the user, but Cayenne injects all services
they need to operate.
Will need to play with it a bit more, but the direction is to keep the
environment agnostic model (DataMap) separate from environment-
specific stuff (access stack). Modeling access stack in the modeler is
a nice shortcut to get people started, but doesn't address JEE
environment complexity well.
Andrus
Re: IOC container
Posted by Andrus Adamchik <an...@objectstyle.org>.
Do you mean multiple DataDomains?
I don't have all the details yet, but the container API will be
extended as needed to fit our needs. For now I am thinking that all
cases where we need to access objects by name, will be delegated to
Configuration and other objects outside container. The container may
store maps of all names, and Configuration will be a frontend to read
from those maps.
But if we find that extending the container is beneficial, we can do
that too. E.g. I am planning something similar to Tapestry
configurations for the users to register/override ExtendedTypes, so
that the users don't have to redefine all types if they need to add
just one extra object.
Also to ensure we are on the same page, I am not planning app-facing
injection, just internal injection of Cayenne classes between
themselves. I.e. we won't inject anything in an app class that is
calling an ObjectContext (unless it is an override for the standard
service).
And finally, unrelated, but since DataDomains were mentioned... I've
been thinking to do away with multiple DataDomains. They are really
independent stacks, so why bother keeping them together in one
project. The users can start multiple Cayenne stacks instead.
Andrus
On Nov 16, 2009, at 4:28 PM, Michael Gentry wrote:
> How are you envisioning injecting an ObjectContext for different
> DataNodes, etc?
>
> Thanks,
>
> mrg
>
>
> On Sun, Nov 15, 2009 at 4:57 PM, Andrus Adamchik <andrus@objectstyle.org
> > wrote:
>> Just for kicks wrote a simple DI container for Cayenne. I checked
>> it in
>> partially to sanbdox folder until the ASF SVN repo went down
>> (http://monitoring.apache.org/), so I'll commit the rest on Monday,
>> or
>> whenever SVN becomes available.
>>
>> This no-frills DI container took me only a couple of hours to write
>> (it
>> borrows some Guice API, but implementation is all mine). It supports
>>
>> * annotation-based field dependency injection
>> * binding interfaces to implementation classes via fluent API
>> * binding interfaces to "provider" (same as "factory") classes
>> * merging multiple DI "modules".
>>
>> The whole thing is only 14K after compilation (so it beats all full
>> featured
>> DI containers in size). Of course that's because it doesn't have
>> all the
>> fancy stuff (of which we'll add at least a few more things) such as
>> constructor injection, dependency cycle resolving, dynamic interface
>> proxies, bound object lifecycle, integration with Spring, etc.
>> Since we are
>> not planning a general purpose container, we might survive without
>> most of
>> those.
>>
>> Here is how the current Configuration class might look like when it
>> is based
>> on DI:
>>
>> public class Configuration {
>>
>> private Injector injector;
>>
>> public Configuration() {
>> this(new CayenneModule());
>> }
>>
>> public Configuration(Module... modules) {
>> this.injector = DIBootstrap.createInjector(modules);
>> }
>>
>> public DataChannel getDataChannel() {
>> return injector.getInstance(DataChannel.class);
>> }
>>
>> public ObjectContext getNewContext() {
>> return injector.getInstance(ObjectContext.class);
>> }
>>
>> // we may create getters for other "services" if we need to
>> }
>>
>> And the actual configuration class (aka "module") used above:
>>
>> public class CayenneModule implements Module {
>>
>> public void configure(Binder binder) {
>>
>> binder.bind(EventManager.class).to(EventManagerImpl.class);
>> binder.bind(DataChannel.class).to(DataDomain.class);
>>
>> binder.bind(QueryCache.class).toProvider(LRUCacheFactory.class);
>>
>> binder.bind(QueryLogger.class).toProvider(FancyLogger.class);
>> // an so on...
>> }
>> }
>>
>> "CayenneModule" is what users can override (e.g. simply subclass),
>> providing
>> alternative implementations for some services.
>>
>> The next step in this prototype would be an attempt to define the
>> current
>> Cayenne stack in terms of DI.
>>
>> Andrus
>>
>> On Oct 27, 2009, at 11:01 PM, Kevin Menard wrote:
>>
>>> On Sun, Oct 25, 2009 at 5:05 PM, Andrus Adamchik <andrus@objectstyle.org
>>> >
>>> wrote:
>>>
>>>> And I just discovered that both Spring (3.0RC1) and Juice (trunk)
>>>> support
>>>> the annotations from this JSR. So it could make sense for us to
>>>> use these
>>>> annotations internally as well. Couldn't dig any info on the
>>>> Tapestry IoC
>>>> support for this JSR, but they are on the JSR "support group", so
>>>> at
>>>> least
>>>> they are watching it.
>>>
>>> Thiago, the Tapestry member on the support group, just learned
>>> that it
>>> had been approved. Howard didn't even know the JSR existed.
>>> There's
>>> no discussion on adding in the annotation support to Tapestry IoC
>>> and
>>> I suspect it will happen, but Tapestry is behind the ball on that
>>> one.
>>>
>>> --
>>> Kevin
>>>
>>
>>
>
Re: IOC container
Posted by Michael Gentry <mg...@masslight.net>.
How are you envisioning injecting an ObjectContext for different DataNodes, etc?
Thanks,
mrg
On Sun, Nov 15, 2009 at 4:57 PM, Andrus Adamchik <an...@objectstyle.org> wrote:
> Just for kicks wrote a simple DI container for Cayenne. I checked it in
> partially to sanbdox folder until the ASF SVN repo went down
> (http://monitoring.apache.org/), so I'll commit the rest on Monday, or
> whenever SVN becomes available.
>
> This no-frills DI container took me only a couple of hours to write (it
> borrows some Guice API, but implementation is all mine). It supports
>
> * annotation-based field dependency injection
> * binding interfaces to implementation classes via fluent API
> * binding interfaces to "provider" (same as "factory") classes
> * merging multiple DI "modules".
>
> The whole thing is only 14K after compilation (so it beats all full featured
> DI containers in size). Of course that's because it doesn't have all the
> fancy stuff (of which we'll add at least a few more things) such as
> constructor injection, dependency cycle resolving, dynamic interface
> proxies, bound object lifecycle, integration with Spring, etc. Since we are
> not planning a general purpose container, we might survive without most of
> those.
>
> Here is how the current Configuration class might look like when it is based
> on DI:
>
> public class Configuration {
>
> private Injector injector;
>
> public Configuration() {
> this(new CayenneModule());
> }
>
> public Configuration(Module... modules) {
> this.injector = DIBootstrap.createInjector(modules);
> }
>
> public DataChannel getDataChannel() {
> return injector.getInstance(DataChannel.class);
> }
>
> public ObjectContext getNewContext() {
> return injector.getInstance(ObjectContext.class);
> }
>
> // we may create getters for other "services" if we need to
> }
>
> And the actual configuration class (aka "module") used above:
>
> public class CayenneModule implements Module {
>
> public void configure(Binder binder) {
> binder.bind(EventManager.class).to(EventManagerImpl.class);
> binder.bind(DataChannel.class).to(DataDomain.class);
>
> binder.bind(QueryCache.class).toProvider(LRUCacheFactory.class);
> binder.bind(QueryLogger.class).toProvider(FancyLogger.class);
> // an so on...
> }
> }
>
> "CayenneModule" is what users can override (e.g. simply subclass), providing
> alternative implementations for some services.
>
> The next step in this prototype would be an attempt to define the current
> Cayenne stack in terms of DI.
>
> Andrus
>
> On Oct 27, 2009, at 11:01 PM, Kevin Menard wrote:
>
>> On Sun, Oct 25, 2009 at 5:05 PM, Andrus Adamchik <an...@objectstyle.org>
>> wrote:
>>
>>> And I just discovered that both Spring (3.0RC1) and Juice (trunk) support
>>> the annotations from this JSR. So it could make sense for us to use these
>>> annotations internally as well. Couldn't dig any info on the Tapestry IoC
>>> support for this JSR, but they are on the JSR "support group", so at
>>> least
>>> they are watching it.
>>
>> Thiago, the Tapestry member on the support group, just learned that it
>> had been approved. Howard didn't even know the JSR existed. There's
>> no discussion on adding in the annotation support to Tapestry IoC and
>> I suspect it will happen, but Tapestry is behind the ball on that one.
>>
>> --
>> Kevin
>>
>
>
Re: IOC container
Posted by Andrus Adamchik <an...@objectstyle.org>.
On Nov 21, 2009, at 11:49 PM, Andrus Adamchik wrote:
>
> * annotation-based field dependency injection
> * annotation-based constructor dependency injection
> * injection of map and list "configurations" (allows to add things
> like extra ExtendedTypes)
> * binding interfaces to implementation classes via fluent API
> * binding interfaces to "provider" (same as "factory") classes
> * merging multiple DI "modules"
> * dependency cycle detection
[one more]
* standard and user-defined scopes for bound objects.
Andrus
Re: IOC container
Posted by Andrus Adamchik <an...@objectstyle.org>.
Just finished all the main features I'd like to see in the DI
container. So here is a new checklist:
* annotation-based field dependency injection
* annotation-based constructor dependency injection
* injection of map and list "configurations" (allows to add things
like extra ExtendedTypes)
* binding interfaces to implementation classes via fluent API
* binding interfaces to "provider" (same as "factory") classes
* merging multiple DI "modules"
* dependency cycle detection
The container is still pretty small (all the di package classes are
~26K when compiled), and it seems like it was worth the effort (vs.
just using Guice for instance).
Now will try to find time to define a Cayenne stack based on the DI,
instead of the old Configuration:
https://svn.apache.org/repos/asf/cayenne/sandbox/cayenne-di/src/main/java/org/apache/cayenne/runtime/
Andrus
On Nov 15, 2009, at 11:57 PM, Andrus Adamchik wrote:
> Just for kicks wrote a simple DI container for Cayenne. I checked it
> in partially to sanbdox folder until the ASF SVN repo went down (http://monitoring.apache.org/
> ), so I'll commit the rest on Monday, or whenever SVN becomes
> available.
>
> This no-frills DI container took me only a couple of hours to write
> (it borrows some Guice API, but implementation is all mine). It
> supports
>
> * annotation-based field dependency injection
> * binding interfaces to implementation classes via fluent API
> * binding interfaces to "provider" (same as "factory") classes
> * merging multiple DI "modules".
>
> The whole thing is only 14K after compilation (so it beats all full
> featured DI containers in size). Of course that's because it doesn't
> have all the fancy stuff (of which we'll add at least a few more
> things) such as constructor injection, dependency cycle resolving,
> dynamic interface proxies, bound object lifecycle, integration with
> Spring, etc. Since we are not planning a general purpose container,
> we might survive without most of those.
>
> Here is how the current Configuration class might look like when it
> is based on DI:
>
> public class Configuration {
>
> private Injector injector;
>
> public Configuration() {
> this(new CayenneModule());
> }
>
> public Configuration(Module... modules) {
> this.injector = DIBootstrap.createInjector(modules);
> }
>
> public DataChannel getDataChannel() {
> return injector.getInstance(DataChannel.class);
> }
>
> public ObjectContext getNewContext() {
> return injector.getInstance(ObjectContext.class);
> }
>
> // we may create getters for other "services" if we need to
> }
>
> And the actual configuration class (aka "module") used above:
>
> public class CayenneModule implements Module {
>
> public void configure(Binder binder) {
> binder.bind(EventManager.class).to(EventManagerImpl.class);
> binder.bind(DataChannel.class).to(DataDomain.class);
> binder.bind(QueryCache.class).toProvider(LRUCacheFactory.class);
> binder.bind(QueryLogger.class).toProvider(FancyLogger.class);
> // an so on...
> }
> }
>
> "CayenneModule" is what users can override (e.g. simply subclass),
> providing alternative implementations for some services.
>
> The next step in this prototype would be an attempt to define the
> current Cayenne stack in terms of DI.
>
> Andrus
>
> On Oct 27, 2009, at 11:01 PM, Kevin Menard wrote:
>
>> On Sun, Oct 25, 2009 at 5:05 PM, Andrus Adamchik <andrus@objectstyle.org
>> > wrote:
>>
>>> And I just discovered that both Spring (3.0RC1) and Juice (trunk)
>>> support
>>> the annotations from this JSR. So it could make sense for us to
>>> use these
>>> annotations internally as well. Couldn't dig any info on the
>>> Tapestry IoC
>>> support for this JSR, but they are on the JSR "support group", so
>>> at least
>>> they are watching it.
>>
>> Thiago, the Tapestry member on the support group, just learned that
>> it
>> had been approved. Howard didn't even know the JSR existed. There's
>> no discussion on adding in the annotation support to Tapestry IoC and
>> I suspect it will happen, but Tapestry is behind the ball on that
>> one.
>>
>> --
>> Kevin
>>
>
>
Re: IOC container
Posted by Andrus Adamchik <an...@objectstyle.org>.
Just for kicks wrote a simple DI container for Cayenne. I checked it
in partially to sanbdox folder until the ASF SVN repo went down (http://monitoring.apache.org/
), so I'll commit the rest on Monday, or whenever SVN becomes available.
This no-frills DI container took me only a couple of hours to write
(it borrows some Guice API, but implementation is all mine). It supports
* annotation-based field dependency injection
* binding interfaces to implementation classes via fluent API
* binding interfaces to "provider" (same as "factory") classes
* merging multiple DI "modules".
The whole thing is only 14K after compilation (so it beats all full
featured DI containers in size). Of course that's because it doesn't
have all the fancy stuff (of which we'll add at least a few more
things) such as constructor injection, dependency cycle resolving,
dynamic interface proxies, bound object lifecycle, integration with
Spring, etc. Since we are not planning a general purpose container, we
might survive without most of those.
Here is how the current Configuration class might look like when it is
based on DI:
public class Configuration {
private Injector injector;
public Configuration() {
this(new CayenneModule());
}
public Configuration(Module... modules) {
this.injector = DIBootstrap.createInjector(modules);
}
public DataChannel getDataChannel() {
return injector.getInstance(DataChannel.class);
}
public ObjectContext getNewContext() {
return injector.getInstance(ObjectContext.class);
}
// we may create getters for other "services" if we need to
}
And the actual configuration class (aka "module") used above:
public class CayenneModule implements Module {
public void configure(Binder binder) {
binder.bind(EventManager.class).to(EventManagerImpl.class);
binder.bind(DataChannel.class).to(DataDomain.class);
binder.bind(QueryCache.class).toProvider(LRUCacheFactory.class);
binder.bind(QueryLogger.class).toProvider(FancyLogger.class);
// an so on...
}
}
"CayenneModule" is what users can override (e.g. simply subclass),
providing alternative implementations for some services.
The next step in this prototype would be an attempt to define the
current Cayenne stack in terms of DI.
Andrus
On Oct 27, 2009, at 11:01 PM, Kevin Menard wrote:
> On Sun, Oct 25, 2009 at 5:05 PM, Andrus Adamchik <andrus@objectstyle.org
> > wrote:
>
>> And I just discovered that both Spring (3.0RC1) and Juice (trunk)
>> support
>> the annotations from this JSR. So it could make sense for us to use
>> these
>> annotations internally as well. Couldn't dig any info on the
>> Tapestry IoC
>> support for this JSR, but they are on the JSR "support group", so
>> at least
>> they are watching it.
>
> Thiago, the Tapestry member on the support group, just learned that it
> had been approved. Howard didn't even know the JSR existed. There's
> no discussion on adding in the annotation support to Tapestry IoC and
> I suspect it will happen, but Tapestry is behind the ball on that one.
>
> --
> Kevin
>
Re: IOC container
Posted by Kevin Menard <ni...@gmail.com>.
On Sun, Oct 25, 2009 at 5:05 PM, Andrus Adamchik <an...@objectstyle.org> wrote:
> And I just discovered that both Spring (3.0RC1) and Juice (trunk) support
> the annotations from this JSR. So it could make sense for us to use these
> annotations internally as well. Couldn't dig any info on the Tapestry IoC
> support for this JSR, but they are on the JSR "support group", so at least
> they are watching it.
Thiago, the Tapestry member on the support group, just learned that it
had been approved. Howard didn't even know the JSR existed. There's
no discussion on adding in the annotation support to Tapestry IoC and
I suspect it will happen, but Tapestry is behind the ball on that one.
--
Kevin
Re: IOC container
Posted by Andrus Adamchik <an...@objectstyle.org>.
I've been pondering on how a Cayenne IoC "bridge" might work. My
initial idea was something like an inverted "commons-logging". Spring/
Guice/Tapestry users would explicitly bind a Cayenne stack to a
respective container using some "binder" class that we provide,
specific to each container (unlike commons-logging that tries to guess
the environment, causing occasional grief). In the absence of an
external container Cayenne will use a very simple bundled container,
essentially a map of interfaces vs services loaded from a classpath
file.
There's also a JSR-330 that aims at standardizing injection annotations:
http://www.infoq.com/news/2009/08/dependency-injection-javaee6
And I just discovered that both Spring (3.0RC1) and Juice (trunk)
support the annotations from this JSR. So it could make sense for us
to use these annotations internally as well. Couldn't dig any info on
the Tapestry IoC support for this JSR, but they are on the JSR
"support group", so at least they are watching it.
Anyways, will need to experiment with it a bit and see how easy it is
to redefine internal Cayenne "services" from the application.
Andrus
On Jun 3, 2009, at 3:02 PM, Andrus Adamchik wrote:
> Right... I envision lots of trouble integrating this into regular
> JEE ecosystem. My current idea is to use built-in container only if
> an app has no other container, and load Cayenne configs via an app
> container otherwise, so that there's only one configuration registry.
>
> Andrus
>
> On Jun 3, 2009, at 2:42 PM, Malcolm Edgar wrote:
>
>> One concern I have about introducing a 3rd party IoC container is
>> class loader conflicts which may occur with including a popular IoC
>> container. As Cayenne may have a dependency on version X but the
>> application uses version Y.
>>
>> regards Malcolm Edgar
>>
>> On Wed, Jun 3, 2009 at 6:03 AM, Andrus Adamchik <andrus@objectstyle.org
>> > wrote:
>>> I have a good opinion about Tapestry IoC approach in general
>>> (including the
>>> now defunct Hivemind), and I wanted to investigate Guice.
>>>
>>> There's some conflicting requirements to address here - we don't
>>> want to
>>> write/maintain our own IoC container, yet, we don't want to embed
>>> a huge
>>> third-party engine, of which we'll use only a subset of features.
>>> I'd like
>>> it to work standalone, as well as be able to integrate (or at
>>> least play
>>> well) with popular IoC containers (how many containers in one app
>>> is too
>>> many?). Then there's a matter of modeler support, which is adverse
>>> to
>>> annotations, and favors XML or other config files...
>>>
>>> All in all, I think assembling a core of Cayenne stack via such a
>>> container
>>> should open some interesting possibilities, beyond organizing
>>> current
>>> configuration.
>>>
>>> Andrus
>>>
>>>
>>>
>>> On Jun 2, 2009, at 6:53 PM, Robert Zeigler wrote:
>>>>
>>>> If you're really considering going the 3rd party ioc route, I
>>>> highly
>>>> recommend T5IOC.
>>>> Note that configuration is (typically) done via code in T5IOC,
>>>> but I find
>>>> it extremely flexible & powerful, while still being simple to use
>>>> (and
>>>> small! :).
>>>> If not that, then guice. I'd even go for pico (though preferably
>>>> not).
>>>> Anything but the monster that spring has become. ;)
>>>>
>>>> Robert
>>>>
>>>> On Jun 2, 2009, at 6/29:02 AM , Andrus Adamchik wrote:
>>>>
>>>>>
>>>>> On Jun 2, 2009, at 4:38 PM, Andrus Adamchik wrote:
>>>>>
>>>>>>>
>>>>>>> Modeler support will be covered by setting class name of
>>>>>>> strategy
>>>>>>
>>>>>> I am afraid this approach will be rather arbitrary to the end
>>>>>> user, so I
>>>>>> suggest we discuss it some more before putting it in Cayenne.
>>>>>> Marking an
>>>>>> entity to use "soft delete" based on some criteria is a clear and
>>>>>> understandable feature. Setting a "delete strategy" is not, and
>>>>>> will
>>>>>> contribute to confusion. This is totally be ok as a backend
>>>>>> extension point,
>>>>>> but I will hate to see that as a general use feature.
>>>>>
>>>>> In this context let me mention one idea for Cayenne 3.0 + N,
>>>>> that I've
>>>>> been thinking about for some time. I am taking this to a
>>>>> separate thread to
>>>>> avoid distraction from the soft delete discussion, which has
>>>>> only tangential
>>>>> relevance.
>>>>>
>>>>> Since we already have a bunch of extension points throughout the
>>>>> stack,
>>>>> some exposed via the Modeler (misplaced like cache JGroups
>>>>> config, or
>>>>> justified like Adapter config), and some are available only via
>>>>> the code, we
>>>>> need a way to reign them in. The standard way of doing that is
>>>>> via an IoC
>>>>> container.
>>>>>
>>>>> No, I don't want to bundle Spring with Cayenne, besides it has to
>>>>> integrate with the larger app ecosystem, so we still need to
>>>>> figure the
>>>>> technical details. But the point is that we will be able to
>>>>> provide a single
>>>>> place to configure all extension points, separate from the
>>>>> mapping. As
>>>>> unlike the mapping those parameters are often different for the
>>>>> same
>>>>> project, depending on the environment where it is deployed.
>>>>>
>>>>> Right now this place is cayenne.xml (and it might as well stay
>>>>> this way
>>>>> in the future), just that unlike say Spring config files, it has
>>>>> a rigid
>>>>> structure and is not generic enough to handle arbitrary
>>>>> extensions and
>>>>> dependencies. It was ok for the early versions of Cayenne, since
>>>>> there was
>>>>> only a few things you could change (data source factory and
>>>>> adapter I
>>>>> believe). But now something more powerful and clean is desirable.
>>>>>
>>>>> Just some raw thoughts.
>>>>>
>>>>> Andrus
>>>>
>>>>
>>>
>>>
>>
>
>
Re: IOC container
Posted by Andrus Adamchik <an...@objectstyle.org>.
Right... I envision lots of trouble integrating this into regular JEE
ecosystem. My current idea is to use built-in container only if an app
has no other container, and load Cayenne configs via an app container
otherwise, so that there's only one configuration registry.
Andrus
On Jun 3, 2009, at 2:42 PM, Malcolm Edgar wrote:
> One concern I have about introducing a 3rd party IoC container is
> class loader conflicts which may occur with including a popular IoC
> container. As Cayenne may have a dependency on version X but the
> application uses version Y.
>
> regards Malcolm Edgar
>
> On Wed, Jun 3, 2009 at 6:03 AM, Andrus Adamchik <andrus@objectstyle.org
> > wrote:
>> I have a good opinion about Tapestry IoC approach in general
>> (including the
>> now defunct Hivemind), and I wanted to investigate Guice.
>>
>> There's some conflicting requirements to address here - we don't
>> want to
>> write/maintain our own IoC container, yet, we don't want to embed a
>> huge
>> third-party engine, of which we'll use only a subset of features.
>> I'd like
>> it to work standalone, as well as be able to integrate (or at least
>> play
>> well) with popular IoC containers (how many containers in one app
>> is too
>> many?). Then there's a matter of modeler support, which is adverse to
>> annotations, and favors XML or other config files...
>>
>> All in all, I think assembling a core of Cayenne stack via such a
>> container
>> should open some interesting possibilities, beyond organizing current
>> configuration.
>>
>> Andrus
>>
>>
>>
>> On Jun 2, 2009, at 6:53 PM, Robert Zeigler wrote:
>>>
>>> If you're really considering going the 3rd party ioc route, I highly
>>> recommend T5IOC.
>>> Note that configuration is (typically) done via code in T5IOC, but
>>> I find
>>> it extremely flexible & powerful, while still being simple to use
>>> (and
>>> small! :).
>>> If not that, then guice. I'd even go for pico (though preferably
>>> not).
>>> Anything but the monster that spring has become. ;)
>>>
>>> Robert
>>>
>>> On Jun 2, 2009, at 6/29:02 AM , Andrus Adamchik wrote:
>>>
>>>>
>>>> On Jun 2, 2009, at 4:38 PM, Andrus Adamchik wrote:
>>>>
>>>>>>
>>>>>> Modeler support will be covered by setting class name of strategy
>>>>>
>>>>> I am afraid this approach will be rather arbitrary to the end
>>>>> user, so I
>>>>> suggest we discuss it some more before putting it in Cayenne.
>>>>> Marking an
>>>>> entity to use "soft delete" based on some criteria is a clear and
>>>>> understandable feature. Setting a "delete strategy" is not, and
>>>>> will
>>>>> contribute to confusion. This is totally be ok as a backend
>>>>> extension point,
>>>>> but I will hate to see that as a general use feature.
>>>>
>>>> In this context let me mention one idea for Cayenne 3.0 + N, that
>>>> I've
>>>> been thinking about for some time. I am taking this to a separate
>>>> thread to
>>>> avoid distraction from the soft delete discussion, which has only
>>>> tangential
>>>> relevance.
>>>>
>>>> Since we already have a bunch of extension points throughout the
>>>> stack,
>>>> some exposed via the Modeler (misplaced like cache JGroups
>>>> config, or
>>>> justified like Adapter config), and some are available only via
>>>> the code, we
>>>> need a way to reign them in. The standard way of doing that is
>>>> via an IoC
>>>> container.
>>>>
>>>> No, I don't want to bundle Spring with Cayenne, besides it has to
>>>> integrate with the larger app ecosystem, so we still need to
>>>> figure the
>>>> technical details. But the point is that we will be able to
>>>> provide a single
>>>> place to configure all extension points, separate from the
>>>> mapping. As
>>>> unlike the mapping those parameters are often different for the
>>>> same
>>>> project, depending on the environment where it is deployed.
>>>>
>>>> Right now this place is cayenne.xml (and it might as well stay
>>>> this way
>>>> in the future), just that unlike say Spring config files, it has
>>>> a rigid
>>>> structure and is not generic enough to handle arbitrary
>>>> extensions and
>>>> dependencies. It was ok for the early versions of Cayenne, since
>>>> there was
>>>> only a few things you could change (data source factory and
>>>> adapter I
>>>> believe). But now something more powerful and clean is desirable.
>>>>
>>>> Just some raw thoughts.
>>>>
>>>> Andrus
>>>
>>>
>>
>>
>
Re: IOC container
Posted by Malcolm Edgar <ma...@gmail.com>.
One concern I have about introducing a 3rd party IoC container is
class loader conflicts which may occur with including a popular IoC
container. As Cayenne may have a dependency on version X but the
application uses version Y.
regards Malcolm Edgar
On Wed, Jun 3, 2009 at 6:03 AM, Andrus Adamchik <an...@objectstyle.org> wrote:
> I have a good opinion about Tapestry IoC approach in general (including the
> now defunct Hivemind), and I wanted to investigate Guice.
>
> There's some conflicting requirements to address here - we don't want to
> write/maintain our own IoC container, yet, we don't want to embed a huge
> third-party engine, of which we'll use only a subset of features. I'd like
> it to work standalone, as well as be able to integrate (or at least play
> well) with popular IoC containers (how many containers in one app is too
> many?). Then there's a matter of modeler support, which is adverse to
> annotations, and favors XML or other config files...
>
> All in all, I think assembling a core of Cayenne stack via such a container
> should open some interesting possibilities, beyond organizing current
> configuration.
>
> Andrus
>
>
>
> On Jun 2, 2009, at 6:53 PM, Robert Zeigler wrote:
>>
>> If you're really considering going the 3rd party ioc route, I highly
>> recommend T5IOC.
>> Note that configuration is (typically) done via code in T5IOC, but I find
>> it extremely flexible & powerful, while still being simple to use (and
>> small! :).
>> If not that, then guice. I'd even go for pico (though preferably not).
>> Anything but the monster that spring has become. ;)
>>
>> Robert
>>
>> On Jun 2, 2009, at 6/29:02 AM , Andrus Adamchik wrote:
>>
>>>
>>> On Jun 2, 2009, at 4:38 PM, Andrus Adamchik wrote:
>>>
>>>>>
>>>>> Modeler support will be covered by setting class name of strategy
>>>>
>>>> I am afraid this approach will be rather arbitrary to the end user, so I
>>>> suggest we discuss it some more before putting it in Cayenne. Marking an
>>>> entity to use "soft delete" based on some criteria is a clear and
>>>> understandable feature. Setting a "delete strategy" is not, and will
>>>> contribute to confusion. This is totally be ok as a backend extension point,
>>>> but I will hate to see that as a general use feature.
>>>
>>> In this context let me mention one idea for Cayenne 3.0 + N, that I've
>>> been thinking about for some time. I am taking this to a separate thread to
>>> avoid distraction from the soft delete discussion, which has only tangential
>>> relevance.
>>>
>>> Since we already have a bunch of extension points throughout the stack,
>>> some exposed via the Modeler (misplaced like cache JGroups config, or
>>> justified like Adapter config), and some are available only via the code, we
>>> need a way to reign them in. The standard way of doing that is via an IoC
>>> container.
>>>
>>> No, I don't want to bundle Spring with Cayenne, besides it has to
>>> integrate with the larger app ecosystem, so we still need to figure the
>>> technical details. But the point is that we will be able to provide a single
>>> place to configure all extension points, separate from the mapping. As
>>> unlike the mapping those parameters are often different for the same
>>> project, depending on the environment where it is deployed.
>>>
>>> Right now this place is cayenne.xml (and it might as well stay this way
>>> in the future), just that unlike say Spring config files, it has a rigid
>>> structure and is not generic enough to handle arbitrary extensions and
>>> dependencies. It was ok for the early versions of Cayenne, since there was
>>> only a few things you could change (data source factory and adapter I
>>> believe). But now something more powerful and clean is desirable.
>>>
>>> Just some raw thoughts.
>>>
>>> Andrus
>>
>>
>
>
Re: IOC container
Posted by Andrus Adamchik <an...@objectstyle.org>.
I have a good opinion about Tapestry IoC approach in general
(including the now defunct Hivemind), and I wanted to investigate Guice.
There's some conflicting requirements to address here - we don't want
to write/maintain our own IoC container, yet, we don't want to embed a
huge third-party engine, of which we'll use only a subset of features.
I'd like it to work standalone, as well as be able to integrate (or at
least play well) with popular IoC containers (how many containers in
one app is too many?). Then there's a matter of modeler support, which
is adverse to annotations, and favors XML or other config files...
All in all, I think assembling a core of Cayenne stack via such a
container should open some interesting possibilities, beyond
organizing current configuration.
Andrus
On Jun 2, 2009, at 6:53 PM, Robert Zeigler wrote:
> If you're really considering going the 3rd party ioc route, I highly
> recommend T5IOC.
> Note that configuration is (typically) done via code in T5IOC, but I
> find it extremely flexible & powerful, while still being simple to
> use (and small! :).
> If not that, then guice. I'd even go for pico (though preferably
> not). Anything but the monster that spring has become. ;)
>
> Robert
>
> On Jun 2, 2009, at 6/29:02 AM , Andrus Adamchik wrote:
>
>>
>> On Jun 2, 2009, at 4:38 PM, Andrus Adamchik wrote:
>>
>>>>
>>>> Modeler support will be covered by setting class name of strategy
>>>
>>> I am afraid this approach will be rather arbitrary to the end
>>> user, so I suggest we discuss it some more before putting it in
>>> Cayenne. Marking an entity to use "soft delete" based on some
>>> criteria is a clear and understandable feature. Setting a "delete
>>> strategy" is not, and will contribute to confusion. This is
>>> totally be ok as a backend extension point, but I will hate to see
>>> that as a general use feature.
>>
>> In this context let me mention one idea for Cayenne 3.0 + N, that
>> I've been thinking about for some time. I am taking this to a
>> separate thread to avoid distraction from the soft delete
>> discussion, which has only tangential relevance.
>>
>> Since we already have a bunch of extension points throughout the
>> stack, some exposed via the Modeler (misplaced like cache JGroups
>> config, or justified like Adapter config), and some are available
>> only via the code, we need a way to reign them in. The standard way
>> of doing that is via an IoC container.
>>
>> No, I don't want to bundle Spring with Cayenne, besides it has to
>> integrate with the larger app ecosystem, so we still need to figure
>> the technical details. But the point is that we will be able to
>> provide a single place to configure all extension points, separate
>> from the mapping. As unlike the mapping those parameters are often
>> different for the same project, depending on the environment where
>> it is deployed.
>>
>> Right now this place is cayenne.xml (and it might as well stay this
>> way in the future), just that unlike say Spring config files, it
>> has a rigid structure and is not generic enough to handle arbitrary
>> extensions and dependencies. It was ok for the early versions of
>> Cayenne, since there was only a few things you could change (data
>> source factory and adapter I believe). But now something more
>> powerful and clean is desirable.
>>
>> Just some raw thoughts.
>>
>> Andrus
>
>
Re: IOC container
Posted by Robert Zeigler <ro...@roxanemy.com>.
If you're really considering going the 3rd party ioc route, I highly
recommend T5IOC.
Note that configuration is (typically) done via code in T5IOC, but I
find it extremely flexible & powerful, while still being simple to use
(and small! :).
If not that, then guice. I'd even go for pico (though preferably
not). Anything but the monster that spring has become. ;)
Robert
On Jun 2, 2009, at 6/29:02 AM , Andrus Adamchik wrote:
>
> On Jun 2, 2009, at 4:38 PM, Andrus Adamchik wrote:
>
>>>
>>> Modeler support will be covered by setting class name of strategy
>>
>> I am afraid this approach will be rather arbitrary to the end user,
>> so I suggest we discuss it some more before putting it in Cayenne.
>> Marking an entity to use "soft delete" based on some criteria is a
>> clear and understandable feature. Setting a "delete strategy" is
>> not, and will contribute to confusion. This is totally be ok as a
>> backend extension point, but I will hate to see that as a general
>> use feature.
>
> In this context let me mention one idea for Cayenne 3.0 + N, that
> I've been thinking about for some time. I am taking this to a
> separate thread to avoid distraction from the soft delete
> discussion, which has only tangential relevance.
>
> Since we already have a bunch of extension points throughout the
> stack, some exposed via the Modeler (misplaced like cache JGroups
> config, or justified like Adapter config), and some are available
> only via the code, we need a way to reign them in. The standard way
> of doing that is via an IoC container.
>
> No, I don't want to bundle Spring with Cayenne, besides it has to
> integrate with the larger app ecosystem, so we still need to figure
> the technical details. But the point is that we will be able to
> provide a single place to configure all extension points, separate
> from the mapping. As unlike the mapping those parameters are often
> different for the same project, depending on the environment where
> it is deployed.
>
> Right now this place is cayenne.xml (and it might as well stay this
> way in the future), just that unlike say Spring config files, it has
> a rigid structure and is not generic enough to handle arbitrary
> extensions and dependencies. It was ok for the early versions of
> Cayenne, since there was only a few things you could change (data
> source factory and adapter I believe). But now something more
> powerful and clean is desirable.
>
> Just some raw thoughts.
>
> Andrus
IOC container
Posted by Andrus Adamchik <an...@objectstyle.org>.
On Jun 2, 2009, at 4:38 PM, Andrus Adamchik wrote:
>>
>> Modeler support will be covered by setting class name of strategy
>
> I am afraid this approach will be rather arbitrary to the end user,
> so I suggest we discuss it some more before putting it in Cayenne.
> Marking an entity to use "soft delete" based on some criteria is a
> clear and understandable feature. Setting a "delete strategy" is
> not, and will contribute to confusion. This is totally be ok as a
> backend extension point, but I will hate to see that as a general
> use feature.
In this context let me mention one idea for Cayenne 3.0 + N, that I've
been thinking about for some time. I am taking this to a separate
thread to avoid distraction from the soft delete discussion, which has
only tangential relevance.
Since we already have a bunch of extension points throughout the
stack, some exposed via the Modeler (misplaced like cache JGroups
config, or justified like Adapter config), and some are available only
via the code, we need a way to reign them in. The standard way of
doing that is via an IoC container.
No, I don't want to bundle Spring with Cayenne, besides it has to
integrate with the larger app ecosystem, so we still need to figure
the technical details. But the point is that we will be able to
provide a single place to configure all extension points, separate
from the mapping. As unlike the mapping those parameters are often
different for the same project, depending on the environment where it
is deployed.
Right now this place is cayenne.xml (and it might as well stay this
way in the future), just that unlike say Spring config files, it has a
rigid structure and is not generic enough to handle arbitrary
extensions and dependencies. It was ok for the early versions of
Cayenne, since there was only a few things you could change (data
source factory and adapter I believe). But now something more powerful
and clean is desirable.
Just some raw thoughts.
Andrus
Re: Non-physical delete... again
Posted by Andrey Razumovsky <ra...@gmail.com>.
Seems we have same questions in second feature I wanted to implement -
qualifiers for DbEntities. Should they work for EJBQLs too? As far as I can
tell after looking at the code, current EJBQL doesn't use ObjEntity
qualifiers.
I can't think of anything better than implementing DbEntity qualifier as
simple string that will be ANDed with WHERE clauses for SELECT and JOIN
tables. This way we won't be able to handle any difference between different
DBMS. We just don't have "DB-based" expressions... Maybe you have better
ideas..?
Thanks,
Andrey
2009/6/3 Andrus Adamchik <an...@objectstyle.org>
>
> On Jun 3, 2009, at 4:12 PM, Andrey Razumovsky wrote:
>
>>
>>> Let's first decide which approach above we'll be using (1. intercept on
>>> commit or 2. intercept of anything "delete").
>>>
>>>
>> I see. What implemented now is "1.5 - intercept of anything
>> DeleteBatchQuery". This might be okay if we plan #2 someday. Actually I
>> want
>> this feature right now, and changing EJBQL nature might be tricky. So I
>> suggest we either end with #1 or commit current code, which is little part
>> of #2.
>>
>
> I suggest going with #1 then.
>
>
> Looking at this one more time, I agree. This is irrelevant for approach
>>> #1,
>>> but for #2 I think we can achieve what we need with a DataNode bound
>>> SQLActionVisitor, which allows to process all types of queries in a
>>> generic
>>> fashion (see below my notes on EJBQL).
>>>
>>>
>> The most common SQLActionVisitor is JdbcActionBuilder and it cannot
>> contain
>> reference to DataNode by design, as said before.
>>
>
> I meant this in a general sense. Your strategy class can have an anonymous
> inner class implementing SQLActionVisitor or something like that. Anyways,
> this is not applicable for #1 ... I think.
>
> Andrus
>
Re: Non-physical delete... again
Posted by Andrus Adamchik <an...@objectstyle.org>.
On Jun 3, 2009, at 4:12 PM, Andrey Razumovsky wrote:
>>
>> Let's first decide which approach above we'll be using (1.
>> intercept on
>> commit or 2. intercept of anything "delete").
>>
>
> I see. What implemented now is "1.5 - intercept of anything
> DeleteBatchQuery". This might be okay if we plan #2 someday.
> Actually I want
> this feature right now, and changing EJBQL nature might be tricky.
> So I
> suggest we either end with #1 or commit current code, which is
> little part
> of #2.
I suggest going with #1 then.
>> Looking at this one more time, I agree. This is irrelevant for
>> approach #1,
>> but for #2 I think we can achieve what we need with a DataNode bound
>> SQLActionVisitor, which allows to process all types of queries in a
>> generic
>> fashion (see below my notes on EJBQL).
>>
>
> The most common SQLActionVisitor is JdbcActionBuilder and it cannot
> contain
> reference to DataNode by design, as said before.
I meant this in a general sense. Your strategy class can have an
anonymous inner class implementing SQLActionVisitor or something like
that. Anyways, this is not applicable for #1 ... I think.
Andrus
Re: Non-physical delete... again
Posted by Andrey Razumovsky <ra...@gmail.com>.
>
>
>
> Let's first decide which approach above we'll be using (1. intercept on
> commit or 2. intercept of anything "delete").
>
I see. What implemented now is "1.5 - intercept of anything
DeleteBatchQuery". This might be okay if we plan #2 someday. Actually I want
this feature right now, and changing EJBQL nature might be tricky. So I
suggest we either end with #1 or commit current code, which is little part
of #2.
>
> Looking at this one more time, I agree. This is irrelevant for approach #1,
> but for #2 I think we can achieve what we need with a DataNode bound
> SQLActionVisitor, which allows to process all types of queries in a generic
> fashion (see below my notes on EJBQL).
>
The most common SQLActionVisitor is JdbcActionBuilder and it cannot contain
reference to DataNode by design, as said before. I should say that uploaded
"DN bounded OperationObserver" allows to pass DN to ALL queries.
"Processing" e.g. ebjql and batch in generic fashion currently seems
imposible to me :(. They can logically do the same, but implementation is
too different.
As I already said, both long-plan ways are OK for me, but I wish to be able
to intercept context commit action as fast as possible.
Re: Non-physical delete... again
Posted by Andrus Adamchik <an...@objectstyle.org>.
On Jun 3, 2009, at 3:00 PM, Andrey Razumovsky wrote:
> First, the main goal of the feature is to provide extension point for
> insert/update/delete queries of context commit process.
This is what I thought initially. But you mentioning intercepting
delete queries at the lower levels made me think your intent was to
make things more generic, and rewrite every single delete going
through the system irregardless of origin?
In any event, both approaches do make sense. The first one is ok short
term (3.0). The second one - long term, considering that we want any
batch delete queries, except maybe SQLTemplate and ProcedureQuery, to
change the state of objects in the context, which we are not doing
now, "performQuery" becomes sort of like "commitChanges". Right now we
need to pick one approach for 3.0, and follow it consistently.
> Currently *BatchQueries are responsible for those actions. But they
> can be used
> separately. Should we keep original batch queries (e.g. if they are
> invoked
> in context.performQuery()) work as they did, ignoring user-provided
> 'strategy'? Who knows. If so, we need to create different types of
> queries
> in DDFlushAction. Current implementation says "no". I can stand both
> ways.
Let's first decide which approach above we'll be using (1. intercept
on commit or 2. intercept of anything "delete").
> Second, where should user-provided code be attached? Certainly, not
> to a
> datamap, as we discussed before. And not to DbAdapter. DbAdapter was
> designed to handle differences between DBMS and we definitely want
> user-provided behaviour act on all DBMS. So that should be DD or DN
> (data-node). As an example, there is new SchemaUpdateStrategy which
> in some
> other way specifies how Cayenne should affect on DB. It is DN
> property.
Looking at this one more time, I agree. This is irrelevant for
approach #1, but for #2 I think we can achieve what we need with a
DataNode bound SQLActionVisitor, which allows to process all types of
queries in a generic fashion (see below my notes on EJBQL).
> Third, should we push this behavior to other actions, e.g. EJBQL? I
> don't
> think so. EJBQL is same as SQL(Template) but in terms of object
> language (as
> far as I know, it works through SQLTemplate). So it's more "raw" than
> context's actions.
That's the thing - EJBQL, for all its similarity to SQLTemplate, is
not "raw". We don't have lots of usable object API around it yet, but
it is as OO as SelectQuery or a BatchQuery. It can be unambiguously
"compiled" back into a tree of mapping objects. So if we go with
strategy 2, DeleteBatchQuery and deleting EJBQL are the same beasts.
> Fourth, how should we pass the strategy to the place where query
> actions are
> performed? This is tricky implementation problem. If we create
> separate
> queries for "batches with user behavior", it'll be simple. Currently
> it
> works, although code seems not very clear to me.
Let's first decide which approach above we'll be using, and then
discuss this.
Andrus
Re: Non-physical delete... again
Posted by Andrey Razumovsky <ra...@gmail.com>.
I'm a bit confused here. Let's try to make it clear.
First, the main goal of the feature is to provide extension point for
insert/update/delete queries of context commit process. Currently
*BatchQueries are responsible for those actions. But they can be used
separately. Should we keep original batch queries (e.g. if they are invoked
in context.performQuery()) work as they did, ignoring user-provided
'strategy'? Who knows. If so, we need to create different types of queries
in DDFlushAction. Current implementation says "no". I can stand both ways.
Second, where should user-provided code be attached? Certainly, not to a
datamap, as we discussed before. And not to DbAdapter. DbAdapter was
designed to handle differences between DBMS and we definitely want
user-provided behaviour act on all DBMS. So that should be DD or DN
(data-node). As an example, there is new SchemaUpdateStrategy which in some
other way specifies how Cayenne should affect on DB. It is DN property.
Third, should we push this behavior to other actions, e.g. EJBQL? I don't
think so. EJBQL is same as SQL(Template) but in terms of object language (as
far as I know, it works through SQLTemplate). So it's more "raw" than
context's actions.
Fourth, how should we pass the strategy to the place where query actions are
performed? This is tricky implementation problem. If we create separate
queries for "batches with user behavior", it'll be simple. Currently it
works, although code seems not very clear to me.
2009/6/3 Andrus Adamchik <an...@objectstyle.org>
> Sorry for jumping the gun. Let me take it back for a moment. I was still
> trying to understand how do we present this feature to a user, and where it
> fits in the overall design. Now after this discussion, I am clear on the
> intention (I think), and more comfortable with the suggested concept and
> implementation.
>
> So intercepting things at the DataNode level is ok. I am +1 on that.
>
> One more question (you've probably thought it through already). The
> existing extension point for changing low level query behavior is
> DbAdapter.getAction(Query query, DataNode node). Should we build on that
> instead of adding another strategy to the DataNode? This seems particularly
> promising, since there is also a very common batch delete/update query -
> EJBQLQuery, that we'd need to handle. SQLAction overriding can apply to any
> kind of query.
>
> Thoughts?
> Andrus
>
>
>
> On Jun 3, 2009, at 1:36 PM, Andrus Adamchik wrote:
>
>> On Jun 3, 2009, at 12:01 PM, Andrey Razumovsky wrote:
>>
>> I've never used that myself, but e.g. DeleteBatchQuery can be fired
>>> separately using context.performAction(..). It is public in .query
>>> package
>>> after all. I don't want to have different behaviors for that
>>>
>>
>> I disagree. I think we do want delete query to behave like delete query,
>> and use the soft delete strategy for the objects managed by the context.
>>
>> Andrus
>>
>
>
Re: Non-physical delete... again
Posted by Andrus Adamchik <an...@objectstyle.org>.
Sorry for jumping the gun. Let me take it back for a moment. I was
still trying to understand how do we present this feature to a user,
and where it fits in the overall design. Now after this discussion, I
am clear on the intention (I think), and more comfortable with the
suggested concept and implementation.
So intercepting things at the DataNode level is ok. I am +1 on that.
One more question (you've probably thought it through already). The
existing extension point for changing low level query behavior is
DbAdapter.getAction(Query query, DataNode node). Should we build on
that instead of adding another strategy to the DataNode? This seems
particularly promising, since there is also a very common batch delete/
update query - EJBQLQuery, that we'd need to handle. SQLAction
overriding can apply to any kind of query.
Thoughts?
Andrus
On Jun 3, 2009, at 1:36 PM, Andrus Adamchik wrote:
> On Jun 3, 2009, at 12:01 PM, Andrey Razumovsky wrote:
>
>> I've never used that myself, but e.g. DeleteBatchQuery can be fired
>> separately using context.performAction(..). It is public in .query
>> package
>> after all. I don't want to have different behaviors for that
>
> I disagree. I think we do want delete query to behave like delete
> query, and use the soft delete strategy for the objects managed by
> the context.
>
> Andrus
Re: Non-physical delete... again
Posted by Andrus Adamchik <an...@objectstyle.org>.
On Jun 3, 2009, at 12:01 PM, Andrey Razumovsky wrote:
> I've never used that myself, but e.g. DeleteBatchQuery can be fired
> separately using context.performAction(..). It is public in .query
> package
> after all. I don't want to have different behaviors for that
I disagree. I think we do want delete query to behave like delete
query, and use the soft delete strategy for the objects managed by the
context.
Andrus
Re: Non-physical delete... again
Posted by Andrey Razumovsky <ra...@gmail.com>.
I've never used that myself, but e.g. DeleteBatchQuery can be fired
separately using context.performAction(..). It is public in .query package
after all. I don't want to have different behaviors for that
2009/6/3 Andrus Adamchik <an...@objectstyle.org>
> Let me rephrase. What other cases do we want to handle with this strategy,
> in addition to "commit" (that triggers flush action)?
>
> Andrus
>
>
>
> On Jun 3, 2009, at 11:51 AM, Andrus Adamchik wrote:
>
>> On Jun 3, 2009, at 11:45 AM, Andrey Razumovsky wrote:
>>
>> Yes, but that will make factory working only in flush action, but not if
>>> it
>>> is fired from somewhere else.
>>>
>>
>> Correct. But why do we want to do it differently?
>>
>> Andrus
>>
>>
>>
>
Re: Non-physical delete... again
Posted by Andrus Adamchik <an...@objectstyle.org>.
Let me rephrase. What other cases do we want to handle with this
strategy, in addition to "commit" (that triggers flush action)?
Andrus
On Jun 3, 2009, at 11:51 AM, Andrus Adamchik wrote:
> On Jun 3, 2009, at 11:45 AM, Andrey Razumovsky wrote:
>
>> Yes, but that will make factory working only in flush action, but
>> not if it
>> is fired from somewhere else.
>
> Correct. But why do we want to do it differently?
>
> Andrus
>
>
Re: Non-physical delete... again
Posted by Andrus Adamchik <an...@objectstyle.org>.
On Jun 3, 2009, at 11:45 AM, Andrey Razumovsky wrote:
> Yes, but that will make factory working only in flush action, but
> not if it
> is fired from somewhere else.
Correct. But why do we want to do it differently?
Andrus
Re: Non-physical delete... again
Posted by Andrey Razumovsky <ra...@gmail.com>.
Yes, but that will make factory working only in flush action, but not if it
is fired from somewhere else. I've uploaded what I have now. Passing of node
is a quite blurry, but I can stand this solution
2009/6/3 Andrus Adamchik <an...@objectstyle.org>
>
> On Jun 3, 2009, at 11:24 AM, Andrus Adamchik wrote:
>
> You'd generate a BatchUpdateAction instead of delete or something like
>> that.
>>
>
> I mean a BatchUpdateQuery not Action.
>
>
Re: Non-physical delete... again
Posted by Andrus Adamchik <an...@objectstyle.org>.
On Jun 3, 2009, at 11:24 AM, Andrus Adamchik wrote:
> You'd generate a BatchUpdateAction instead of delete or something
> like that.
I mean a BatchUpdateQuery not Action.
Re: Non-physical delete... again
Posted by Andrus Adamchik <an...@objectstyle.org>.
> After all, batch queries are public and can
> be fired from anywhere, including context.performQuery(..).
Exactly, BatchQuery is just that - a query. And we probably do not
want to redefine how it is processed. So this leads me to think that
the logic fork should still happen somewhere inside
DataDomainFlushAction. You'd generate a BatchUpdateAction instead of
delete or something like that.
Andrus
On Jun 3, 2009, at 11:16 AM, Andrey Razumovsky wrote:
> It's not that easy as it sounds. BatchAction is born from BatchQuery
> (which
> is in .query package and does not have access to DataDomain/Node) and
> JDBCActionBuilder (which is logical part of JdbcAdapter, and also
> does not
> have access to DataDomain/Node). After all, batch queries are public
> and can
> be fired from anywhere, including context.performQuery(..). So it
> starts not
> with DataDomainFlushAction, but with DataNodeQueryAction. The best I
> could
> do was adding factory property to DataNode and passing it to action
> in query
> observer.
>
> 2009/6/2 Andrus Adamchik <an...@objectstyle.org>
>
>> I swiched to DataMap after I saw no quick access to DataDomain in
>>> BatchAction class.
>>>
>>
>> It all starts with DataDomainFlushAction, which has a reference to
>> DD, so
>> there should be a way to inject factory down the tree.
>>
>> I assume API changes in public classes of access.jdbc package are
>> allowed?
>>>
>>
>> Until we are in Beta, yes.
>>
>> Andrus
>>
>>
>>
>> On Jun 2, 2009, at 5:25 PM, Andrey Razumovsky wrote:
>>
>> I swiched to DataMap after I saw no quick access to DataDomain in
>>> BatchAction class. This needs futher investigation, we need to
>>> pass domain
>>> there somehow. I assume API changes in public classes of access.jdbc
>>> package
>>> are allowed?
>>>
>>> 2009/6/2 Andrus Adamchik <an...@objectstyle.org>
>>>
>>> Excellent. I have one comment (consistent with my position in the
>>>> previous
>>>> message). Configuration of the factory below should be attached
>>>> to the
>>>> stack
>>>> objects (e.g. DataDomain), not the mapping objects (DataMap):
>>>>
>>>> +
>>>> + /**
>>>> + * Sets factory for creating QueryBuilders
>>>> + */
>>>> + public void setQueryBuilderFactory(BatchQueryBuilderFactory
>>>> queryBuilderFactory) {
>>>> + this.queryBuilderFactory = queryBuilderFactory;
>>>> + }
>>>> +
>>>> + /**
>>>> + * @return factory for creating QueryBuilders. Might be null
>>>> + */
>>>> + public BatchQueryBuilderFactory getQueryBuilderFactory() {
>>>> + return queryBuilderFactory;
>>>> + }
>>>>
>>>> Cheers,
>>>> Andrus
>>>>
>>>> P.S. Maybe you can separately commit the @Deprecated part of the
>>>> patch
>>>> ;-)
>>>>
>>>>
>>>>
>>>> On Jun 2, 2009, at 5:07 PM, Andrey Razumovsky wrote:
>>>>
>>>> For not to be unsubstantiated, I uploaded my vision of the
>>>> feature. Note
>>>>
>>>>> that there is no modeler support. It allows to provide custom
>>>>> factory
>>>>> that
>>>>> creates builders of INSERT, UPDATE, DELETE queries. 'Soft-delete'
>>>>> factory
>>>>> is
>>>>> included.
>>>>> I do not say that 'soft delete' checkbox is not needed, but
>>>>> uploaded
>>>>> code
>>>>> is
>>>>> much more generic and allows to plug any behavior (maybe even
>>>>> Ari's
>>>>> proposed
>>>>> 'versions'). 'Soft' strategy can be configured with 'deleted'
>>>>> field name
>>>>> and
>>>>> will not fire UPDATE if such field does not exist in DB table.
>>>>>
>>>>> Please add your comments!
>>>>>
>>>>> Thanks,
>>>>> Andrey
>>>>>
>>>>> 2009/6/2 Andrus Adamchik <an...@objectstyle.org>
>>>>>
>>>>>
>>>>> On Jun 2, 2009, at 2:54 PM, Andrey Razumovsky wrote:
>>>>>>
>>>>>> But I'm no fan of adding some sort of 'soft' checkbox for
>>>>>> dbattributes
>>>>>>
>>>>>>
>>>>>>>
>>>>>>> I was suggesting marking entity with a "soft delete" checkbox
>>>>>>> (not
>>>>>> individual attribute - this would make no sense), and creating a
>>>>>> criteria
>>>>>> based on qualifier that references an attribute.
>>>>>>
>>>>>> Modeler support will be covered by setting class name of strategy
>>>>>>
>>>>>>
>>>>>>>
>>>>>>> I am afraid this approach will be rather arbitrary to the end
>>>>>>> user,
>>>>>> so I
>>>>>> suggest we discuss it some more before putting it in Cayenne.
>>>>>> Marking
>>>>>> an
>>>>>> entity to use "soft delete" based on some criteria is a clear and
>>>>>> understandable feature. Setting a "delete strategy" is not, and
>>>>>> will
>>>>>> contribute to confusion. This is totally be ok as a backend
>>>>>> extension
>>>>>> point,
>>>>>> but I will hate to see that as a general use feature.
>>>>>>
>>>>>> Andrus
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>
>>
Re: Non-physical delete... again
Posted by Andrey Razumovsky <ra...@gmail.com>.
It's not that easy as it sounds. BatchAction is born from BatchQuery (which
is in .query package and does not have access to DataDomain/Node) and
JDBCActionBuilder (which is logical part of JdbcAdapter, and also does not
have access to DataDomain/Node). After all, batch queries are public and can
be fired from anywhere, including context.performQuery(..). So it starts not
with DataDomainFlushAction, but with DataNodeQueryAction. The best I could
do was adding factory property to DataNode and passing it to action in query
observer.
2009/6/2 Andrus Adamchik <an...@objectstyle.org>
> I swiched to DataMap after I saw no quick access to DataDomain in
>> BatchAction class.
>>
>
> It all starts with DataDomainFlushAction, which has a reference to DD, so
> there should be a way to inject factory down the tree.
>
> I assume API changes in public classes of access.jdbc package are allowed?
>>
>
> Until we are in Beta, yes.
>
> Andrus
>
>
>
> On Jun 2, 2009, at 5:25 PM, Andrey Razumovsky wrote:
>
> I swiched to DataMap after I saw no quick access to DataDomain in
>> BatchAction class. This needs futher investigation, we need to pass domain
>> there somehow. I assume API changes in public classes of access.jdbc
>> package
>> are allowed?
>>
>> 2009/6/2 Andrus Adamchik <an...@objectstyle.org>
>>
>> Excellent. I have one comment (consistent with my position in the
>>> previous
>>> message). Configuration of the factory below should be attached to the
>>> stack
>>> objects (e.g. DataDomain), not the mapping objects (DataMap):
>>>
>>> +
>>> + /**
>>> + * Sets factory for creating QueryBuilders
>>> + */
>>> + public void setQueryBuilderFactory(BatchQueryBuilderFactory
>>> queryBuilderFactory) {
>>> + this.queryBuilderFactory = queryBuilderFactory;
>>> + }
>>> +
>>> + /**
>>> + * @return factory for creating QueryBuilders. Might be null
>>> + */
>>> + public BatchQueryBuilderFactory getQueryBuilderFactory() {
>>> + return queryBuilderFactory;
>>> + }
>>>
>>> Cheers,
>>> Andrus
>>>
>>> P.S. Maybe you can separately commit the @Deprecated part of the patch
>>> ;-)
>>>
>>>
>>>
>>> On Jun 2, 2009, at 5:07 PM, Andrey Razumovsky wrote:
>>>
>>> For not to be unsubstantiated, I uploaded my vision of the feature. Note
>>>
>>>> that there is no modeler support. It allows to provide custom factory
>>>> that
>>>> creates builders of INSERT, UPDATE, DELETE queries. 'Soft-delete'
>>>> factory
>>>> is
>>>> included.
>>>> I do not say that 'soft delete' checkbox is not needed, but uploaded
>>>> code
>>>> is
>>>> much more generic and allows to plug any behavior (maybe even Ari's
>>>> proposed
>>>> 'versions'). 'Soft' strategy can be configured with 'deleted' field name
>>>> and
>>>> will not fire UPDATE if such field does not exist in DB table.
>>>>
>>>> Please add your comments!
>>>>
>>>> Thanks,
>>>> Andrey
>>>>
>>>> 2009/6/2 Andrus Adamchik <an...@objectstyle.org>
>>>>
>>>>
>>>> On Jun 2, 2009, at 2:54 PM, Andrey Razumovsky wrote:
>>>>>
>>>>> But I'm no fan of adding some sort of 'soft' checkbox for dbattributes
>>>>>
>>>>>
>>>>>>
>>>>>> I was suggesting marking entity with a "soft delete" checkbox (not
>>>>> individual attribute - this would make no sense), and creating a
>>>>> criteria
>>>>> based on qualifier that references an attribute.
>>>>>
>>>>> Modeler support will be covered by setting class name of strategy
>>>>>
>>>>>
>>>>>>
>>>>>> I am afraid this approach will be rather arbitrary to the end user,
>>>>> so I
>>>>> suggest we discuss it some more before putting it in Cayenne. Marking
>>>>> an
>>>>> entity to use "soft delete" based on some criteria is a clear and
>>>>> understandable feature. Setting a "delete strategy" is not, and will
>>>>> contribute to confusion. This is totally be ok as a backend extension
>>>>> point,
>>>>> but I will hate to see that as a general use feature.
>>>>>
>>>>> Andrus
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>
>
Re: Non-physical delete... again
Posted by Andrus Adamchik <an...@objectstyle.org>.
> I swiched to DataMap after I saw no quick access to DataDomain in
> BatchAction class.
It all starts with DataDomainFlushAction, which has a reference to DD,
so there should be a way to inject factory down the tree.
> I assume API changes in public classes of access.jdbc package are
> allowed?
Until we are in Beta, yes.
Andrus
On Jun 2, 2009, at 5:25 PM, Andrey Razumovsky wrote:
> I swiched to DataMap after I saw no quick access to DataDomain in
> BatchAction class. This needs futher investigation, we need to pass
> domain
> there somehow. I assume API changes in public classes of access.jdbc
> package
> are allowed?
>
> 2009/6/2 Andrus Adamchik <an...@objectstyle.org>
>
>> Excellent. I have one comment (consistent with my position in the
>> previous
>> message). Configuration of the factory below should be attached to
>> the stack
>> objects (e.g. DataDomain), not the mapping objects (DataMap):
>>
>> +
>> + /**
>> + * Sets factory for creating QueryBuilders
>> + */
>> + public void setQueryBuilderFactory(BatchQueryBuilderFactory
>> queryBuilderFactory) {
>> + this.queryBuilderFactory = queryBuilderFactory;
>> + }
>> +
>> + /**
>> + * @return factory for creating QueryBuilders. Might be null
>> + */
>> + public BatchQueryBuilderFactory getQueryBuilderFactory() {
>> + return queryBuilderFactory;
>> + }
>>
>> Cheers,
>> Andrus
>>
>> P.S. Maybe you can separately commit the @Deprecated part of the
>> patch ;-)
>>
>>
>>
>> On Jun 2, 2009, at 5:07 PM, Andrey Razumovsky wrote:
>>
>> For not to be unsubstantiated, I uploaded my vision of the feature.
>> Note
>>> that there is no modeler support. It allows to provide custom
>>> factory that
>>> creates builders of INSERT, UPDATE, DELETE queries. 'Soft-delete'
>>> factory
>>> is
>>> included.
>>> I do not say that 'soft delete' checkbox is not needed, but
>>> uploaded code
>>> is
>>> much more generic and allows to plug any behavior (maybe even Ari's
>>> proposed
>>> 'versions'). 'Soft' strategy can be configured with 'deleted'
>>> field name
>>> and
>>> will not fire UPDATE if such field does not exist in DB table.
>>>
>>> Please add your comments!
>>>
>>> Thanks,
>>> Andrey
>>>
>>> 2009/6/2 Andrus Adamchik <an...@objectstyle.org>
>>>
>>>
>>>> On Jun 2, 2009, at 2:54 PM, Andrey Razumovsky wrote:
>>>>
>>>> But I'm no fan of adding some sort of 'soft' checkbox for
>>>> dbattributes
>>>>
>>>>>
>>>>>
>>>> I was suggesting marking entity with a "soft delete" checkbox (not
>>>> individual attribute - this would make no sense), and creating a
>>>> criteria
>>>> based on qualifier that references an attribute.
>>>>
>>>> Modeler support will be covered by setting class name of strategy
>>>>
>>>>>
>>>>>
>>>> I am afraid this approach will be rather arbitrary to the end
>>>> user, so I
>>>> suggest we discuss it some more before putting it in Cayenne.
>>>> Marking an
>>>> entity to use "soft delete" based on some criteria is a clear and
>>>> understandable feature. Setting a "delete strategy" is not, and
>>>> will
>>>> contribute to confusion. This is totally be ok as a backend
>>>> extension
>>>> point,
>>>> but I will hate to see that as a general use feature.
>>>>
>>>> Andrus
>>>>
>>>>
>>>>
>>>>
>>
Re: Non-physical delete... again
Posted by Andrey Razumovsky <ra...@gmail.com>.
I swiched to DataMap after I saw no quick access to DataDomain in
BatchAction class. This needs futher investigation, we need to pass domain
there somehow. I assume API changes in public classes of access.jdbc package
are allowed?
2009/6/2 Andrus Adamchik <an...@objectstyle.org>
> Excellent. I have one comment (consistent with my position in the previous
> message). Configuration of the factory below should be attached to the stack
> objects (e.g. DataDomain), not the mapping objects (DataMap):
>
> +
> + /**
> + * Sets factory for creating QueryBuilders
> + */
> + public void setQueryBuilderFactory(BatchQueryBuilderFactory
> queryBuilderFactory) {
> + this.queryBuilderFactory = queryBuilderFactory;
> + }
> +
> + /**
> + * @return factory for creating QueryBuilders. Might be null
> + */
> + public BatchQueryBuilderFactory getQueryBuilderFactory() {
> + return queryBuilderFactory;
> + }
>
> Cheers,
> Andrus
>
> P.S. Maybe you can separately commit the @Deprecated part of the patch ;-)
>
>
>
> On Jun 2, 2009, at 5:07 PM, Andrey Razumovsky wrote:
>
> For not to be unsubstantiated, I uploaded my vision of the feature. Note
>> that there is no modeler support. It allows to provide custom factory that
>> creates builders of INSERT, UPDATE, DELETE queries. 'Soft-delete' factory
>> is
>> included.
>> I do not say that 'soft delete' checkbox is not needed, but uploaded code
>> is
>> much more generic and allows to plug any behavior (maybe even Ari's
>> proposed
>> 'versions'). 'Soft' strategy can be configured with 'deleted' field name
>> and
>> will not fire UPDATE if such field does not exist in DB table.
>>
>> Please add your comments!
>>
>> Thanks,
>> Andrey
>>
>> 2009/6/2 Andrus Adamchik <an...@objectstyle.org>
>>
>>
>>> On Jun 2, 2009, at 2:54 PM, Andrey Razumovsky wrote:
>>>
>>> But I'm no fan of adding some sort of 'soft' checkbox for dbattributes
>>>
>>>>
>>>>
>>> I was suggesting marking entity with a "soft delete" checkbox (not
>>> individual attribute - this would make no sense), and creating a criteria
>>> based on qualifier that references an attribute.
>>>
>>> Modeler support will be covered by setting class name of strategy
>>>
>>>>
>>>>
>>> I am afraid this approach will be rather arbitrary to the end user, so I
>>> suggest we discuss it some more before putting it in Cayenne. Marking an
>>> entity to use "soft delete" based on some criteria is a clear and
>>> understandable feature. Setting a "delete strategy" is not, and will
>>> contribute to confusion. This is totally be ok as a backend extension
>>> point,
>>> but I will hate to see that as a general use feature.
>>>
>>> Andrus
>>>
>>>
>>>
>>>
>
Re: Non-physical delete... again
Posted by Andrus Adamchik <an...@objectstyle.org>.
Excellent. I have one comment (consistent with my position in the
previous message). Configuration of the factory below should be
attached to the stack objects (e.g. DataDomain), not the mapping
objects (DataMap):
+
+ /**
+ * Sets factory for creating QueryBuilders
+ */
+ public void setQueryBuilderFactory(BatchQueryBuilderFactory
queryBuilderFactory) {
+ this.queryBuilderFactory = queryBuilderFactory;
+ }
+
+ /**
+ * @return factory for creating QueryBuilders. Might be null
+ */
+ public BatchQueryBuilderFactory getQueryBuilderFactory() {
+ return queryBuilderFactory;
+ }
Cheers,
Andrus
P.S. Maybe you can separately commit the @Deprecated part of the
patch ;-)
On Jun 2, 2009, at 5:07 PM, Andrey Razumovsky wrote:
> For not to be unsubstantiated, I uploaded my vision of the feature.
> Note
> that there is no modeler support. It allows to provide custom
> factory that
> creates builders of INSERT, UPDATE, DELETE queries. 'Soft-delete'
> factory is
> included.
> I do not say that 'soft delete' checkbox is not needed, but uploaded
> code is
> much more generic and allows to plug any behavior (maybe even Ari's
> proposed
> 'versions'). 'Soft' strategy can be configured with 'deleted' field
> name and
> will not fire UPDATE if such field does not exist in DB table.
>
> Please add your comments!
>
> Thanks,
> Andrey
>
> 2009/6/2 Andrus Adamchik <an...@objectstyle.org>
>
>>
>> On Jun 2, 2009, at 2:54 PM, Andrey Razumovsky wrote:
>>
>> But I'm no fan of adding some sort of 'soft' checkbox for
>> dbattributes
>>>
>>
>> I was suggesting marking entity with a "soft delete" checkbox (not
>> individual attribute - this would make no sense), and creating a
>> criteria
>> based on qualifier that references an attribute.
>>
>> Modeler support will be covered by setting class name of strategy
>>>
>>
>> I am afraid this approach will be rather arbitrary to the end user,
>> so I
>> suggest we discuss it some more before putting it in Cayenne.
>> Marking an
>> entity to use "soft delete" based on some criteria is a clear and
>> understandable feature. Setting a "delete strategy" is not, and will
>> contribute to confusion. This is totally be ok as a backend
>> extension point,
>> but I will hate to see that as a general use feature.
>>
>> Andrus
>>
>>
>>
Re: Non-physical delete... again
Posted by Andrey Razumovsky <ra...@gmail.com>.
For not to be unsubstantiated, I uploaded my vision of the feature. Note
that there is no modeler support. It allows to provide custom factory that
creates builders of INSERT, UPDATE, DELETE queries. 'Soft-delete' factory is
included.
I do not say that 'soft delete' checkbox is not needed, but uploaded code is
much more generic and allows to plug any behavior (maybe even Ari's proposed
'versions'). 'Soft' strategy can be configured with 'deleted' field name and
will not fire UPDATE if such field does not exist in DB table.
Please add your comments!
Thanks,
Andrey
2009/6/2 Andrus Adamchik <an...@objectstyle.org>
>
> On Jun 2, 2009, at 2:54 PM, Andrey Razumovsky wrote:
>
> But I'm no fan of adding some sort of 'soft' checkbox for dbattributes
>>
>
> I was suggesting marking entity with a "soft delete" checkbox (not
> individual attribute - this would make no sense), and creating a criteria
> based on qualifier that references an attribute.
>
> Modeler support will be covered by setting class name of strategy
>>
>
> I am afraid this approach will be rather arbitrary to the end user, so I
> suggest we discuss it some more before putting it in Cayenne. Marking an
> entity to use "soft delete" based on some criteria is a clear and
> understandable feature. Setting a "delete strategy" is not, and will
> contribute to confusion. This is totally be ok as a backend extension point,
> but I will hate to see that as a general use feature.
>
> Andrus
>
>
>
Re: Non-physical delete... again
Posted by Andrus Adamchik <an...@objectstyle.org>.
On Jun 2, 2009, at 2:54 PM, Andrey Razumovsky wrote:
> But I'm no fan of adding some sort of 'soft' checkbox for dbattributes
I was suggesting marking entity with a "soft delete" checkbox (not
individual attribute - this would make no sense), and creating a
criteria based on qualifier that references an attribute.
> Modeler support will be covered by setting class name of strategy
I am afraid this approach will be rather arbitrary to the end user, so
I suggest we discuss it some more before putting it in Cayenne.
Marking an entity to use "soft delete" based on some criteria is a
clear and understandable feature. Setting a "delete strategy" is not,
and will contribute to confusion. This is totally be ok as a backend
extension point, but I will hate to see that as a general use feature.
Andrus
Re: Non-physical delete... again
Posted by Andrey Razumovsky <ra...@gmail.com>.
I plan to add some default 'soft' strategy for everyone to use, and it will
likely have name of 'deleted' field as constructor parameter. But I'm no fan
of adding some sort of 'soft' checkbox for dbattributes, because it will
make new problems, such as handling several soft attributes and so on. This
is quite a rare case, after all. Modeler support will be covered by setting
class name of strategy
2009/6/2 Aristedes Maniatis <ar...@ish.com.au>
>
> On 02/06/2009, at 8:08 PM, Andrus Adamchik wrote:
>
>
>> On Jun 2, 2009, at 12:29 PM, Aristedes Maniatis wrote:
>>
>>
>>> 1. Because the second most commonly used implementation will be:
>>>
>>> * boolean NOT NULL field called 'isDeleted'
>>>
>>> Could this alternative implementation be one of the 'out of the box'
>>> choices? For us, we'd want that choice per table since some tables we
>>> actually do delete (since we don't care about keeping historical data). For
>>> Cayenne, the ability to do this without too much code would be very useful
>>> and a strong 'selling point' for the framework.
>>>
>>
>> (BTW we have another area where we could provide a sensible default - the
>> auto increment version column.)
>>
>> What I would like to avoid is implicit invisible mappings forcing user
>> into Cayenne table/column naming conventions. The ability to work on top of
>> an (almost) arbitrary schema is a big deal in the database world. Cayenne
>> never had any such conventions (ok, except for AUTO_PK_TABLE), and this was
>> also a strong usability point.
>>
>> Fortunately we have the Modeler, so we can achieve the best of both
>> worlds. The modeler can create a needed column and a qualifier if an entity
>> is marked as "soft delete". The user can stick with those, or go and edit
>> the names.
>>
>
>
> For sure. I think Andrey wants to implement a generic hook so that the
> entire implementation of what 'delete' means can be replaced by an alternate
> strategy almost like specifying a lifecycle listener. That sounds really
> complex for a user to implement, but some baked-in strategies would be
> useful. You would still get to choose which column represents the concept of
> 'deleted', just as you currently choose which column is the inheritance
> discriminator in the superclass dbEntity.
>
>
> Ari
>
>
>
> -------------------------->
> ish
> http://www.ish.com.au
> Level 1, 30 Wilson Street Newtown 2042 Australia
> phone +61 2 9550 5001 fax +61 2 9550 4001
> GPG fingerprint CBFB 84B4 738D 4E87 5E5C 5EFA EF6A 7D2E 3E49 102A
>
>
>
Re: Non-physical delete... again
Posted by Aristedes Maniatis <ar...@ish.com.au>.
On 02/06/2009, at 8:08 PM, Andrus Adamchik wrote:
>
> On Jun 2, 2009, at 12:29 PM, Aristedes Maniatis wrote:
>
>>
>> 1. Because the second most commonly used implementation will be:
>>
>> * boolean NOT NULL field called 'isDeleted'
>>
>> Could this alternative implementation be one of the 'out of the
>> box' choices? For us, we'd want that choice per table since some
>> tables we actually do delete (since we don't care about keeping
>> historical data). For Cayenne, the ability to do this without too
>> much code would be very useful and a strong 'selling point' for the
>> framework.
>
> (BTW we have another area where we could provide a sensible default
> - the auto increment version column.)
>
> What I would like to avoid is implicit invisible mappings forcing
> user into Cayenne table/column naming conventions. The ability to
> work on top of an (almost) arbitrary schema is a big deal in the
> database world. Cayenne never had any such conventions (ok, except
> for AUTO_PK_TABLE), and this was also a strong usability point.
>
> Fortunately we have the Modeler, so we can achieve the best of both
> worlds. The modeler can create a needed column and a qualifier if an
> entity is marked as "soft delete". The user can stick with those, or
> go and edit the names.
For sure. I think Andrey wants to implement a generic hook so that the
entire implementation of what 'delete' means can be replaced by an
alternate strategy almost like specifying a lifecycle listener. That
sounds really complex for a user to implement, but some baked-in
strategies would be useful. You would still get to choose which column
represents the concept of 'deleted', just as you currently choose
which column is the inheritance discriminator in the superclass
dbEntity.
Ari
-------------------------->
ish
http://www.ish.com.au
Level 1, 30 Wilson Street Newtown 2042 Australia
phone +61 2 9550 5001 fax +61 2 9550 4001
GPG fingerprint CBFB 84B4 738D 4E87 5E5C 5EFA EF6A 7D2E 3E49 102A
Re: Non-physical delete... again
Posted by Andrus Adamchik <an...@objectstyle.org>.
On Jun 2, 2009, at 12:29 PM, Aristedes Maniatis wrote:
>
> 1. Because the second most commonly used implementation will be:
>
> * boolean NOT NULL field called 'isDeleted'
>
> Could this alternative implementation be one of the 'out of the box'
> choices? For us, we'd want that choice per table since some tables
> we actually do delete (since we don't care about keeping historical
> data). For Cayenne, the ability to do this without too much code
> would be very useful and a strong 'selling point' for the framework.
(BTW we have another area where we could provide a sensible default -
the auto increment version column.)
What I would like to avoid is implicit invisible mappings forcing user
into Cayenne table/column naming conventions. The ability to work on
top of an (almost) arbitrary schema is a big deal in the database
world. Cayenne never had any such conventions (ok, except for
AUTO_PK_TABLE), and this was also a strong usability point.
Fortunately we have the Modeler, so we can achieve the best of both
worlds. The modeler can create a needed column and a qualifier if an
entity is marked as "soft delete". The user can stick with those, or
go and edit the names.
Andrus
Re: Non-physical delete... again
Posted by Aristedes Maniatis <ar...@ish.com.au>.
On 02/06/2009, at 7:08 PM, Andrey Razumovsky wrote:
>> Yeah, good idea to move this down the stack. I would love to have the
>> ObjectContext level code to stay unchanged, but then generate
>> UPDATE instead
>> of DELETE at the lower levels if entity is tagged as "soft delete".
>
>
> I actually want to see this more generic, i.e. DeletionStrategy
> interface
> with one default implementation (which fires DELETE) and ability to
> set my
> own.
Two thoughts:
1. Because the second most commonly used implementation will be:
* boolean NOT NULL field called 'isDeleted'
Could this alternative implementation be one of the 'out of the box'
choices? For us, we'd want that choice per table since some tables we
actually do delete (since we don't care about keeping historical
data). For Cayenne, the ability to do this without too much code would
be very useful and a strong 'selling point' for the framework.
2. This is only a step from having an update strategy as well. For
instance, a customer who wanted to keep a complete audit trail of all
changes to Contact records might want every UPDATE to actually be an
INSERT with the old record marked as deleted and all relations
appropriately adjusted. I'm not convinced this is the best design
pattern (as opposed to storing the diffs of the changes in some log
file), but I've been thinking a little about this approach.
Ari
-------------------------->
ish
http://www.ish.com.au
Level 1, 30 Wilson Street Newtown 2042 Australia
phone +61 2 9550 5001 fax +61 2 9550 4001
GPG fingerprint CBFB 84B4 738D 4E87 5E5C 5EFA EF6A 7D2E 3E49 102A
Re: Non-physical delete... again
Posted by Andrus Adamchik <an...@objectstyle.org>.
On Jun 2, 2009, at 12:08 PM, Andrey Razumovsky wrote:
>>>
>>> 2. Deletion strategy for DataDomain. This means I do not always
>>> fire
>>> DeleteAction, but maybe something else (update action in my case).
>>>
>>
>> Yeah, good idea to move this down the stack. I would love to have the
>> ObjectContext level code to stay unchanged, but then generate
>> UPDATE instead
>> of DELETE at the lower levels if entity is tagged as "soft delete".
>
>
> I actually want to see this more generic, i.e. DeletionStrategy
> interface
> with one default implementation (which fires DELETE) and ability to
> set my
> own.
Not sure I understand, but I guess we'll see how it looks when you
commit the code.
Just one question - are you planning to implement a "soft delete"
feature in Cayenne (with appropriate flags per entity settable in the
Modeler), or just an extension point to hook up your own strategy (or
both)?
Andrus
Re: Non-physical delete... again
Posted by Andrey Razumovsky <ra...@gmail.com>.
Hi,
> Back then, we
> could set up a delegate to intercept all queries, and I automatically
> added the restricting qualifier to each select query.
I'm afraid, simple qualifier would not be enough, I need to set them for all
joined tables in query (I have simple qualifirer already, by using ObjEntity
qualifier).
2009/6/1 Andrus Adamchik <an...@objectstyle.org>
>
>
> On Jun 1, 2009, at 6:09 PM, Andrey Razumovsky wrote:
>
>>
>>
>> 2. Deletion strategy for DataDomain. This means I do not always fire
>> DeleteAction, but maybe something else (update action in my case).
>>
>
> Yeah, good idea to move this down the stack. I would love to have the
> ObjectContext level code to stay unchanged, but then generate UPDATE instead
> of DELETE at the lower levels if entity is tagged as "soft delete".
I actually want to see this more generic, i.e. DeletionStrategy interface
with one default implementation (which fires DELETE) and ability to set my
own.
>
>
> 1. DBEntity qualifier. This is same as ObjEntity qualifier, but applied
>> every time DBentity is being added to select sql. I will add DBEntity
>> qualifier 'deleted=false' and drop current ObjEntity's
>>
>
> So does that mean dropping ObjEntity qualifiers completely? (This may or
> may not be a good idea, I am not yet sure myself).
I mean removing them in my Cayenne project of course, not in API.
> Also I think there's a possibility here to address another annoyance in one
> shot - the need to manually set the inheritance discriminator column for new
> objects when inheritance is used. If we can add functionality to expressions
> to not only "get" the value from an object, but also "set" the value, we can
> do both soft delete and auto inheritance update based on an (almost)
> arbitrary exception. Kind of like OGNL framework does...
>
>
Well, I agree this is must-have in Cayenne. But my proposed solution is a
separate feature, because I need intercepting at DbEntity level.
If noone minds against these features, I think I'll look at implementing
'DeleteStrategy' and 'DbEntity qualifiers'
Andrey
Re: Non-physical delete... again
Posted by Andrus Adamchik <an...@objectstyle.org>.
On Jun 1, 2009, at 6:09 PM, Andrey Razumovsky wrote:
>
>
> 2. Deletion strategy for DataDomain. This means I do not always fire
> DeleteAction, but maybe something else (update action in my case).
Yeah, good idea to move this down the stack. I would love to have the
ObjectContext level code to stay unchanged, but then generate UPDATE
instead of DELETE at the lower levels if entity is tagged as "soft
delete".
> 1. DBEntity qualifier. This is same as ObjEntity qualifier, but
> applied
> every time DBentity is being added to select sql. I will add DBEntity
> qualifier 'deleted=false' and drop current ObjEntity's
So does that mean dropping ObjEntity qualifiers completely? (This may
or may not be a good idea, I am not yet sure myself).
Also I think there's a possibility here to address another annoyance
in one shot - the need to manually set the inheritance discriminator
column for new objects when inheritance is used. If we can add
functionality to expressions to not only "get" the value from an
object, but also "set" the value, we can do both soft delete and auto
inheritance update based on an (almost) arbitrary exception. Kind of
like OGNL framework does...
Andrus
Re: Non-physical delete... again
Posted by Mike Kienenberger <mk...@gmail.com>.
I have a legacy Cayenne 1.1.4 app that does the same thing.
I handled it back then by doing something similar. Back then, we
could set up a delegate to intercept all queries, and I automatically
added the restricting qualifier to each select query.
I never deleted from the application level code . Instead, I had a
special invalidation manager class that I called instead which would
update the boolean field (and a timestamp) and invalidate all objects
referencing that object.
It worked out well enough, although there were issues with the
invalidation propagating to all sessions exactly when I wanted it to
happen.
However, I didn't have any flattened relationships back then -- too
ignorant to know any better.
On Mon, Jun 1, 2009 at 11:09 AM, Andrey Razumovsky
<ra...@gmail.com> wrote:
> Hi,
>
> We've discussed this time ago, but I'm back now with some ideas.
>
> Current situation:
> I have to use special boolean column named "deleted" in all DB tables. That
> is, I never (or very rarely) do something like "DELETE FROM ..." or
> "context.deleteObject()", instead I do "UPDATE... SET deleted=true" or
> cdo.setDeleted(true). To select only undeleted records, I add qualifier like
> "deleted=true" to every ObjEntity. Also I add pre-update listeners to all
> entities which unregisters object and processes delete rules (also
> respective to 'deleted' field) if 'deleted' flag is set.
> It is obvious that Cayenne cannot completely handle this situation. One
> example is CAY-1109, but it can be workarounded as described above. More
> serious problems are:
> - I cannot use properly flattened relationships, because 'deleted' qualifier
> is not applied to DBEntities selection (e.g. in 'medium' table of
> many-to-many relationship)
> - flattened expressions, e.g. toArtist.name="Rublev" also miss that
> qualifier
> - there is no objects with DELETED state, only with MODIFIED
> ...and so on.
>
> I faced this situation since the first days I used Cayenne. Now when I
> thought about this a bit, I think I can handle it with two new features. I'm
> not sure they completely match Cayenne paradigm, but...
>
> 1. DBEntity qualifier. This is same as ObjEntity qualifier, but applied
> every time DBentity is being added to select sql. I will add DBEntity
> qualifier 'deleted=false' and drop current ObjEntity's
>
> 2. Deletion strategy for DataDomain. This means I do not always fire
> DeleteAction, but maybe something else (update action in my case).
>
> Any comments much appreciated.
>
> Thanks,
> Andrey
>