You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@cayenne.apache.org by Mike Kienenberger <mk...@gmail.com> on 2013/09/27 17:46:26 UTC

Creating a new ServerRuntime from an existing ServerRuntime

The idea of creating a new ServerRuntime is good, but the
implementation leaves  me with a few questions.    My ServerRuntime is
created in the context of the web app.

Is it reasonable to try to create it using the information in the
existing ServerRuntime?   Can I pull the injector and modules out of
the existing Runtime and reuse them to create a new runtime, or do I
need to create copies of the existing modules and injector?   My guess
is that each runtime needs unique injector and modules objects, but I
want to minimize the work I need to do.

It looks like I have to pull my configurationLocation out of the
ServerModule, which doesn't really provide it.

I'm not seeing an easy way to create a new ServerRuntime from scratch
without having access to data which was only available back when the
web application started up, short of storing that information
somewhere globally and reusing it.

On Tue, Sep 24, 2013 at 2:04 PM, Andrus Adamchik <an...@objectstyle.org> wrote:
>> The "special DataContext" case where the qualifier should be ignored can probably be handled by starting a separate ServerRuntime, where you can strip off the qualifiers. For whatever overhead it creates (ideally not much), this has an advantage of cleanly separating "spaces" with different ORM rules.
>
> Elaborating on this a bit… The old Configuration allowed multiple DataDomains, each of those requiring its own DataMap(s) saved in the project upfront. Good idea, but hard to use in practice.
>
> ServerRuntime (with single DD each) is more user-friendly. By starting multiple independent runtimes you to easily reuse a single mapping project, tweaking each in-memory copy local to each Runtime (as well as tweaking other parameters like cache). 2 Runtimes can reuse a single DataSource (JNDI, or otherwise), etc.
>
> Andrus
>

Re: Creating a new ServerRuntime from an existing ServerRuntime

Posted by John Huss <jo...@gmail.com>.
In my case the copy was the same.  The point was to create a separate DB
connection pool for background tasks to use so that they could do DB
intensive tasks without impacting the main DB connection pool.  I see your
point though.


On Fri, Sep 27, 2013 at 11:49 AM, Andrus Adamchik <an...@objectstyle.org>wrote:

> > So it looks like I can reuse modules to create my own runtime.
>
> Yes.
>
> > However, the current 3.1 API isn't very friendly toward this approach.
>
>
> Yes - see my other email. A common pattern is to have some kind of
> external factory that defines the modules.
>
> Also I don't perceive 'copy' method as very useful. The point of a second
> runtime is that it is somehow different from the first, and modules is what
> makes it different. I think you are doing it in a pre-3.1-DI-way - creating
> a runtime first, then customizing it. I would usually place customization
> code inside the modules, which are kind of deferred "closures".
>
> Andrus
>
>
> On Sep 27, 2013, at 7:39 PM, Mike Kienenberger <mk...@gmail.com> wrote:
>
> > So it looks like I can reuse modules to create my own runtime.
> > However, the current 3.1 API isn't very friendly toward this approach.
> > I had to clone the ServerRuntime class so that I could create my own
> > version so I could call CayenneRuntime(Module... modules) in my
> > constructor.
> >
> > Having a cloned ServerRuntime on which to make customizations seems
> > like a reasonable use case that we should support.   Can we add such a
> > method to ServerRuntime?   I think that's a better choice than making
> > it easier to create a ServerRuntime subclass.
> >
> > private ServerRuntime(Module... modules) {
> >    super(modules);
> > }
> >
> > public ServerRuntime copy() {
> >        return ServerRuntime(serverRuntime.getModules());
> > }
> >
> > It might be reasonable to make the private constructor public so that
> > someone can create ServerRuntimes where they are not required to pass
> > configurationLocation data but can provide their own alternative to
> > ServerModule.  This would have also worked in my case, removing the
> > need to have a copy() method.   However, I think the copy() method
> > provides assurance to the developer that this approach is viable.
> >
> >
> > Here's what my application code ended up looking like (using my cloned
> > class), and I think it's a good approach (except for the cloned class)
> > for these cases:
> >
> >        PaymentMethod paymentMethod = paymentHistory.getPaymentMethod();
> >        if (null == paymentMethod) {
> >            ServerRuntime currentRuntime =
> ServiceLocator.getCayenneRuntime();
> >
> >            // Payment method was invalidated at this point -- create
> > a runtime that can read invalidated payment methods
> >
> >            CopiedServerRuntime copiedRuntime = new
> > CopiedServerRuntime(currentRuntime);
> >            DataDomain dataDomain = copiedRuntime.getDataDomain();
> >            dataDomain.setSharedCacheEnabled(false);
> >
> >            EntityResolver entityResolver =
> dataDomain.getEntityResolver();
> >            ObjEntity paymentMethodObjEntity =
> > entityResolver.getObjEntity(PaymentMethod.class.getSimpleName());
> >            paymentMethodObjEntity.setDeclaredQualifier(null);
> >
> >            ObjectContext unrestrictedObjectContext =
> > copiedRuntime.getContext();
> >            PaymentHistory unrestrictedPaymentHistory =
> > unrestrictedObjectContext.localObject(paymentHistory);
> >            paymentMethod = unrestrictedPaymentHistory.getPaymentMethod();
> >        }
> >
> >
> > On Fri, Sep 27, 2013 at 11:46 AM, Mike Kienenberger <mk...@gmail.com>
> wrote:
> >> The idea of creating a new ServerRuntime is good, but the
> >> implementation leaves  me with a few questions.    My ServerRuntime is
> >> created in the context of the web app.
> >>
> >> Is it reasonable to try to create it using the information in the
> >> existing ServerRuntime?   Can I pull the injector and modules out of
> >> the existing Runtime and reuse them to create a new runtime, or do I
> >> need to create copies of the existing modules and injector?   My guess
> >> is that each runtime needs unique injector and modules objects, but I
> >> want to minimize the work I need to do.
> >>
> >> It looks like I have to pull my configurationLocation out of the
> >> ServerModule, which doesn't really provide it.
> >>
> >> I'm not seeing an easy way to create a new ServerRuntime from scratch
> >> without having access to data which was only available back when the
> >> web application started up, short of storing that information
> >> somewhere globally and reusing it.
> >>
> >> On Tue, Sep 24, 2013 at 2:04 PM, Andrus Adamchik <
> andrus@objectstyle.org> wrote:
> >>>> The "special DataContext" case where the qualifier should be ignored
> can probably be handled by starting a separate ServerRuntime, where you can
> strip off the qualifiers. For whatever overhead it creates (ideally not
> much), this has an advantage of cleanly separating "spaces" with different
> ORM rules.
> >>>
> >>> Elaborating on this a bit… The old Configuration allowed multiple
> DataDomains, each of those requiring its own DataMap(s) saved in the
> project upfront. Good idea, but hard to use in practice.
> >>>
> >>> ServerRuntime (with single DD each) is more user-friendly. By starting
> multiple independent runtimes you to easily reuse a single mapping project,
> tweaking each in-memory copy local to each Runtime (as well as tweaking
> other parameters like cache). 2 Runtimes can reuse a single DataSource
> (JNDI, or otherwise), etc.
> >>>
> >>> Andrus
> >>>
> >
>
>

