Most apps only need a single ServerRuntime, not multiple. You can pass
multiple DataDomains (models) to a single ServerRuntime constructor.
The runtime itself isn't that similar to the OSC. It is really just a thing
that configures the dependency injection and becomes the entry point to
Cayenne.
Personally, I just store the runtime wherever is convenient. In tomcat,
that is inside the ServletContext, which is like a singleton. It's not
really much better than just using a static variable, except for cases
where you want to hot redeploy an app to a running container (which isn't
usually a good idea anyway, and doesn't apply to WO).
You can create a peer context like this if you runtime has been bound to
the current thread using
CayenneRuntime.bindThreadInjector(runtime.getInjector())
public static ObjectContext newObjectContext() {
ObjectContextFactory factory =
CayenneRuntime.getThreadInjector().getInstance(ObjectContextFactory.class);
return (factory != null) ? factory.createContext() : null;
}
On Tue, Sep 6, 2016 at 4:01 PM Ramsey Gurley <[email protected]>
wrote:
> Hi all,
>
> Long time EOF/WebObjects user, new to Cayenne. I’m finding a lot of
> Cayenne is very similar to EOF. There are clearly major differences too.
> One of these is the ServerRuntime concept. It seems like it is fairly
> similar to an EOObjectStoreCoordinator at first glance, but I’m finding it
> is quite different.
>
> Let me share some code to illustrate my confusion:
>
> final ServerRuntime first = new ServerRuntime("cayenne-project.xml");
> final ServerRuntime second = new ServerRuntime("cayenne-project.xml");
> final ServerRuntime third = new ServerRuntime("cayenne-project2.xml");
> final ObjectContext oc = first.newContext();
> final ObjectContext oc2 = second.newContext(oc);
> final ObjectContext oc3 = third.newContext(oc);
> final ObjectContext oc4 = third.newContext();
> final ObjectContext oc5 = first.newContext(oc4);
> final Customer c1 = Customer.customerForLoginId(oc, "login id");
> final Customer c2 = Customer.customerForLoginId(oc2, "login id");
> final Customer c3 = Customer.customerForLoginId(oc3, "login id");
> final Customer c4 = Customer.customerForLoginId(oc4, "login id");
> final Customer c5 = Customer.customerForLoginId(oc5, "login id");
>
> where
>
> public static Customer customerForLoginId(final ObjectContext context,
> final String loginId) {
> return SelectQuery.query(Customer.class,
> LOGIN_ID.eq(loginId)).selectOne(context);
> }
>
> cayenne-project.xml contains all my cayenne models. cayenne-project2.xml
> is entirely empty. Exceptions are not thrown until the last two lines
> fetching c4 and c5. I didn’t expect to make it past oc2. I only expected c1
> to work for fetching.
>
> In the given situation, I’m obviously working on authentication. In the
> EOF code there is a process that logs a login attempt. In order to do that
> in EOF, I use a peer editing context to create, edit, and save the log
> object to the database. Therefore, I need a way to get a peer ObjectContext
> given an ObjectContext. Thus far, the best I’ve come up with is to have a
> public static final ServerRuntime stashed on a utility class, and use that
> one instance for everything… but this seems to go against all the work done
> with dependency injection. I tried to follow the advice found in this
> message,
>
>
> http://cayenne.markmail.org/search/?q=peer+objectcontext#query:peer%20objectcontext+page:2+mid:v77r6qhv6c4m72iy+state:results
>
> but storing the Injector in the user properties breaks serialization of
> the ObjectContext. Is there an easy way to get a peer OC that I am missing?
> Also, how do I know the OC is appropriate for something like a SelectQuery?
> Do I need to wrap all calls in try blocks in case some code hands in the
> wrong ServerRuntime’s OC?
>
> Thanks,
>
> Ramsey
>
>