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

propfile=$1
props=`awk -F= ‘{print $1}’ $propfile`
count=0
total=0

echo “These property keys were not found in the code base:”
for prop in $props
do
#echo “Looking for property: $prop”
if [ ! -z “$prop” ];
then
total=`expr $total + 1`
output=`grep –exclude-dir=”.svn” -re “[\’\”]$prop[\’\”]” *`
if [ -z “$output” ];
then
echo “$prop”
count=`expr $count + 1`
fi
fi
done

echo “done! Found $count possibly uneeded message keys in $propfile (out of $total total keys)”

Download the file here: findunusedmessages.sh

This is in the babble, openmrs category tagged as , , , ,

Add a comment »

Currently tables created in MySQL default to MyISam. This is unacceptable for us at Openmrs. You can set a property in your my.cnf file called “default-storage-engine”, but I needed a solution that didn’t involve implementers having to modify their system config files.

I changed the jdbc connection url string to set a session property that sets InnoDB as the default engine:

jdbc:mysql://localhost:3306/databasename?autoReconnect=true&sessionVariables=storage_engine=InnoDB

NOTE! Requires mysql jdbc connecter version 3.1.18 or greater. See http://dev.mysql.com/doc/refman/5.0/en/connector-j.html for documentation and then http://dev.mysql.com/downloads/connector/j/ to download.

The error message I was getting before upgrading the mysql jdbc connector was:

java.sql.SQLException: Server connection failure during transaction. Due to underlying exception: ‘java.sql.SQLException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ” at line 1’.

** BEGIN NESTED EXCEPTION **

java.sql.SQLException
MESSAGE: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ” at line 1

STACKTRACE:

java.sql.SQLException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ” at line 1
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2921)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1570)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1665)
at com.mysql.jdbc.Connection.execSQL(Connection.java:2972)
at com.mysql.jdbc.Connection.execSQL(Connection.java:2902)
at com.mysql.jdbc.Statement.executeUpdate(Statement.java:929)
at com.mysql.jdbc.Connection.setSessionVariables(Connection.java:5077)
at com.mysql.jdbc.Connection.initializePropsFromServer(Connection.java:3680)
at com.mysql.jdbc.Connection.createNewIO(Connection.java:2684)
at com.mysql.jdbc.Connection.<init>(Connection.java:1474)
at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:264)
at com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:135)
at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:182)
at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:171)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:137)
at com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1014)
at com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:32)
at com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask.run(BasicResourcePool.java:1810)
at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)

This is in the babble category tagged as ,

Add a comment »

For some reason Java doesn’t like to obey http forwards if the protocol is changing. It has been this way for a while: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4620571.  So when I was trying to load https://modules.openmrs.org that had an apache redirectMatch to http://modules.openmrs.org, I would get the html for the 301 redirect instead of the source of http://modules.openmrs.org.

I was lucky that I have control over the server and could change the http/https to a simply proxy instead of redirecting.  If I didn’t, I would have had to catch the protocol change and refetch the new url.

It took me a while to find an answer for this because these keywords didn’t give many results on google: URLConnection HttpURLConnection openConnection() connect() getInputStream() Apache redirectMatch 301 302.

This is in the babble category tagged as ,

2 comments »

- 25 Jul 2008 -

I was recently tasked with finding out the number of methods in each class in each package inside of OpenMRS. My first thought was to write a java class to do some reflection. My second thought was to find a java class that someone else had written and use that. My third thought was to find a way for Eclipse to do it.

I really should have jumped to that last one first.  Googling for my second thought gave me nothing useful.  However, simply adding “eclipse” to my search term brought up the Metrics plugin as the first result!  The Metrics plugin counts all different types of things.  Lucky for me, “number of methods” just happens to be one of them.

To get the counts working for you, follow these easy steps:

  1. Add http://metrics.sourceforge.net/update to eclipse as a plugin update site
  2. Turn metrics on for your project:
    1. Right click on the root of your project in Package Explorer view
    2. Choose Properties–>Metrics–>Enable Metrics
  3. Do an Eclipse clean rebuild
  4. Click on the root of your project in the Package Explorer
  5. Open the “Metrics” view

These are the relevant statistics from the OpenMRS project:

The second api/web are from the test package.  We have a lot of work to do to catch our total number of unit test methods up with our number of api methods.

I’ve also uploaded the entire OpenMRS metrics output.

This is in the openmrs category tagged as , ,

Add a comment »

I attended a session today at the MySQLConf2008 by Mark Matthews on adding extensions to the mysql jdbc connector. There are some exciting implications as an alternative to the BIRT ODA Plugin project. The idea of that project is to create a series of REST calls to only require the end user of the BIRT reporting application to have a high level knowledge of OpenMRS objects (instead of low level knowledge of the OpenMRS data model).

Sometime last year Burke laid out his dream BIRT (or other reporting frameworks) connection. It entailed writing a custom jdbc connector that didn’t act on the database, but instead acted on our API. The “available tables” as the user would see it in BIRT would actually be a subset of our higher level Java objects.

In the session Mark discussed the new intercept-ability of the MySQL Connector/J (new in version 5.1ga of the connector). The relevant/interesting addition to the connector is the “statement interceptor”. We could use this to intercept the select calls from BIRT that look like “SELECT AGE, GENDER, WEIGHT, HEIGHT, LATEST CD4 FROM PATIENT WHERE DATE > 1/1/2008”. These calls could be turned into some LogicService calls on AGE, WEIGHT, LATEST CD4, etc to get the ResultSet instead of passing that (unusable) query to mysql. The LogicService’s resultSet could then be returned to BIRT for display as a data set. There isn’t any documentation on MySQL Forge on how this would work yet. Mark’s slides should show up as an option on the mysqlconf’s wiki soon though.

Side note: The jdbc driver’s version number does not match with the mysql version numbers. Version 5.1 of the driver can be used with the current 5.0 of MySQL.

This is in the openmrs category tagged as , ,

Add a comment »

« Previous Entries