Re: Creating a new ServerRuntime from an existing ServerRuntime

Posted by Mike Kienenberger <mk...@gmail.com>.
No, what you are suggesting is reasonable when there's only one
variation from the common ServerRuntime, which is currently my use
case.   What you're saying about caching this unrestricting qualifier
runtime makes sense for my situation, and I like to stick to the
recommended practices whenever possible.

The problem would be for when there are several.    In one instance, I
might need to turn off PaymentMethod's qualifiers.   In another, I
need to turn off PaymentHistory's qualifiers, in a third, turn off
both of them, in a fourth turn off a different entities.   I don't see
that this solution scales, but that's not really a problem for my
situation.

It just seems like there's no reason not to let people create a copy
of a runtime from an existing runtime so they don't have to create a
duplicate runtime out there for some obscure use case that doesn't
warrant storing it globally.

It's a hypothetical situation, so I guess it's not really an issue at present.


On Fri, Sep 27, 2013 at 1:48 PM, Andrus Adamchik <an...@objectstyle.org> wrote:
>> I was able to do this in six easily-understandable lines of code with
>> a ServerRuntime(Modules) constructor, and I fear that your suggested
>> approach requires me to create several separate classes, store
>> configuration globally, and create new modules for each qualifier that
>> I need to disable or change.
>
> No, nothing like that :) I assume in both your and John's cases any number of runtimes created have application scope (runtimes are not cheap, so you won't be starting them ad-hoc). I noticed you have ServiceLocator, so keep using that. And just implement 2 methods there, each indicating the purpose and/or flavor of a given runtime, say:
>
> - getCommonRuntime()
> - getAdminRuntime()
>
> And inside ServiceLocator in place where you create "common" runtime, create "admin" one as well from the same set of modules. And use the same 6 lines of code to customize the later. Those 6 lines you can either place in a subclass of XMLDataMapLoader (redefining it in a module), or do it after the runtime is created (like you are doing now). For the purpose of this discussion this is actually irrelevant, so I take back my earlier remark about pre and post 3.1 way of doing things.
>
>> And John's use case is even more straight-forward than my own.
>
> Same solution.
>
> I guess I am too much of a dependency injection person, always assuming that referencing some common object is cheap and easy. So maybe I am overlooking something?
>
> Andrus
>
>
> On Sep 27, 2013, at 8:03 PM, Mike Kienenberger <mk...@gmail.com> wrote:
>
>> While I can understand the desire for purity with that pattern, it
>> seems to me that it's too expensive to maintain in this use case.
>>
>> I don't want to have to maintain a factory for building runtimes and
>> track all of the configuration needed to do that, just to turn off a
>> qualifier.    The existing runtime contains everything necessary --
>> there's just no easy way to get at it.
>>
>> Maybe I am overlooking something.
>>
>> I know you are busy, but can you provide an example of how I would
>> perform the same task for which I provided code (turn off a qualifier
>> in an otherwise duplicate ServerRuntime deep inside business logic)
>> using modules?
>>
>> I was able to do this in six easily-understandable lines of code with
>> a ServerRuntime(Modules) constructor, and I fear that your suggested
>> approach requires me to create several separate classes, store
>> configuration globally, and create new modules for each qualifier that
>> I need to disable or change.
>>
>> And John's use case is even more straight-forward than my own.
>>
>>
>> On Fri, Sep 27, 2013 at 12:49 PM, Andrus Adamchik
>> <an...@objectstyle.org> wrote:
>>>> So it looks like I can reuse modules to create my own runtime.
>>>
>>> Yes.
>>>
>>>> However, the current 3.1 API isn't very friendly toward this approach.
>>>
>>>
>>> Yes - see my other email. A common pattern is to have some kind of external factory that defines the modules.
>>>
>>> Also I don't perceive 'copy' method as very useful. The point of a second runtime is that it is somehow different from the first, and modules is what makes it different. I think you are doing it in a pre-3.1-DI-way - creating a runtime first, then customizing it. I would usually place customization code inside the modules, which are kind of deferred "closures".
>>>
>>> Andrus
>>>
>>>
>>> On Sep 27, 2013, at 7:39 PM, Mike Kienenberger <mk...@gmail.com> wrote:
>>>
>>>> So it looks like I can reuse modules to create my own runtime.
>>>> However, the current 3.1 API isn't very friendly toward this approach.
>>>> I had to clone the ServerRuntime class so that I could create my own
>>>> version so I could call CayenneRuntime(Module... modules) in my
>>>> constructor.
>>>>
>>>> Having a cloned ServerRuntime on which to make customizations seems
>>>> like a reasonable use case that we should support.   Can we add such a
>>>> method to ServerRuntime?   I think that's a better choice than making
>>>> it easier to create a ServerRuntime subclass.
>>>>
>>>> private ServerRuntime(Module... modules) {
>>>>   super(modules);
>>>> }
>>>>
>>>> public ServerRuntime copy() {
>>>>       return ServerRuntime(serverRuntime.getModules());
>>>> }
>>>>
>>>> It might be reasonable to make the private constructor public so that
>>>> someone can create ServerRuntimes where they are not required to pass
>>>> configurationLocation data but can provide their own alternative to
>>>> ServerModule.  This would have also worked in my case, removing the
>>>> need to have a copy() method.   However, I think the copy() method
>>>> provides assurance to the developer that this approach is viable.
>>>>
>>>>
>>>> Here's what my application code ended up looking like (using my cloned
>>>> class), and I think it's a good approach (except for the cloned class)
>>>> for these cases:
>>>>
>>>>       PaymentMethod paymentMethod = paymentHistory.getPaymentMethod();
>>>>       if (null == paymentMethod) {
>>>>           ServerRuntime currentRuntime = ServiceLocator.getCayenneRuntime();
>>>>
>>>>           // Payment method was invalidated at this point -- create
>>>> a runtime that can read invalidated payment methods
>>>>
>>>>           CopiedServerRuntime copiedRuntime = new
>>>> CopiedServerRuntime(currentRuntime);
>>>>           DataDomain dataDomain = copiedRuntime.getDataDomain();
>>>>           dataDomain.setSharedCacheEnabled(false);
>>>>
>>>>           EntityResolver entityResolver = dataDomain.getEntityResolver();
>>>>           ObjEntity paymentMethodObjEntity =
>>>> entityResolver.getObjEntity(PaymentMethod.class.getSimpleName());
>>>>           paymentMethodObjEntity.setDeclaredQualifier(null);
>>>>
>>>>           ObjectContext unrestrictedObjectContext =
>>>> copiedRuntime.getContext();
>>>>           PaymentHistory unrestrictedPaymentHistory =
>>>> unrestrictedObjectContext.localObject(paymentHistory);
>>>>           paymentMethod = unrestrictedPaymentHistory.getPaymentMethod();
>>>>       }
>>>>
>>>>
>>>> On Fri, Sep 27, 2013 at 11:46 AM, Mike Kienenberger <mk...@gmail.com> wrote:
>>>>> The idea of creating a new ServerRuntime is good, but the
>>>>> implementation leaves  me with a few questions.    My ServerRuntime is
>>>>> created in the context of the web app.
>>>>>
>>>>> Is it reasonable to try to create it using the information in the
>>>>> existing ServerRuntime?   Can I pull the injector and modules out of
>>>>> the existing Runtime and reuse them to create a new runtime, or do I
>>>>> need to create copies of the existing modules and injector?   My guess
>>>>> is that each runtime needs unique injector and modules objects, but I
>>>>> want to minimize the work I need to do.
>>>>>
>>>>> It looks like I have to pull my configurationLocation out of the
>>>>> ServerModule, which doesn't really provide it.
>>>>>
>>>>> I'm not seeing an easy way to create a new ServerRuntime from scratch
>>>>> without having access to data which was only available back when the
>>>>> web application started up, short of storing that information
>>>>> somewhere globally and reusing it.
>>>>>
>>>>> On Tue, Sep 24, 2013 at 2:04 PM, Andrus Adamchik <an...@objectstyle.org> wrote:
>>>>>>> The "special DataContext" case where the qualifier should be ignored can probably be handled by starting a separate ServerRuntime, where you can strip off the qualifiers. For whatever overhead it creates (ideally not much), this has an advantage of cleanly separating "spaces" with different ORM rules.
>>>>>>
>>>>>> Elaborating on this a bit… The old Configuration allowed multiple DataDomains, each of those requiring its own DataMap(s) saved in the project upfront. Good idea, but hard to use in practice.
>>>>>>
>>>>>> ServerRuntime (with single DD each) is more user-friendly. By starting multiple independent runtimes you to easily reuse a single mapping project, tweaking each in-memory copy local to each Runtime (as well as tweaking other parameters like cache). 2 Runtimes can reuse a single DataSource (JNDI, or otherwise), etc.
>>>>>>
>>>>>> Andrus
>>>>>>
>>>>
>>>
>>
>

