Hey, already done. I'll try to check in this morning. On Sep 2, 2011 10:19 PM, "Mark Goodrich" <[email protected]> wrote: > Dave-- > > Do you want me to try to pick this one up? There doesn't seem to be much objection to using a hibernate interceptor, so I could prototype this solution next week. > > -Mark > > -----Original Message----- > From: [email protected] [mailto:[email protected]] On Behalf Of Mark Goodrich > Sent: Thursday, September 01, 2011 9:52 AM > To: [email protected] > Subject: Re: [OPENMRS-DEV] sync and namephonetics, and openmrs handlers > > One key point is that we would be using a hibernate interceptor in Name Phonetics for both sync purposes and standard purposes. (That is, the Hibernate interceptor would completely replace the current AOP interceptor--we could maintain both, but this seems ugly). > > However, I still agree that this seems like the best solution (or at least the best solution that doesn't require a change to core). > > Mark > > -----Original Message----- > From: [email protected] [mailto:[email protected]] On Behalf Of Michael Seaton > Sent: Thursday, September 01, 2011 9:23 AM > To: [email protected] > Subject: Re: [OPENMRS-DEV] sync and namephonetics, and openmrs handlers > > If it works, using a hibernate interceptor seems to me to be the best of > the available options. > > Although I understand the desire to keep us from "baking in hibernate", > I think for all practical purposes, that ship has sailed. And > particularly since sync uses hibernate interceptors and bypasses the > API, it seems like a logical extension to use the same mechanism within > modules for sync purposes. If one day we wish to remove this hibernate > dependency, we can always revisit this question and put in an > alternative solution... > > The advantages that I see with this approach: > > * It's more reliable than AOP (eg. AOP only works if only those method > calls it is listening for are the ones that can save Person Names) > * It may reduce the AOP overhead > * It requires no dependencies at all between sync and namephonetics to work > * It does not force us to make namephonetics extend OpenmrsObject > * It reduces the payload of sync transmissions as namephonetics would > not be synched, but generated locally > * It will work even if namephonetics is not installed on all servers > within a sync network > > Any other opinions? Is anything I have put above incorrect? > > Thanks, > Mike > > > > > On 09/01/2011 04:40 AM, Dave Thomas wrote: >> I like Ben's idea of adding the 'intendedTarget' to the Handler >> interface in core even if we don't use it in this case. This creates >> a nice mechanism for modules to register handlers intended for each >> other's services, which will be useful i think in the long run. >> >> This however, creates a 'must update' situation for both rwanda and >> haiti, which is difficult. And this handler fix would need to be >> applied to all branches 1.6 onwards. >> >> But true, we could move the PersonName logic to a hibernate >> interceptor, now that we've gone down that road. Although we'd have >> to be explicit about this being a post-processing event to avoid the >> famous hibernate cascade error, but maybe this is a trivial concern. >> >> Opinions on baking hibernate into namephonetics? >> >> d >> >> On 8/31/11, Friedman, Roger (CDC/CGH/DGHA) (CTR)<[email protected]> wrote: >>> Are we baking in Hibernate now? >>> >>> -----Original Message----- >>> From: [email protected] [mailto:[email protected]] On Behalf Of Mark Goodrich >>> Sent: Wednesday, August 31, 2011 5:33 PM >>> To: [email protected] >>> Subject: Re: [OPENMRS-DEV] sync and namephonetics, and openmrs handlers >>> >>> Just talked with Mike about this. I'm not that familiar with Hibernate >>> interceptors, but is there any reason we can't change Name Phonetic so that >>> instead of AOP'ing around savePatient it uses a Hibernate interceptor to >>> intercept all saves of PersonName at the hibernate level? >>> >>> Mark >>> >>> -----Original Message----- >>> From: [email protected] [mailto:[email protected]] On Behalf Of Dave Thomas >>> Sent: Friday, August 26, 2011 7:57 AM >>> To: [email protected] >>> Subject: Re: [OPENMRS-DEV] sync and namephonetics, and openmrs handlers >>> >>> 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] >>> >>> _________________________________________ >>> >>> 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] >>> >> _________________________________________ >> >> 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] > > _________________________________________ > > 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]
_________________________________________ 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]

