Custom message source "breaking things".

Hi all,

I’m needing some guidance here… After installing the Initializer module that provides a custom message source, I get this error when I attempt to load the login page:

org.springframework.context.NoSuchMessageException: No message found under code 'ui.i18n.Location.name.2131aff8-2e2a-480a-b7ab-4ac53250262b' for locale 'en_GB'.

However there are no errors printed in the log before that, all modules start fine… etc. Here it is: log.txt (84.2 KB) This is happening with Ref App 2.5 (Core 2.0.1).

The issue arises even if CustomMessageSource does not process any additional .properties files. Its sole presence triggers the problem. So basically this can be reproduced by just adding the Initializer module to the list of modules of Ref App 2.5 and start the server.

Has anyone any idea of what might be happening? I must say that I’m blocked and I have no idea where to look next.

Cc. @wyclif, @mseaton, @dkayiwa

I think you need to set useCodeAsDefaultMessage to true on your custom message source.

On the other hand, I feel like you’ve written boiler point code to add a custom message source for a file based source, isn’t it enough to just extend MutableResourceBundleMessageSource in your module and then add the location(s) of your message files to the basenames property? And then set your subclass as the active message source

@mksd, offhand one possible issue is that the UI Framework module may not support custom message sources. E.g. it may load a message source at module startup or when the spring context is refreshed (e.g. in code like this) and not pick up if you later configure a custom message source.

This is just a wild guess though.

Ok so you suggest that whenever UI Framework attempts to set its message source it misses on the custom messages that Initializer has added?

But what is this: "ui.i18n.Location.name.2131aff8-2e2a-480a-b7ab-4ac53250262b"? I can’t even figure out where this message code is coming from, and why that one specifically is not being translated? Perhaps others codes also can’t be found, but I can’t be sure, that’s the only error popping out at this point.

This code was kindly shared by @mseaton, I just borrowed it as a starting point for loading additional messages at runtime. To give some background, it was at first used in the context of unit tests in the reporting module. @mseaton, any thoughts?

@wyclif, since I’m totally unfamiliar with this message sources tech. in the first place, I may as well try what you suggest. Not sure what basenames can or cannot be, but our custom files are provided from within the app data directory, so they are not on the classpath.

Thanks @darius, somehow your remark hinted that the succession of events could indeed break UI Framework. And by trying this first just on the Platform (as in Core + AH + Initializer + config. folder) confirmed that the issue was very likely linked to UI Framework.

So I defined the bean like this in moduleApplicationContext.xml:

<bean id="initializerMessageSource" class="org.openmrs.module.initializer.InitializerMessageSource"
  init-method="refreshCache"/>

This ensures that InitializerMessageSource#refreshCache() is invoked as soon as the class is wired by Spring, and it looks like it’s solving the issue.

I’m not shouting victory too soon though, I can only see that it doesn’t break anything anymore. We will now try this out in Bahmni and hopefully observe that messages are translated as expected.

@mksd the error message you are getting is because you don’t have a translation for ui.i18n.Location.name.2131aff8-2e2a-480a-b7ab-4ac53250262b there is something neat that the uiframework does to translate for metadata like locations, encounter types etc. but I still think it would fail for the regular message codes that have no translations, setting useCodeAsDefaultMessage on your custom message source should fix it, I think all you need to do is to override the getter for useCodeAsDefaultMessage and return true, the base class you’re extending returns false by default which is why you’re getting that exception.

About my other suggestion, basenames is a field on the message source object from one of the super classes (AsbtractMessageSource), it is the list of files from which the message source loads the translations, the names can be absolute paths or classpath. So extending core’s MutableResourceBundleMessageSource and adding your file path to basenames as seen here should pick up your messages and include them. Do you also see realize from that file in core that useCodeAsDefaultMessage is set to true? Alternatively you could get the spring bean with id mutableResourceBundleMessageSource and add the location to the basenames via one of spring’s bean processing callbacks

If the message code exists and its not getting picked up, then you might want to follow up with @darius’ suggestion about something in UI framework possibly module causing it

This is because the login.gsp page tries to translate the location names using ui.format(...), which uses this feature of the UI Framework module.

Yes, this is part of the fix. I will come back to this later as it has become less critical now, and then I’ll give a try at extending MutableResourceBundleMessageSource as you suggested.

Will I not have to explicitly add the folder containing the .properties files to the class path though? Like do something along these lines: ‘Can a directory be added to the class path at runtime?

The value you specify can be a path to a file or a file on the class path