Re: Creating a new ServerRuntime from an existing ServerRuntime

Posted by Andrus Adamchik <an...@objectstyle.org>.
> I was able to do this in six easily-understandable lines of code with
> a ServerRuntime(Modules) constructor, and I fear that your suggested
> approach requires me to create several separate classes, store
> configuration globally, and create new modules for each qualifier that
> I need to disable or change.

No, nothing like that :) I assume in both your and John's cases any number of runtimes created have application scope (runtimes are not cheap, so you won't be starting them ad-hoc). I noticed you have ServiceLocator, so keep using that. And just implement 2 methods there, each indicating the purpose and/or flavor of a given runtime, say:

- getCommonRuntime()
- getAdminRuntime()

And inside ServiceLocator in place where you create "common" runtime, create "admin" one as well from the same set of modules. And use the same 6 lines of code to customize the later. Those 6 lines you can either place in a subclass of XMLDataMapLoader (redefining it in a module), or do it after the runtime is created (like you are doing now). For the purpose of this discussion this is actually irrelevant, so I take back my earlier remark about pre and post 3.1 way of doing things.

> And John's use case is even more straight-forward than my own.

Same solution. 

I guess I am too much of a dependency injection person, always assuming that referencing some common object is cheap and easy. So maybe I am overlooking something?

