Hi, I found a bug in the NSArray handling in the encoder, here is my class with a fix, do not use the previous version.
Samuel > Le 9 nov. 2024 à 10:11, Samuel Pelletier via Webobjects-dev > <webobjects-dev@lists.apple.com> a écrit : > > Hi, > > Last week I encountered a problem very similar to a previous OC case... I > have a report page with some user defined filter that use EOs and do the > fetch in background. Creating a snapshot of all possible parameter seems a > fragile solution since it required a very good discipline to make sure the > problem does not coma back... Having a way to archive or serialize an > EOQualifier with no exigent context dependency seems a bette solution. > > After some digging in Wonder sources and list archive, I found > EOKeyValueArchiving but never found a complete working code using EOs. It > seems there is no basic implementation of delegate and support classes in > WOnder or elsewhere to make this works. I wrote those classes that convert > any EO to EOGlobalID on archiving and EOGlobalID back to EO using the > specified EditingContext when unarchiving. > > Here si the recipe and my utility classe source for anyone that may need it. > I can prepare a pull request to add it to Wonder if others can confirm there > is nothing already in place that do that. > > Regards > > Samuel > > > public class RapportRendementMatiere extends BaseRapportComponent { > ... > private KAKeyValueArchive filtersArchive = new KAKeyValueArchive(); > > public actionStartingTheFetch() { > // build the qualifier array qualifiers in the request using Eos and > archive it. > filtersArchive.archiveObject(new ERXAndQualifier(qualifiers), > "qualifier"); > // Add some other values that may require access to session or other > EOs > filtersArchive.archiveObject(dateDebutToFind(), "dateDebut"); > filtersArchive.archiveObject(rapportMachines(), "rapportMachines"); > > // Start background thread (could use ERX tasks or any other means > here... > new Thread(new Runnable() { > @Override > public void run() { > ERXApplication._startRequest(); > try { > EOEditingContext ec = ERXEC.newEditingContext(); > fetchRapport(ec); > etat = Etat.Affiche; > } finally { > ERXApplication._endRequest(); > } > } > }).start(); > } > > public void fetchRapport(EOEditingContext ec) { > // In background thread... > filtersArchive.setEditingContext(ec); > EOQualifier qualifier = filtersArchive.unarchiveObject("qualifier"); > if (qualifier != null) { > // use the qualifier > } > > // get the date that was in session > LocalDate dateDebut = filtersArchive.unarchiveObject("dateDebut"); > > // get array of EOs > NSArray<Machine> rapportMachines = > filtersArchive.unarchiveObject("rapportMachines"); > ... > } > } > > > > > Utility class source package com.kaviju.commons.model; import com.webobjects.eocontrol.EOEditingContext; import com.webobjects.eocontrol.EOGenericRecord; import com.webobjects.eocontrol.EOGlobalID; import com.webobjects.eocontrol.EOKeyValueArchiver; import com.webobjects.eocontrol.EOKeyValueArchiving; import com.webobjects.eocontrol.EOKeyValueUnarchiver; import com.webobjects.foundation.NSArray; import com.webobjects.foundation.NSKeyValueCoding; import com.webobjects.foundation.NSMutableArray; import er.extensions.foundation.ERXValueUtilities; public class KAKeyValueArchive { static { EOKeyValueArchiving.Support.setSupportForClass(new KAKeyValueArchiverEoSupport(), EOGenericRecord.class); } private KAKeyValueArchiver archiver; public KAKeyValueArchive() { archiver = new KAKeyValueArchiver(); archiver.setDelegate(new ArchiverDelegate()); } public void archiveObject(Object object, String key) { object = object != null ? object : NSKeyValueCoding.NullValue; archiver.encodeObject(object, key); } public KAKeyValueUnarchiver unarchiverWithEditingContext(EOEditingContext ec) { return new KAKeyValueUnarchiver(this, ec); } // EOKeyValueArchiver n'encode pas les NSArray correctement... public static class KAKeyValueArchiver extends EOKeyValueArchiver { @SuppressWarnings({ "unchecked", "rawtypes" }) @Override protected void _encodeArrayForKey(NSArray objects, String key) { int count = objects.count(); if (count > 0) { NSMutableArray<Object> array = new NSMutableArray<>(count); for (int i = 0; i < count; i++) { KAKeyValueArchiver nestedCoder = new KAKeyValueArchiver(); nestedCoder.setDelegate(delegate()); Object object = objects.objectAtIndex(i); nestedCoder.encodeObject(object, "dictionary"); array.addObject(nestedCoder.dictionary().objectForKey("dictionary")); } this._propertyList.setObjectForKey(array, key); } else { this._propertyList.setObjectForKey(objects, key); } } } public static class KAKeyValueUnarchiver { private KAKeyValueArchive archive; private EOKeyValueUnarchiver unarchiver; public KAKeyValueUnarchiver(KAKeyValueArchive archive) { this.archive = archive; } public KAKeyValueUnarchiver(KAKeyValueArchive archive, EOEditingContext ec) { this.archive = archive; setEditingContext(ec); } public void setEditingContext(EOEditingContext ec) { unarchiver = new EOKeyValueUnarchiver(archive.archiver.dictionary()); unarchiver.setDelegate(new UnarchiverDelegate(ec)); } @SuppressWarnings({ "unchecked" }) public <T extends Object> T unarchiveObject(String key) { Object value = unarchiver.decodeObjectForKey(key); if (ERXValueUtilities.isNull(value)) { return null; } return (T)value; } } public static class KAKeyValueArchiverEoSupport extends EOKeyValueArchiving.Support { @Override public void encodeWithKeyValueArchiver(Object paramObject, EOKeyValueArchiver param1eoKeyValueArchiver) { param1eoKeyValueArchiver.encodeReferenceToObject(paramObject, "eo"); } @Override public Object decodeObjectWithKeyValueUnarchiver(EOKeyValueUnarchiver param1eoKeyValueUnarchiver) { return param1eoKeyValueUnarchiver.decodeObjectReferenceForKey("eo"); } } public static class ArchiverDelegate implements EOKeyValueArchiver.Delegate { @Override public Object referenceToEncodeForObject(EOKeyValueArchiver paramEOKeyValueArchiver, Object paramObject) { if (paramObject instanceof EOGenericRecord) { return ((EOGenericRecord)paramObject).__globalID(); } return paramObject; } } public static class UnarchiverDelegate implements EOKeyValueUnarchiver.Delegate { private final EOEditingContext ec; public UnarchiverDelegate(EOEditingContext ec) { this.ec = ec; } @Override public Object unarchiverObjectForReference(EOKeyValueUnarchiver param1eoKeyValueUnarchiver, Object paramObject) { if (paramObject instanceof EOGlobalID) { return ec.faultForGlobalID((EOGlobalID) paramObject, ec); } return paramObject; } } } _______________________________________________ Do not post admin requests to the list. They will be ignored. Webobjects-dev mailing list (Webobjects-dev@lists.apple.com) Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com