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 >>>> >> >