Andrus


On Sep 27, 2013, at 8:03 PM, Mike Kienenberger <mk...@gmail.com> wrote:

> While I can understand the desire for purity with that pattern, it
> seems to me that it's too expensive to maintain in this use case.
> 
> I don't want to have to maintain a factory for building runtimes and
> track all of the configuration needed to do that, just to turn off a
> qualifier.    The existing runtime contains everything necessary --
> there's just no easy way to get at it.
> 
> Maybe I am overlooking something.
> 
> I know you are busy, but can you provide an example of how I would
> perform the same task for which I provided code (turn off a qualifier
> in an otherwise duplicate ServerRuntime deep inside business logic)
> using modules?
> 
> I was able to do this in six easily-understandable lines of code with
> a ServerRuntime(Modules) constructor, and I fear that your suggested
> approach requires me to create several separate classes, store
> configuration globally, and create new modules for each qualifier that
> I need to disable or change.
> 
> And John's use case is even more straight-forward than my own.
> 
> 
> On Fri, Sep 27, 2013 at 12:49 PM, Andrus Adamchik
> <an...@objectstyle.org> wrote:
>>> So it looks like I can reuse modules to create my own runtime.
>> 
>> Yes.
>> 
>>> However, the current 3.1 API isn't very friendly toward this approach.
>> 
>> 
>> Yes - see my other email. A common pattern is to have some kind of external factory that defines the modules.
>> 
>> Also I don't perceive 'copy' method as very useful. The point of a second runtime is that it is somehow different from the first, and modules is what makes it different. I think you are doing it in a pre-3.1-DI-way - creating a runtime first, then customizing it. I would usually place customization code inside the modules, which are kind of deferred "closures".
>> 
>> Andrus
>> 
>> 
>> On Sep 27, 2013, at 7:39 PM, Mike Kienenberger <mk...@gmail.com> wrote:
>> 
>>> So it looks like I can reuse modules to create my own runtime.
>>> However, the current 3.1 API isn't very friendly toward this approach.
>>> I had to clone the ServerRuntime class so that I could create my own
>>> version so I could call CayenneRuntime(Module... modules) in my
>>> constructor.
>>> 
>>> Having a cloned ServerRuntime on which to make customizations seems
>>> like a reasonable use case that we should support.   Can we add such a
>>> method to ServerRuntime?   I think that's a better choice than making
>>> it easier to create a ServerRuntime subclass.
>>> 
>>> private ServerRuntime(Module... modules) {
>>>   super(modules);
>>> }
>>> 
>>> public ServerRuntime copy() {
>>>       return ServerRuntime(serverRuntime.getModules());
>>> }
>>> 
>>> It might be reasonable to make the private constructor public so that
>>> someone can create ServerRuntimes where they are not required to pass
>>> configurationLocation data but can provide their own alternative to
>>> ServerModule.  This would have also worked in my case, removing the
>>> need to have a copy() method.   However, I think the copy() method
>>> provides assurance to the developer that this approach is viable.
>>> 
>>> 
>>> Here's what my application code ended up looking like (using my cloned
>>> class), and I think it's a good approach (except for the cloned class)
>>> for these cases:
>>> 
>>>       PaymentMethod paymentMethod = paymentHistory.getPaymentMethod();
>>>       if (null == paymentMethod) {
>>>           ServerRuntime currentRuntime = ServiceLocator.getCayenneRuntime();
>>> 
>>>           // Payment method was invalidated at this point -- create
>>> a runtime that can read invalidated payment methods
>>> 
>>>           CopiedServerRuntime copiedRuntime = new
>>> CopiedServerRuntime(currentRuntime);
>>>           DataDomain dataDomain = copiedRuntime.getDataDomain();
>>>           dataDomain.setSharedCacheEnabled(false);
>>> 
>>>           EntityResolver entityResolver = dataDomain.getEntityResolver();
>>>           ObjEntity paymentMethodObjEntity =
>>> entityResolver.getObjEntity(PaymentMethod.class.getSimpleName());
>>>           paymentMethodObjEntity.setDeclaredQualifier(null);
>>> 
>>>           ObjectContext unrestrictedObjectContext =
>>> copiedRuntime.getContext();
>>>           PaymentHistory unrestrictedPaymentHistory =
>>> unrestrictedObjectContext.localObject(paymentHistory);
>>>           paymentMethod = unrestrictedPaymentHistory.getPaymentMethod();
>>>       }
>>> 
>>> 
>>> On Fri, Sep 27, 2013 at 11:46 AM, Mike Kienenberger <mk...@gmail.com> wrote:
>>>> The idea of creating a new ServerRuntime is good, but the
>>>> implementation leaves  me with a few questions.    My ServerRuntime is
>>>> created in the context of the web app.
>>>> 
>>>> Is it reasonable to try to create it using the information in the
>>>> existing ServerRuntime?   Can I pull the injector and modules out of
>>>> the existing Runtime and reuse them to create a new runtime, or do I
>>>> need to create copies of the existing modules and injector?   My guess
>>>> is that each runtime needs unique injector and modules objects, but I
>>>> want to minimize the work I need to do.
>>>> 
>>>> It looks like I have to pull my configurationLocation out of the
>>>> ServerModule, which doesn't really provide it.
>>>> 
>>>> I'm not seeing an easy way to create a new ServerRuntime from scratch
>>>> without having access to data which was only available back when the
>>>> web application started up, short of storing that information
>>>> somewhere globally and reusing it.
>>>> 
>>>> On Tue, Sep 24, 2013 at 2:04 PM, Andrus Adamchik <an...@objectstyle.org> wrote:
>>>>>> The "special DataContext" case where the qualifier should be ignored can probably be handled by starting a separate ServerRuntime, where you can strip off the qualifiers. For whatever overhead it creates (ideally not much), this has an advantage of cleanly separating "spaces" with different ORM rules.
>>>>> 
>>>>> Elaborating on this a bit… The old Configuration allowed multiple DataDomains, each of those requiring its own DataMap(s) saved in the project upfront. Good idea, but hard to use in practice.
>>>>> 
>>>>> ServerRuntime (with single DD each) is more user-friendly. By starting multiple independent runtimes you to easily reuse a single mapping project, tweaking each in-memory copy local to each Runtime (as well as tweaking other parameters like cache). 2 Runtimes can reuse a single DataSource (JNDI, or otherwise), etc.
>>>>> 
>>>>> Andrus
>>>>> 
>>> 
>> 
> 


