Loading Modules Error due to Filters and Spring Beans

Application Name: Platform Version Number: 2.0.5

Question: I have a problem with loading my module, OpenHMIS Cashier, into OpenMRS. When I load it, I get the following error. https://pastebin.com/pUsSbDtr

The ultimate cause is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'cashierLogoutFilter' is defined.

See below for my setup and what I’ve tried, but does anyone know anything, or what, I’m doing wrong? The class is decorated with the @Component annotation and Spring can see it from my context file.

For some background, I’m in the process of updating this module to use platform 2.0.5. Other’s have had problems with this module (openHMIS module’s settings page error) and I’ve already included those fixes.

I believe the problem comes from using a filter (defined in the config.xml of the OMOD submodule) that is using <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>. You can view the code repository on Git and the file if you wish. Loading the OMOD in platform 1.11.7 works fine. It’s only in 2.0.5 that the error is thrown.

I’ve tried moving the filter class around, specifically defining the bean in the webModuleApplicationContext.xml file, and even moving the definitions to a web.xml file in a WEB-INF folder. This last option enables the module to load, but no filters get registered for the module and the code in the filter does not execute. I’ve also tried defining listeners (<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>) in the files, in addition to referencing <context-param> nodes to put the reference <param-value>classpath*:/webModuleApplicationContext.xml</param-value>.

Any suggestions or thoughts would be appreciated. Also, you will not be able to compile the code and pull it from the repository to do your own testing at the moment. I’m in the process of updating each of this module’s dependencies to platform 2.0.5.

Where is the class decorated with the @Component annotation?

It is located in the omod_1.x submodule, which you can find here. This is included as a dependency to the omod module, which is what unpackages and holds the other modules. I tried moving the class around to the omod_2.x and omod modules to see if that would change anything, but no luck.

@kwburnett, I wonder if it fails after installing the module and restarting the server.

When I step through the OMRS code, it fails on line 544 of WebModuleUtil.java. Is the module installed and the server restarted on f.init(config);?

The component class is “org.openmrs.module.openhmis.cashier.web.filter.CashierLogoutFilter”, and the filter in config.xml is of class “org.springframework.web.filter.DelegatingFilterProxy”. How are the two connected?

From what I read online, specifying a class of org.springframework.web.filter.DelegatingFilterProxy means that filter delegates to Spring to supply the class (see https://stackoverflow.com/questions/6725234/whats-the-point-of-spring-mvcs-delegatingfilterproxy, first answer). So, Spring looks for a bean named “cashierLogoutFilter” to determine which class should go in the filter.

Is there a better way to do this? I’m not sure what the implications of swapping the DelegatingFilterProxy are other than there is a tight coupling there. But, that may be the only way to get it to work. Let me give it a shot.

Here are the results of my tests. After updating the filter to directly reference the class CashierLogoutFilter, the auto-wired properties of the filter are null and aren’t set. So, the filter throws NPEs. @raff this seemed to happen after the module was installed and the server restarted, though I didn’t trace it through the code yet.

I found a SO post mentioning away to handle this, so I applied their solution. But, that gave me errors saying Spring couldn’t find the auto-wire beans, even though they are defined in OpenMRS Core. Here is the error. https://pastebin.com/7MUqTiSi

So, still not sure what to do. Any other thoughts?

"org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.openmrs.module.openhmis.cashier.api.ITimesheetService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: "

Will need to look at your commit and entire module repository to advice appropriately.

Ah, you’re right on the class. I was looking at the wrong auto-wire field. Ok, let me investigate some more and I’ll report back.

So, I finally figured out what the issue was. The problem was with the Legacy UI module. I was using version 1.3.1 in my app. This had a change introduced to make the filters loaded as soon as the module was uploaded. See the change on GitHub.

Downgrading to Legacy UI version 1.2.3 fixed the problem of not being able to upload the file. However, to get the module’s filters to work in 1.2.3 (and in earlier versions of OMRS), you have to stop and restart the module after it’s loaded. I noticed this was the only time loadFilters would be called on the WebModuleUtil class.

In the most recent versions of the Legacy UI, the filters would be loaded before the context was refreshed. Some dependencies are needed by the filter and Spring injects them. However, Spring can only inject them after the context has been refreshed. I switched the order up and made the necessary changes in the Legacy UI code to fix this. View the pull request here.

The module may be using filters incorrectly, but I was able to get the module to upload with no change to the module and only updating the Legacy UI. Thoughts?

I have put comments in the pull request.

@kwburnett your changes look good. I have just merged your pull request. Thanks a lot for the fix! :slight_smile:

Thanks for merging it. My apologies on the headache of the code/branches and thanks for your patience!

No need to apologize because there is always a first time for everyone. Thanks for not giving up. :smile: