Thanks ben. I'd still like to do this without adding anything to core in the short term, because i don't have the bandwidth to update the war file on our servers before our 1.8 migration in a few months. At that point, however, it would be nice to have the key property to use in 1.8.
I also don't know how widely used namephonetics is -- if PIH is the only consumer, then putting a stack trace in the logs at startup for the next 2 months before implementing a proper solution bothers me a lot less. I'm going to wait for Mark G. to get back from vacation first, before doing anything anyway. d On Fri, Aug 26, 2011 at 12:06 PM, Ben Wolfe <[email protected]> wrote: > Well, its mostly independent. Sync still knows about name phonetics in > this case, which is not ideal or scalable. > > You should be able to use the generic handler interface and method on the > Context to get all handlers for the NamePhonetics class. The only question > is how to get a specific class of handler so you're sure the handler you > found is the one specified for sync. The simplest solution would be to add > another option to the @Handler annotation for a "key" or something else. > It'd just be a string that is known between SyncService and NamePhonetics to > know whether it has the right handler or not. > > Ben > > On Wed, Aug 24, 2011 at 5:11 PM, Dave Thomas <[email protected]> wrote: >> >> Hi. AOP'ing around SyncService from NamePhonetics seems to work, >> although if you're using NamePhonetics without sync, you get a >> ClassNotFoundException stack trace in the logs during module start, >> which is a little sloppy. Also, I'm not totally sure what the rules >> are: against all versions of OpenMRS past 1.6.x, is this still how >> exceptions while loading an AOP advice class from a module will be >> handled (i.e. other AOP advice classes from the module will still be >> loaded even if the first AOP errors during loading)? Also, there's >> no danger of NamePhonetics being loaded before Sync causing this to >> fail, right? This is why the context is built twice at startup? >> >> -------------- >> >> Here's short-term option 2: >> >> in NamePhonetics, you add this handler: >> >> >> @Handler(supports = PersonName.class) >> public class PersonNamePhoneticsSaveHandler implements >> RequiredDataHandler<PersonName>{ >> >> public void handle(PersonName personName, User currentUser, Date >> currentDate, String other) { >> >> NamePhoneticsUtil.savePhoneticsForPersonName(personName); >> >> } >> } >> >> >> and in sync, you add the following postProcessor to SyncService: >> >> >> public class NamePhoneticsSaveOrUpdateAfterAdvice implements >> AfterReturningAdvice { >> >> >> private static final String NAME_PHONETICS_HANDLER_CLASS = >> "org.openmrs.module.namephonetics.advice.PersonNamePhoneticsSaveHandler"; >> private RequiredDataHandler<PersonName> handler = null; >> >> >> @SuppressWarnings("unchecked") >> public synchronized void afterReturning(Object returnVal, Method >> method, Object[] arg2, Object arg3) throws Throwable { >> String methodName = method.getName(); >> if (methodName.equals("saveOrUpdate")) { >> //check for valid main argument >> if (arg2 == null || arg2.length == 0) >> return; >> Object mainArgument = arg2[0]; >> if (mainArgument == null) >> return; >> if (mainArgument instanceof PersonName){ >> Class<?> handlerClass = null; >> try { >> handlerClass = >> Class.forName(NAME_PHONETICS_HANDLER_CLASS, false, >> OpenmrsClassLoader.getInstance()); >> } catch (Exception ex){ >> handler = null; >> //pass on doing anything else... >> } >> if (handlerClass != null){ >> if (handler == null) >> handler = >> (RequiredDataHandler<PersonName>) >> HandlerUtil.getPreferredHandler(handlerClass, PersonName.class); >> handler.handle((PersonName) >> mainArgument, null, null, null); >> } >> } >> } >> } >> } >> >> >> This approach creates true module independence with no changes to >> core, and no problems just running sync, or just running >> namephonetics. >> >> The sort-of-lame thing about this is that the Sync post-processor >> looks for a handler that's an implementation of RequiredDataHandler, >> which was the most useful handler interface i could find in core. It >> might be useful to create a new core handler interface with the single >> argument handle method: handle(OpenmrsObject o). Maybe >> GenericOpenmrsObjectHandler? This interface could also require Ben's >> toBeUsedBy(String className) method (where in this case this method >> would return org.openmrs.module.sync). >> >> Another lesser sort-of-lame thing is having such a specific item in >> Sync at all -- this was the best i could come up with without pushing >> something new into 1.6.x core, which i don't want to do because i >> don't have the bandwidth for upgrading the war file on all of our >> remote servers. >> >> Thoughts? I have both of these implemented, and i can apply either one. >> >> I really like the new handler interface idea, but it depends on an >> upgrade to core, which then introduces core version dependencies to >> both NamePhonetics and Sync. >> >> d >> >> On 8/24/11, Ben Wolfe <[email protected]> wrote: >> > The quickest solution would be to AOP around the sync save, check to see >> > if >> > its a personname, and update accordingly. >> > >> > Ben >> > >> > On Wed, Aug 24, 2011 at 2:40 AM, Darius Jazayeri >> > <[email protected]>wrote: >> > >> >> I agree that this seems like something that's more appropriate to >> >> calculate >> >> on the child after importing a name. >> >> >> >> The problem is that we do our post-service-call actions using AOP >> >> rather >> >> than having a proper event-notification mechanism. (Dave, I assume that >> >> namephonetics does AOP-after savePerson, savePersonName, etc.) >> >> >> >> Ideally sync would be able to call a core method like this: >> >> save(importedObject); // uses something internal to sync. >> >> publishEvent(importedObject, "saved"); >> >> >> >> Another solution (also requiring core changes) would be if there was a >> >> generic save method would would delegate to the appropriate service >> >> method. >> >> So that sync doesn't have to do its own hibernateSession.save(object) >> >> which >> >> bypasses the service layer. >> >> >> >> I know that Rafal implemented something like this in the Metadata >> >> Sharing >> >> Module--it actually scans everything that implements OpenmrsService on >> >> the >> >> classpath, and finds save(OpenmrsObject) methods. >> >> >> >> -Darius >> >> >> >> On Mon, Aug 22, 2011 at 12:41 AM, Ben Wolfe <[email protected]> wrote: >> >> >> >>> Am I remembering right that NamePhonetics has a table listing out the >> >>> manipulations of the names? That it doesn't do that calculation on >> >>> the >> >>> fly? It does sound a lot like conceptword in that you don't need to >> >>> send >> >>> those back an forth, instead have them re-calculated on the receiving >> >>> server. >> >>> >> >>> We do have the @Handler annotation in trunk. But its usually used as >> >>> an >> >>> @Handler(supports=NamePhonetics.class) PLUS extended a special class. >> >>> This >> >>> class would have to be in the sync module. Its possible that you >> >>> extend >> >>> a >> >>> class from sync and then use the aware_of_module tag in config.xml. >> >>> This >> >>> is >> >>> a loose module requirement that Daniel did >> >>> https://tickets.openmrs.org/browse/TRUNK-1587 (but its 1.9+ :-/) >> >>> >> >>> The generic Handler class you're proposing would just have a handle(T) >> >>> method? What happens when there are two or more classes defined as: >> >>> @Handler(supports=NamePhonetics.class) >> >>> public class NamePhoneticsHandler extends Handler >> >>> ? >> >>> >> >>> How is sync supposed to know which one to use? Or which one is for >> >>> sync >> >>> and which one is for some other handler? >> >>> >> >>> Answering my own question after pondering for a few minutes: >> >>> add another method called "whoAmIIntendedToBeUsedBy()" that returns a >> >>> String key that the sync module can use to distinguish different >> >>> handler >> >>> classes. (Obviously the name of the method needs some work...) >> >>> >> >>> Ben >> >>> >> >>> >> >>> On Sat, Aug 20, 2011 at 12:10 PM, Dave Thomas <[email protected]> >> >>> wrote: >> >>> >> >>>> Hi. At PIH, we have a few implementations using both sync and >> >>>> namephonetics. Right now, namephonetics objects aren't propagating >> >>>> through sync which is something we want to fix. >> >>>> >> >>>> Option 1 is to have NamePhonetics extend OpenmrsObject, and let sync >> >>>> propogate these. The downsides are 1) extra stuff in the payloads, >> >>>> and 2) I have a feeling there would need to be explicit handling of >> >>>> NamePhonetics objects during ingest, because PersonName objects are >> >>>> explicitly marked as getting processed last (because of the famous >> >>>> TreeSet re-ordering bug). This, i think, would mean that there >> >>>> would >> >>>> have to be a new category of 'things to process last' in the ingest >> >>>> routine, which in sync we could maybe define safely as anything >> >>>> associated with a module (org.openmrs.module*)? Not sure about this >> >>>> though. It is definitely true that we don't want to build any module >> >>>> dependencies between Sync and NamePhonetics. >> >>>> >> >>>> Option 2 is to treat NamePhonetics like ConceptWords in that they're >> >>>> calculated locally. NamePhonetics currently AOPs around savePerson >> >>>> to >> >>>> do this on a local system, but the saving of PersonNames during sync >> >>>> ingest uses the SyncService.saveOrUpdate method. Here's what I was >> >>>> thinking -- what if SyncService had a postInterceptor modeled on >> >>>> RequiredDataAdvice? This postInterceptor class would check for >> >>>> registered handlers for incoming sync items. The only architectural >> >>>> piece that would be needed to do this and avoid building in module >> >>>> dependencies between Sync and NamePhonetics would be a truly default >> >>>> Handler interface in OpenMRS core. NamePhonetics would then register >> >>>> a PersonName handler. Sync ingest would then look for a handler in >> >>>> the saveOrUpdate postProcessor, and if found, apply it. If not found >> >>>> (for sync implementations not using namephonetics), no problem. >> >>>> >> >>>> Option 2 seems like overkill, maybe, although i like the idea of >> >>>> keeping sync packages as simple and small as possible... thoughts on >> >>>> this would be appreciated. >> >>>> >> >>>> Also, generally, would it be useful to have a truly generic handler >> >>>> interface in core (or actually, maybe generic pre-processor and >> >>>> post-processor handler interfaces)? This would be kind of a cool >> >>>> way >> >>>> for modules to register handlers against each other, without building >> >>>> in module dependencies. >> >>>> >> >>>> d >> >>>> >> >>>> _________________________________________ >> >>>> >> >>>> To unsubscribe from OpenMRS Developers' mailing list, send an e-mail >> >>>> to >> >>>> [email protected] with "SIGNOFF openmrs-devel-l" in the >> >>>> body >> >>>> (not the subject) of your e-mail. >> >>>> >> >>>> [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l] >> >>>> >> >>> >> >>> ------------------------------ >> >>> Click here to >> >>> >> >>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from >> >>> OpenMRS Developers' mailing list >> >> >> >> >> >> ------------------------------ >> >> Click here to >> >> >> >> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from >> >> OpenMRS Developers' mailing list >> > >> > _________________________________________ >> > >> > To unsubscribe from OpenMRS Developers' mailing list, send an e-mail to >> > [email protected] with "SIGNOFF openmrs-devel-l" in the body >> > (not >> > the subject) of your e-mail. >> > >> > [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l] >> > >> >> _________________________________________ >> >> To unsubscribe from OpenMRS Developers' mailing list, send an e-mail to >> [email protected] with "SIGNOFF openmrs-devel-l" in the body (not >> the subject) of your e-mail. >> >> [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l] > > ________________________________ > Click here to unsubscribe from OpenMRS Developers' mailing list _________________________________________ To unsubscribe from OpenMRS Developers' mailing list, send an e-mail to [email protected] with "SIGNOFF openmrs-devel-l" in the body (not the subject) of your e-mail. [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]

