Spring Event: Listeners not getting invoked from other omods

Hello folks, We have this scenario

  1. Publish Spring ApplicationEvent
  2. listen from another omod, and do needful

When we write the Listener in the same publishing omod, we receive the event but not from a separate omod. Any reason you think this can happen? The separate omod has the right dependencies (otherwise the omod would not load).

Is it something to do with the differential classloading that OMRS does? although the second omod has the right dependencies specified.

@dkayiwa @raff

When is the event fired? I.e., is it done in the Activator or somewhere else?

Event is fired through an advice on patient service on save.

Asking because it’s really only the Activator’s methods that might get called with the thread-local classloader set to the module classloader, which sometimes has a restricted view. Anywhere else, the classloader should be OpenmrsClassLoader, which should be able to find any class. That’s also the context all Spring beans are registered in. And that’s really the only class-loading weirdness we do.

OTOH, if it were classloader related, I’d expect you’d get a ClassNotFoundException, and I’m guessing there are no errors or anything shown in the logs? Is there a way you can confirm that the listener bean is actually registered in the Spring context?

that was my understanding as well, since effectively in the chain, if an omod mentions that they require another omod, then the classloaders are chained(?). Since no ClassNotFoundException was thrown, I would assume that this part is ok. I will check if the bean is getting registered with spring context.

Yes. For each module, we create a ModuleClassLoader that is responsible for loading classes for that module. It also has references for all the modules that the given module declares as required or that it is aware of. The loadClass() implementation will try to find a class internally and, if that fails, iterate through each required or aware of module and call the corresponding classloaders.

The OpenmrsClassLoader basically works the same, except that it iterates through all ModuleClassLoaders in the order they were loaded to load a class. Which basically means that outside of when the module is being (re-)started, the classpath should be able to find any class in. any. module.

1 Like