Re: Creating a new ServerRuntime from an existing ServerRuntime

Posted by Mike Kienenberger <mk...@gmail.com>.
While I can understand the desire for purity with that pattern, it
seems to me that it's too expensive to maintain in this use case.

I don't want to have to maintain a factory for building runtimes and
track all of the configuration needed to do that, just to turn off a
qualifier.    The existing runtime contains everything necessary --
there's just no easy way to get at it.

Maybe I am overlooking something.

I know you are busy, but can you provide an example of how I would
perform the same task for which I provided code (turn off a qualifier
in an otherwise duplicate ServerRuntime deep inside business logic)
using modules?

I was able to do this in six easily-understandable lines of code with
a ServerRuntime(Modules) constructor, and I fear that your suggested
approach requires me to create several separate classes, store
configuration globally, and create new modules for each qualifier that
I need to disable or change.

And John's use case is even more straight-forward than my own.


On Fri, Sep 27, 2013 at 12:49 PM, Andrus Adamchik
<an...@objectstyle.org> wrote:
>> So it looks like I can reuse modules to create my own runtime.
>
> Yes.
>
>> However, the current 3.1 API isn't very friendly toward this approach.
>
>
> Yes - see my other email. A common pattern is to have some kind of external factory that defines the modules.
>
> Also I don't perceive 'copy' method as very useful. The point of a second runtime is that it is somehow different from the first, and modules is what makes it different. I think you are doing it in a pre-3.1-DI-way - creating a runtime first, then customizing it. I would usually place customization code inside the modules, which are kind of deferred "closures".
>
> Andrus
>
>
> On Sep 27, 2013, at 7:39 PM, Mike Kienenberger <mk...@gmail.com> wrote:
>
>> So it looks like I can reuse modules to create my own runtime.
>> However, the current 3.1 API isn't very friendly toward this approach.
>> I had to clone the ServerRuntime class so that I could create my own
>> version so I could call CayenneRuntime(Module... modules) in my
>> constructor.
>>
>> Having a cloned ServerRuntime on which to make customizations seems
>> like a reasonable use case that we should support.   Can we add such a
>> method to ServerRuntime?   I think that's a better choice than making
>> it easier to create a ServerRuntime subclass.
>>
>> private ServerRuntime(Module... modules) {
>>    super(modules);
>> }
>>
>> public ServerRuntime copy() {
>>        return ServerRuntime(serverRuntime.getModules());
>> }
>>
>> It might be reasonable to make the private constructor public so that
>> someone can create ServerRuntimes where they are not required to pass
>> configurationLocation data but can provide their own alternative to
>> ServerModule.  This would have also worked in my case, removing the
>> need to have a copy() method.   However, I think the copy() method
>> provides assurance to the developer that this approach is viable.
>>
>>
>> Here's what my application code ended up looking like (using my cloned
>> class), and I think it's a good approach (except for the cloned class)
>> for these cases:
>>
>>        PaymentMethod paymentMethod = paymentHistory.getPaymentMethod();
>>        if (null == paymentMethod) {
>>            ServerRuntime currentRuntime = ServiceLocator.getCayenneRuntime();
>>
>>            // Payment method was invalidated at this point -- create
>> a runtime that can read invalidated payment methods
>>
>>            CopiedServerRuntime copiedRuntime = new
>> CopiedServerRuntime(currentRuntime);
>>            DataDomain dataDomain = copiedRuntime.getDataDomain();
>>            dataDomain.setSharedCacheEnabled(false);
>>
>>            EntityResolver entityResolver = dataDomain.getEntityResolver();
>>            ObjEntity paymentMethodObjEntity =
>> entityResolver.getObjEntity(PaymentMethod.class.getSimpleName());
>>            paymentMethodObjEntity.setDeclaredQualifier(null);
>>
>>            ObjectContext unrestrictedObjectContext =
>> copiedRuntime.getContext();
>>            PaymentHistory unrestrictedPaymentHistory =
>> unrestrictedObjectContext.localObject(paymentHistory);
>>            paymentMethod = unrestrictedPaymentHistory.getPaymentMethod();
>>        }
>>
>>
>> On Fri, Sep 27, 2013 at 11:46 AM, Mike Kienenberger <mk...@gmail.com> wrote:
>>> The idea of creating a new ServerRuntime is good, but the
>>> implementation leaves  me with a few questions.    My ServerRuntime is
>>> created in the context of the web app.
>>>
>>> Is it reasonable to try to create it using the information in the
>>> existing ServerRuntime?   Can I pull the injector and modules out of
>>> the existing Runtime and reuse them to create a new runtime, or do I
>>> need to create copies of the existing modules and injector?   My guess
>>> is that each runtime needs unique injector and modules objects, but I
>>> want to minimize the work I need to do.
>>>
>>> It looks like I have to pull my configurationLocation out of the
>>> ServerModule, which doesn't really provide it.
>>>
>>> I'm not seeing an easy way to create a new ServerRuntime from scratch
>>> without having access to data which was only available back when the
>>> web application started up, short of storing that information
>>> somewhere globally and reusing it.
>>>
>>> On Tue, Sep 24, 2013 at 2:04 PM, Andrus Adamchik <an...@objectstyle.org> wrote:
>>>>> The "special DataContext" case where the qualifier should be ignored can probably be handled by starting a separate ServerRuntime, where you can strip off the qualifiers. For whatever overhead it creates (ideally not much), this has an advantage of cleanly separating "spaces" with different ORM rules.
>>>>
>>>> Elaborating on this a bit… The old Configuration allowed multiple DataDomains, each of those requiring its own DataMap(s) saved in the project upfront. Good idea, but hard to use in practice.
>>>>
>>>> ServerRuntime (with single DD each) is more user-friendly. By starting multiple independent runtimes you to easily reuse a single mapping project, tweaking each in-memory copy local to each Runtime (as well as tweaking other parameters like cache). 2 Runtimes can reuse a single DataSource (JNDI, or otherwise), etc.
>>>>
>>>> Andrus
>>>>
>>
>

