Re: Migrations auto-run issue with shared Entities
Re: Migrations auto-run issue with shared Entities
- Subject: Re: Migrations auto-run issue with shared Entities
- From: Chuck Hill <email@hidden>
- Date: Mon, 16 Jul 2012 20:23:58 -0700
If even Avendasora does not want to use it.... it MUST be pretty bad. :-P
On 2012-07-16, at 7:29 PM, David Avendasora wrote:
> Hi Robert and Johan,
>
> First of all, DON'T DO IT!!! For the love of God and all that is good and kind in this world, don't do it!
>
> If you won't not do it for me, then don't do it for Chuck and all the little fluffy bunnies!
>
> Don't mark fetch specs as shared! Turn off the shared EC, walk away and don't look back.
>
> The EOSharedEditingContext (EOSEC) is evil. Evil, EVIL, E-V-I-L! And not in an obvious, spawn-of-satan way, oh no, it is far more subtle than that. There are lots of things that either don't work, or work differently when an EO is shared and none of them are obvious. You have to always keep in mind that the object you are working with is in the EOSEC and often do things differently. It completely ignores the fundamental concept of polymorphism.
>
> For example, let's say you want to edit the name of a Country, which is a shared. You can't just edit it in the EOSEC because EOSEC#saveChanges() raises an exception. You have to localInstance it into a standard EC first do your editing and save it there. But even that's not as easy as it sounds. Here's a fun exercise:
>
> EOEditingContext newEC = ERXEC.newEditingContext();
> country = country.localInstanceIn(newEC);
>
> What editing context is the country in? newEC? Nope. It's still in the EOSEC. Obvious, right? Welcome to the nightmare.
>
> First you have to call: newEC.setSharedEditingContext(null); before localInstanceIn will work.
>
> ERXEC's auto-locking is one of the many things that does not take the EOSharedEditingContext into account. You will have to _manually_ lock and unlock all calls to the EOSharedEditingContext except (according to the documentation):
> • objectsWithFetchSpecification
> • bindObjectsWithFetchSpecification
> • faultForGlobalID
> • objectForGlobalID
> Do yourself a HUGE favor and use EREnterpriseObjectCache instead (http://jenkins.wocommunity.org/job/Wonder/lastSuccessfulBuild/javadoc/er/extensions/eof/ERXEnterpriseObjectCache.html). It is much, much, much better. It has a few flaws as well, but an EO that came out of the EREnterpriseObjectCache is a regular EO and can be passed around and edited the same as any other EO, which is absolutely NOT the case with an EO that is in an EOSharedEditingContext.
>
> Do not use it! You will spend a huge amount of time writing extra code to make it work.
>
> What? Still here? You have a strong masochistic streak? Well, okely dokely then, here we go:
>
> I have a patch but unfortunately it's really not ready for prime-time, but I've included the code (as-is) below.
>
> The core piece of it is to modify ERXApplication#migrationsWillRun(ERXMigrator) and ERXApplication#migrationsDidRun(ERXMigrator) as follows:
>
> private boolean _isSharedObjectLoadingEnabledCachedValue;
>
> protected void migrationsWillRun(ERXMigrator migrator) {
> _isSharedObjectLoadingEnabledCachedValue = ERXDatabaseContext.isSharedObjectLoadingEnabled();
> if (EODatabaseContext.isSharedObjectLoadingEnabled()) {
> EODatabaseContext.setSharedObjectLoadingEnabled(false);
> }
> }
>
> protected void migrationsDidRun(ERXMigrator migrator) {
> if (_isSharedObjectLoadingEnabledCachedValue) {
> EODatabaseContext.setSharedObjectLoadingEnabled(true);
> EOSharedEditingContext sharedEC = EOSharedEditingContext.defaultSharedEditingContext();
> ERXDatabaseContext.loadSharedObjects(sharedEC);
> }
> }
>
> But unfortunately, because the initial database access occurred while shared object loading was disabled, now EOF won't automatically load the shared objects for you. You have to manually load it. I've added the method below to ERXDatabaseContext. It will load/reload all the shared entities (you can see I call it as the last thing in the migrationsDidRun method above).
>
> public static final String FETCH_ALL_FETCH_SPEC_NAME = "FetchAll";
>
> /**
> * Method to manually load (or reload) all shared EOs by iterating through all the models
> *
> * @param sharedEC
> *
> * @author David Avendasora
> * @since Jul 13, 2012
> */
> public static synchronized void loadSharedObjects(EOSharedEditingContext sharedEC) {
> EOModelGroup modelGroup = EOModelGroup.defaultGroup();
> NSArray<EOModel> models = modelGroup.models().immutableClone();
> for (EOModel model : models) {
> String modelFileName = model.name() + ".eomodeld";
> NSArray<EOEntity> entitiesWithSharedObjects = model.entitiesWithSharedObjects().immutableClone();
> for (EOEntity entity : entitiesWithSharedObjects) {
> String entityFileName = modelFileName + File.pathSeparator + entity.name() + ".plist";
> NSArray<String> sharedObjectFetchSpecNames = entity.sharedObjectFetchSpecificationNames();
> if (sharedObjectFetchSpecNames.containsObject(FETCH_ALL_FETCH_SPEC_NAME)) {
> sharedObjectFetchSpecNames = new NSArray<String>(FETCH_ALL_FETCH_SPEC_NAME);
> }
> for (String fetchSpecName : sharedObjectFetchSpecNames) {
> String fetchSpecFileName = modelFileName + File.pathSeparator + entity.name() + ".fspec";
> EOFetchSpecification fetchSpec = entity.fetchSpecificationNamed(fetchSpecName);
> if (fetchSpec != null) {
> // no need to lock because the
> // bindObjectsWithFetchSpecification(EOFetchSpecification, String)
> // method is thread safe.
> sharedEC.bindObjectsWithFetchSpecification(fetchSpec, fetchSpecName);
> }
> else {
> log.warn("Problem found in Entity \"" + entity.name() + "\": \""
> + fetchSpecName + "\" is listed in the \"sharedObjectFetchSpecificationNames\" element of the \""
> + entityFileName + "\" file, but there is no corresponding \""
> + fetchSpecName + "\" element in the \""
> + fetchSpecFileName + "\" file.");
> }
> }
> }
> }
> }
>
> I'm not 100% sure I'm doing the right thing with regards to loading the modelGroup and models … I'm not as comfortable down at this level of EOF as I probably should be. It works, but it might now work for everyone.
>
> Now if I could just scrub hard enough to get this dirty feeling to go away.
>
> Dave
>
> On Jul 15, 2012, at 2:30 PM, Johann Werner wrote:
>
>> I saw a patch for exactly that problem recently in the fork of amagavi. Hopefully there will be a pull request soon (hi David, are you reading this ;-)
>>
>> jw
>>
>>
>> Am 15.07.2012 um 07:52 schrieb Mr. Robert Hanviriyapunt:
>>
>>> I had some issues with Migrations just now when I made an entity Shared. The application started up and attempted to load the shared entity before Migrations could create the table for it. Anyone else had the same problem? My work around was to de-select Shared for the entity, start up the application, stop the application, re-select Shared for the entity, then re-start the application. Gonna be a pain if I have to do this on for a deploy to a stage or prod environment tho.
>>>
>>> = Robert =
>>
>>
>>
>> _______________________________________________
>> Do not post admin requests to the list. They will be ignored.
>> Webobjects-dev mailing list (email@hidden)
>> Help/Unsubscribe/Update your Subscription:
>>
>> This email sent to email@hidden
>>
>>
>
>
> —————————————————————————————
> WebObjects - so easy that even Dave Avendasora can do it!™
> —————————————————————————————
> David Avendasora
> Senior Software Abuser
> Kaiten, Inc.
>
>
>
>
> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Webobjects-dev mailing list (email@hidden)
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
--
Chuck Hill Senior Consultant / VP Development
Practical WebObjects - for developers who want to increase their overall knowledge of WebObjects or who are trying to solve specific problems.
http://www.global-village.net/gvc/practical_webobjects
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden