Archive

Subscription

Blogroll

Over time the messages in our Spring message.properties files grow stale. When a developer updates/changes code he/she doesn’t necessarily go to the messages.properties and remove all the keys that they removed from code. This has not detrimental effect on code, it just means that when translating into a new language the translator is potentially more work than they need to.

I wrote this quick shell script to loop over the file and do a recursive grep for that key. The key is considered “used” if it exists in the current directory with quotes around it (single or double). This WILL NOT find keys if they are only used programmatically. (e.g. VAR + “.started”)

#!/bin/sh

# Loops over all the keys in the given messages.properties file
# and looks in the current directory for the string in quotes.
# Results are printed to stdout
#
# use: (from the “web” dir in openmrs)
# sh ./findunusedmessages.sh WEB-INF/messages.properties

While migrating from JUnit 3.x to the new 4.x framework, one method I found that was missing was Spring‘s getLoadCount() method on the AbstractDepenpendencyInjectionTest. The value returned allowed us to tell whether a test was running by itself or in a group a tests (like with the ant junit-report target or right-clicking on /test/src and choosing run-as junit test).

Having this method was useful for two reasons:

A test like CreateInitialDataSet that is meant to be configured and run alone. If this test sees that its being run in a group, it returns early and doesn’t actually run the test

The module tests needed to have the application context refreshed before running. To do this, I made the previous test mark the context as “dirty” so that the test directly following it would have a fresh app context.

There were actually two separate solutions:

All tests extend BaseContextSensitiveTest for convenience methods and setup. Every junit class will invoke this class and its constructor. By adding a static variable loadCount and incrementing that in the constructor, I am able to know how many tests have been run up to that point.

The application context doesn’t need to be marked as dirty. The dummy method could actually be removed without replacement.

I’m going to post this here as a reminder to other OpenMRS developers (and myself) and to hopefully save a few hours/days of debugging. The key to getting transactions to work correctly in the webapp is to, well, tell Spring that we’re in a transaction. You can do this by simply putting an @Transactional annotation in the *Service java interface.

Without that key piece of text, the service and its methods will still work. However, they’ll work in a readonly kind of way. All data written to the database will be rolled back when the body of work has completed. This little error manifested itself recently after our reporting code-a-thon. During the event we had to create a new API service, which is only done maybe a few times a year. The service didn’t get the @Transactional tag and so therefore all database editing failed that went through the ReportService. The unit tests set up for the object passed, but that is because a unit test happens all within a single transaction — the rollback is always done after the completion of the test anyway.

I added a note to http://openmrs.org/wiki/OpenMRS_API about the requirement, but I’m sure there will be an OpenMRS developer in the future struggling with their object not saving or updating in the database and be completely baffled by it.

I recently had a very frustrating error that I want to document here for future Googling’s sake. After a non-ideal shutdown of Tomcat and/or the jvm I was unable to start the OpenMRS webapp. Tomcat was giving this error in its log file:

This is somewhat expected with the move from Spring 2.0 to 2.5. As of Spring Framework 2.5 the new url to use in the application context is

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

but even after making this change in the code and redeploying the webapp, Tomcat refused to start giving the same url (with just spring-beans.xsd).

Solution:

A Spring definition file (namely applicationContext-service.xml) was being cached in Tomcat’s work directory and not being replaced on webapp deploy for some reason. I uninstalled the webapp and then deleted all files under <tomcathome>/work/localhost. Upon installing openmrs and starting Tomcat again everything started up as expected.