Re: Creating a new ServerRuntime from an existing ServerRuntime

Posted by Andrus Adamchik <an...@objectstyle.org>.
> So it looks like I can reuse modules to create my own runtime.

Yes.

> However, the current 3.1 API isn't very friendly toward this approach.


Yes - see my other email. A common pattern is to have some kind of external factory that defines the modules. 

Also I don't perceive 'copy' method as very useful. The point of a second runtime is that it is somehow different from the first, and modules is what makes it different. I think you are doing it in a pre-3.1-DI-way - creating a runtime first, then customizing it. I would usually place customization code inside the modules, which are kind of deferred "closures".

Andrus


On Sep 27, 2013, at 7:39 PM, Mike Kienenberger <mk...@gmail.com> wrote:

> So it looks like I can reuse modules to create my own runtime.
> However, the current 3.1 API isn't very friendly toward this approach.
> I had to clone the ServerRuntime class so that I could create my own
> version so I could call CayenneRuntime(Module... modules) in my
> constructor.
> 
> Having a cloned ServerRuntime on which to make customizations seems
> like a reasonable use case that we should support.   Can we add such a
> method to ServerRuntime?   I think that's a better choice than making
> it easier to create a ServerRuntime subclass.
> 
> private ServerRuntime(Module... modules) {
>    super(modules);
> }
> 
> public ServerRuntime copy() {
>        return ServerRuntime(serverRuntime.getModules());
> }
> 
> It might be reasonable to make the private constructor public so that
> someone can create ServerRuntimes where they are not required to pass
> configurationLocation data but can provide their own alternative to
> ServerModule.  This would have also worked in my case, removing the
> need to have a copy() method.   However, I think the copy() method
> provides assurance to the developer that this approach is viable.
> 
> 
> Here's what my application code ended up looking like (using my cloned
> class), and I think it's a good approach (except for the cloned class)
> for these cases:
> 
>        PaymentMethod paymentMethod = paymentHistory.getPaymentMethod();
>        if (null == paymentMethod) {
>            ServerRuntime currentRuntime = ServiceLocator.getCayenneRuntime();
> 
>            // Payment method was invalidated at this point -- create
> a runtime that can read invalidated payment methods
> 
>            CopiedServerRuntime copiedRuntime = new
> CopiedServerRuntime(currentRuntime);
>            DataDomain dataDomain = copiedRuntime.getDataDomain();
>            dataDomain.setSharedCacheEnabled(false);
> 
>            EntityResolver entityResolver = dataDomain.getEntityResolver();
>            ObjEntity paymentMethodObjEntity =
> entityResolver.getObjEntity(PaymentMethod.class.getSimpleName());
>            paymentMethodObjEntity.setDeclaredQualifier(null);
> 
>            ObjectContext unrestrictedObjectContext =
> copiedRuntime.getContext();
>            PaymentHistory unrestrictedPaymentHistory =
> unrestrictedObjectContext.localObject(paymentHistory);
>            paymentMethod = unrestrictedPaymentHistory.getPaymentMethod();
>        }
> 
> 
> On Fri, Sep 27, 2013 at 11:46 AM, Mike Kienenberger <mk...@gmail.com> wrote:
>> The idea of creating a new ServerRuntime is good, but the
>> implementation leaves  me with a few questions.    My ServerRuntime is
>> created in the context of the web app.
>> 
>> Is it reasonable to try to create it using the information in the
>> existing ServerRuntime?   Can I pull the injector and modules out of
>> the existing Runtime and reuse them to create a new runtime, or do I
>> need to create copies of the existing modules and injector?   My guess
>> is that each runtime needs unique injector and modules objects, but I
>> want to minimize the work I need to do.
>> 
>> It looks like I have to pull my configurationLocation out of the
>> ServerModule, which doesn't really provide it.
>> 
>> I'm not seeing an easy way to create a new ServerRuntime from scratch
>> without having access to data which was only available back when the
>> web application started up, short of storing that information
>> somewhere globally and reusing it.
>> 
>> On Tue, Sep 24, 2013 at 2:04 PM, Andrus Adamchik <an...@objectstyle.org> wrote:
>>>> The "special DataContext" case where the qualifier should be ignored can probably be handled by starting a separate ServerRuntime, where you can strip off the qualifiers. For whatever overhead it creates (ideally not much), this has an advantage of cleanly separating "spaces" with different ORM rules.
>>> 
>>> Elaborating on this a bit… The old Configuration allowed multiple DataDomains, each of those requiring its own DataMap(s) saved in the project upfront. Good idea, but hard to use in practice.
>>> 
>>> ServerRuntime (with single DD each) is more user-friendly. By starting multiple independent runtimes you to easily reuse a single mapping project, tweaking each in-memory copy local to each Runtime (as well as tweaking other parameters like cache). 2 Runtimes can reuse a single DataSource (JNDI, or otherwise), etc.
>>> 
>>> Andrus
>>> 
> 


