> 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 <[email protected]> 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 > <[email protected]> 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 <[email protected]> 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 <[email protected]> >>> 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 <[email protected]> >>>> 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 >>>>> >>> >> >