Re: Creating a new ServerRuntime from an existing ServerRuntime

Posted by John Huss <jo...@gmail.com>.
I've had to make a copy of a ServerRuntime object before too - an API for
it would be useful.


On Fri, Sep 27, 2013 at 11:39 AM, Mike Kienenberger <mk...@gmail.com>wrote:

> So it looks like I can reuse modules to create my own runtime.
> However, the current 3.1 API isn't very friendly toward this approach.
> I had to clone the ServerRuntime class so that I could create my own
> version so I could call CayenneRuntime(Module... modules) in my
> constructor.
>
> Having a cloned ServerRuntime on which to make customizations seems
> like a reasonable use case that we should support.   Can we add such a
> method to ServerRuntime?   I think that's a better choice than making
> it easier to create a ServerRuntime subclass.
>
> private ServerRuntime(Module... modules) {
>     super(modules);
> }
>
> public ServerRuntime copy() {
>         return ServerRuntime(serverRuntime.getModules());
> }
>
> It might be reasonable to make the private constructor public so that
> someone can create ServerRuntimes where they are not required to pass
> configurationLocation data but can provide their own alternative to
> ServerModule.  This would have also worked in my case, removing the
> need to have a copy() method.   However, I think the copy() method
> provides assurance to the developer that this approach is viable.
>
>
> Here's what my application code ended up looking like (using my cloned
> class), and I think it's a good approach (except for the cloned class)
> for these cases:
>
>         PaymentMethod paymentMethod = paymentHistory.getPaymentMethod();
>         if (null == paymentMethod) {
>             ServerRuntime currentRuntime =
> ServiceLocator.getCayenneRuntime();
>
>             // Payment method was invalidated at this point -- create
> a runtime that can read invalidated payment methods
>
>             CopiedServerRuntime copiedRuntime = new
> CopiedServerRuntime(currentRuntime);
>             DataDomain dataDomain = copiedRuntime.getDataDomain();
>             dataDomain.setSharedCacheEnabled(false);
>
>             EntityResolver entityResolver = dataDomain.getEntityResolver();
>             ObjEntity paymentMethodObjEntity =
> entityResolver.getObjEntity(PaymentMethod.class.getSimpleName());
>             paymentMethodObjEntity.setDeclaredQualifier(null);
>
>             ObjectContext unrestrictedObjectContext =
> copiedRuntime.getContext();
>             PaymentHistory unrestrictedPaymentHistory =
> unrestrictedObjectContext.localObject(paymentHistory);
>             paymentMethod = unrestrictedPaymentHistory.getPaymentMethod();
>         }
>
>
> On Fri, Sep 27, 2013 at 11:46 AM, Mike Kienenberger <mk...@gmail.com>
> wrote:
> > The idea of creating a new ServerRuntime is good, but the
> > implementation leaves  me with a few questions.    My ServerRuntime is
> > created in the context of the web app.
> >
> > Is it reasonable to try to create it using the information in the
> > existing ServerRuntime?   Can I pull the injector and modules out of
> > the existing Runtime and reuse them to create a new runtime, or do I
> > need to create copies of the existing modules and injector?   My guess
> > is that each runtime needs unique injector and modules objects, but I
> > want to minimize the work I need to do.
> >
> > It looks like I have to pull my configurationLocation out of the
> > ServerModule, which doesn't really provide it.
> >
> > I'm not seeing an easy way to create a new ServerRuntime from scratch
> > without having access to data which was only available back when the
> > web application started up, short of storing that information
> > somewhere globally and reusing it.
> >
> > On Tue, Sep 24, 2013 at 2:04 PM, Andrus Adamchik <an...@objectstyle.org>
> wrote:
> >>> The "special DataContext" case where the qualifier should be ignored
> can probably be handled by starting a separate ServerRuntime, where you can
> strip off the qualifiers. For whatever overhead it creates (ideally not
> much), this has an advantage of cleanly separating "spaces" with different
> ORM rules.
> >>
> >> Elaborating on this a bit… The old Configuration allowed multiple
> DataDomains, each of those requiring its own DataMap(s) saved in the
> project upfront. Good idea, but hard to use in practice.
> >>
> >> ServerRuntime (with single DD each) is more user-friendly. By starting
> multiple independent runtimes you to easily reuse a single mapping project,
> tweaking each in-memory copy local to each Runtime (as well as tweaking
> other parameters like cache). 2 Runtimes can reuse a single DataSource
> (JNDI, or otherwise), etc.
> >>
> >> Andrus
> >>
>

Re: Creating a new ServerRuntime from an existing ServerRuntime

Posted by Mike Kienenberger <mk...@gmail.com>.
So it looks like I can reuse modules to create my own runtime.
However, the current 3.1 API isn't very friendly toward this approach.
I had to clone the ServerRuntime class so that I could create my own
version so I could call CayenneRuntime(Module... modules) in my
constructor.

Having a cloned ServerRuntime on which to make customizations seems
like a reasonable use case that we should support.   Can we add such a
method to ServerRuntime?   I think that's a better choice than making
it easier to create a ServerRuntime subclass.

private ServerRuntime(Module... modules) {
    super(modules);
}

public ServerRuntime copy() {
        return ServerRuntime(serverRuntime.getModules());
}

It might be reasonable to make the private constructor public so that
someone can create ServerRuntimes where they are not required to pass
configurationLocation data but can provide their own alternative to
ServerModule.  This would have also worked in my case, removing the
need to have a copy() method.   However, I think the copy() method
provides assurance to the developer that this approach is viable.


Here's what my application code ended up looking like (using my cloned
class), and I think it's a good approach (except for the cloned class)
for these cases:

        PaymentMethod paymentMethod = paymentHistory.getPaymentMethod();
        if (null == paymentMethod) {
            ServerRuntime currentRuntime = ServiceLocator.getCayenneRuntime();

            // Payment method was invalidated at this point -- create
a runtime that can read invalidated payment methods

            CopiedServerRuntime copiedRuntime = new
CopiedServerRuntime(currentRuntime);
            DataDomain dataDomain = copiedRuntime.getDataDomain();
            dataDomain.setSharedCacheEnabled(false);

            EntityResolver entityResolver = dataDomain.getEntityResolver();
            ObjEntity paymentMethodObjEntity =
entityResolver.getObjEntity(PaymentMethod.class.getSimpleName());
            paymentMethodObjEntity.setDeclaredQualifier(null);

            ObjectContext unrestrictedObjectContext =
copiedRuntime.getContext();
            PaymentHistory unrestrictedPaymentHistory =
unrestrictedObjectContext.localObject(paymentHistory);
            paymentMethod = unrestrictedPaymentHistory.getPaymentMethod();
        }


On Fri, Sep 27, 2013 at 11:46 AM, Mike Kienenberger <mk...@gmail.com> wrote:
> The idea of creating a new ServerRuntime is good, but the
> implementation leaves  me with a few questions.    My ServerRuntime is
> created in the context of the web app.
>
> Is it reasonable to try to create it using the information in the
> existing ServerRuntime?   Can I pull the injector and modules out of
> the existing Runtime and reuse them to create a new runtime, or do I
> need to create copies of the existing modules and injector?   My guess
> is that each runtime needs unique injector and modules objects, but I
> want to minimize the work I need to do.
>
> It looks like I have to pull my configurationLocation out of the
> ServerModule, which doesn't really provide it.
>
> I'm not seeing an easy way to create a new ServerRuntime from scratch
> without having access to data which was only available back when the
> web application started up, short of storing that information
> somewhere globally and reusing it.
>
> On Tue, Sep 24, 2013 at 2:04 PM, Andrus Adamchik <an...@objectstyle.org> wrote:
>>> The "special DataContext" case where the qualifier should be ignored can probably be handled by starting a separate ServerRuntime, where you can strip off the qualifiers. For whatever overhead it creates (ideally not much), this has an advantage of cleanly separating "spaces" with different ORM rules.
>>
>> Elaborating on this a bit… The old Configuration allowed multiple DataDomains, each of those requiring its own DataMap(s) saved in the project upfront. Good idea, but hard to use in practice.
>>
>> ServerRuntime (with single DD each) is more user-friendly. By starting multiple independent runtimes you to easily reuse a single mapping project, tweaking each in-memory copy local to each Runtime (as well as tweaking other parameters like cache). 2 Runtimes can reuse a single DataSource (JNDI, or otherwise), etc.
>>
>> Andrus
>>

Re: Creating a new ServerRuntime from an existing ServerRuntime

Posted by Andrus Adamchik <an...@objectstyle.org>.
ServerRuntime encapsulates a full Cayenne stack (which includes injector). How you create and manage it is left up to the app. Here is for instance how I usually encapsulate it in a Tapestry application:

  https://github.com/andrus/wowodc13/blob/master/services/src/main/java/demo/services/cayenne/CayenneService.java

CayenneService in this example is both a factory (defining custom modules among other things) and a holder of a reference to ServerRuntime. CayenneService itself is a singleton injectable via Tapestry to pages and other services. Your version of CayenneService can store multiple runtimes if needed. As to where to put CayenneService, you may use something like Spring or put it in ServletContext. In other words just follow the patterns for managing app singletons that you are using already. Cayenne is intentionally made agnostic to that.

Andrus



On Sep 27, 2013, at 6:46 PM, Mike Kienenberger <mk...@gmail.com> wrote:
> The idea of creating a new ServerRuntime is good, but the
> implementation leaves  me with a few questions.    My ServerRuntime is
> created in the context of the web app.
> 
> Is it reasonable to try to create it using the information in the
> existing ServerRuntime?   Can I pull the injector and modules out of
> the existing Runtime and reuse them to create a new runtime, or do I
> need to create copies of the existing modules and injector?   My guess
> is that each runtime needs unique injector and modules objects, but I
> want to minimize the work I need to do.
> 
> It looks like I have to pull my configurationLocation out of the
> ServerModule, which doesn't really provide it.
> 
> I'm not seeing an easy way to create a new ServerRuntime from scratch
> without having access to data which was only available back when the
> web application started up, short of storing that information
> somewhere globally and reusing it.
> 
> On Tue, Sep 24, 2013 at 2:04 PM, Andrus Adamchik <an...@objectstyle.org> wrote:
>>> The "special DataContext" case where the qualifier should be ignored can probably be handled by starting a separate ServerRuntime, where you can strip off the qualifiers. For whatever overhead it creates (ideally not much), this has an advantage of cleanly separating "spaces" with different ORM rules.
>> 
>> Elaborating on this a bit… The old Configuration allowed multiple DataDomains, each of those requiring its own DataMap(s) saved in the project upfront. Good idea, but hard to use in practice.
>> 
>> ServerRuntime (with single DD each) is more user-friendly. By starting multiple independent runtimes you to easily reuse a single mapping project, tweaking each in-memory copy local to each Runtime (as well as tweaking other parameters like cache). 2 Runtimes can reuse a single DataSource (JNDI, or otherwise), etc.
>> 
>> Andrus
>> 
>