Getting Started - Lab Module Back-end Development

Lab-module specific page - Useful for back-end developers working on the Lab Module. General back-end developers can look at Getting Started Guide: Back-end Development

Note that the Laboratory module back end is going to remain an OpenMRS project using the OpenMRS repository until OpenMRS changes to git in the near future.

I.  Understanding the design

From Dropbox (Dropbox/JSS EMR/Documentation/Lab Rats Only):

LabDataModel.ppt -- overview of the lab data model
Concepts.xls -- the concept library and other OpenMRS tables for the test data
Catalog.tab -- a tab-delimited file showing the lab catalog for the test data

II.  Getting started with OpenMRS

Install MySQL (Following steps are not needed if using latest code which automatically adds lab related data to db)

  1. Create database 
    1. create database jsslab;
    2. use jsslab;
  2. After creating jsslab database, create username: openmrs with password: openmrs
    1. CREATE USER 'openmrs'@'localhost' identified by 'openmrs';
    2. GRANT ALL ON jsslab.* to 'openmrs'@'localhost';
  3. Download and unzip the latest jsslab mysqldump file: jsslab20120221.zip (in Dropbox /JSS EMR/Documentation/Lab Rats Only)
  4. Use the MySQL command interface to load it
            source <path>\jsslab20120221.sql
  5. Install MySQL workbench, get the model from dropbox/Documentation/LabRatsOnly/jsslab2.mwb (Not necessary step) 

Install OpenMRS

  1. Follow step-by-step installation instructions at https://wiki.openmrs.org/display/docs/Step+by+Step+Installation+for+Developers
  2. When you are setting up your OpenMRS environment, if you need help, don't hesitate to get in touch. Here are some tips:
    1. You will need to install the JDK (currently Glassfish3), Eclipse (currently Indigo), Eclipse add-ins from the marketplace (subclipse, maven, maven subclipse integration, run jetty run. NOTE: The maven sublipse integration is no longer supported and may not work with the newest version of subclipse. If so, try the Subversive plug-ins instead), maven. For now you don't need to install Tomcat.
    2. With Eclipse, you need to edit eclipse.ini to add the following 2 lines at the top:
      1. -vm
      2. c:/Program Files/glassfish3/jdk/jre/bin/javaw.exe
    3. If you have earlier versions of the JRE on the machine, you need to go to Preferences>>Java and change the JRE to the glassfish location.
    4. When you are first importing, use Import from SVN, but just go far enough to identify the OpenMRS SVN repository (http://svn.openmrs.org), then continue via Import Maven Project using Source Control. You will have to install a number of adapters when you download projects for the first time, just go with the flow.
  3. Make sure your standalone Maven and Eclipse maven are using the same repository. Install maven first and take the default (~/.m2/repository on xnix, c:\documents and settings\<username>\.m2\repository on Windows), then check the maven preferences to see what Eclipse is using
  4. Include the following 3 projects in your Eclipse workspace: JSSLab module trunk http://svn.openmrs.org/openmrs-modules/jsslab/, OpenMRS 1.8.x branch, webservices.rest module 0.8 branch.
  5. You will have to install the webservices.rest files into your local maven repository. See https://wiki.openmrs.org/display/docs/Requiring+another+module+in+your+module in the section Installing omod to a local repo. You do not need to do the other steps, they are already included in what you check out.
  6. You will need to run OpenMRS from your workspace via Jetty. This is because of a not-yet-released fix needed to map the LabTestResults table. If you have installed Tomcat, you will need to stop the service to be able to run Jetty.

When you first run OpenMRS, it will take you through the initial configuration and setup process.  Make sure you specify that you want to use the existing DB jsslab, that you have a user openmrs for OpenMRS to use, and that you don't want to load any test data.

III.  Testing

  1. Make sure that you have installed the run-jetty-run plugin for Eclipse
  2. Make sure that you have the restws and openmrs 1.8 projects in your workspace and that you have done a maven clean install on all three projects with Debug output and Update snapshots selected
  3. Depending on your OS, you may find it useful to download and install the open source CURL utility in dropbox/Documentation/LabRatsOnly
  4. In Eclipse, right click on openmrs-webapp/target/jetty, choose debug as, run jetty
  5. From the menu, choose Window > Open Perspective > Debug. Wait until the console stops producing output and there is a process tree in the Debug pane.
  6. Open a new browser window, I like to use Firefox for testing.
  7. Go to http://localhost:8080/openmrs-webapp. The first time you do this, you will go through the installer. Point it to the jsslab DB and the openmrs user, you don't want it to create a database or install test data. Latest .omod file of jsslab creates necessary tables & data by itself
  8. You should see the openmrs login screen, use admin/test. Go to administration, module administration. Stop (red stop sign icon) and unload (trash can icon) all non-required modules (I think that will leave you only with logic). Get and start (green arrow icon) the webservices.rest omod from <workspace>/<webservices.rest project>/tags/0.8/omod/target (your path will be slightly different if you got only the 0.8 version and not the entire project). Get and start the jsslab omod from <workspace>/<jsslab project>/trunk/omod/target. As you debug, you will need to recompile jsslab (it will try to make changes dynamically, but I don't trust that). You will need to stop the jsslab module, unload it, compile, get the new version and start it. Sometime soon there will be some changes to the rest.webservices module. At that point you will have to stop the and unload the jsslab module, stop and unload the rest.webservices module, either get the new rest.webservices module or compile the changes, load and start the rest.webservices module, and load and start the jsslab module.
  9. Testing: Go to administration, rest.webservices module, test. In the URI line, change "/openmrs/ws/rest/v1/patient/495b10c4-56bd-11df-a35e-0027136865c4" to /openmrs-webapp/ws/rest/v1/module/jsslab/<resource><request info>. Choose a message type. If you are doing an update or create, you will need a body. If you are doing a get, you will may need a representation (if you are using ?v in the request, you shouldn't need to).
  10. You can also test the gets just by navigating to the URI. If you have logged out of openmrs, you should receive a login prompt.

IV.  Tasks

The stack we are building is something like this: (1) liquibase to install the new tables (not yet started, we are working directly with MySQL for now); (2) POJOs which represent the DB objects (e.g. LabInstrument.java); (3) the DAO interface and Hibernate implementation which perform low-level manipulation of the POJOs (e.g. LabInstrumentDAO.java and HibernateLabInstrumentDAO.java); (4) the service interface and implementation which provide useful functionality to the webapp (e.g. LabManagementService.java and LabManagementServiceImpl.java); (5) the REST resource which serves POJO content to the REST API (LabInstrumentResource.java); and (6) the controller which implements the REST endpoint (LabInstrumentController.java).

Just to make sure that everyone knows what the priority tasks are:

  1. The services support the following tables:
    1. Lab Management Service -- lab_instrument, lab_supply_item
    2. Lab Catalog Service -- lab_test_panel, lab_test, lab_precondition, lab_specimen_template
    3. Lab Testing Service -- lab_specimen, lab_test_specimen, lab_result, lab_report, lab_test_run, lab_test_ranges
    4. Lab Order Service -- lab_order, lab_order_specimen
  2. Each table/service needs the following components:
    1. <table>.hbm.xml (Hibernate map file) -- all done -- omod/src/main/resources
    2. <table>.java (data object) -- some done but some done ones need to have comparable moved -- api/jsslab/db
    3. <table>DAO.java (data access interface) -- some done -- api/jsslab/db
    4. Hibernate<table>DAO (data access object) -- some done but some done ones need to have sorting removed -- api/jsslab/db/hibernate
    5. <service>.java service interface -- some done -- api/jsslab
    6. <service>Impl.java service object -- some done but some done ones need to have sorting added -- api/jsslab/impl
    7. <table>Resource.java REST resource -- some done but all need testing -- omod/jsslab.rest.resource
    8. <table>Controller.java REST controller -- some done but all need testing -- omod/jsslab.rest.controller

At the moment, our best examples are probably test_panel and test from the catalog service; the only resources we have running are labInstrument, labSupplyItem and labPrecondition. For each resource, we need REST controller and resource objects; a POJO for holding table data; a DAO and HibernateDAO for each resource; and appropriate methods in a Service and ServiceImpl. The idea I think is to start from the resource and see what methods are needed and put those methods into the service, then combine or divide the methods into methods of the DAO. I have sent all of you a list of items to code to, if you can't find it let me know. However, after consultation with OpenMRS folks, there is going to be a change. We will not implement Comparable, we will have a custom compare class for each object callable by Collections.sort(<list>,<custom compare class>) . I would like to try to keep these classes in the associated DAO object, even if they are only used in the Service. All existing code has to be refactored to do this.

Also we have reached a certain level of clarity on searches. Searches are invoked by the q parameter on a REST call to a resource. These searches should cover ID- or name-like fields excluding UUID and <object>_id. The DAO method to do these searches should accept paramenters for the search value, a boolean for whether to include voided/retired, and a start and end record count number (the second parameter may be a count, I forget, but it's clear in the code).

     Finally, let me say that it is important not to overthink. Basically, if we can build our stack for each of the objects, then it will be up to the front end people to start working with them and discovering what additional back-end services they require while we clean up our act. I am doing nothing but copying standard methods that exist in the REST module, such as Get<object>ByUuid, Save<object>, GetAll<object>s, GetCountOf<object>s, Get<object>ByName, Get<object>ById, Retire<object> or Void<object>, and Purge<object>. Those that don't apply to the object I'm working on, I don't implement. I modify the interface to match the implementation instead of working in the other direction because of the semi-agile style in which we are working.

 

IV. Debugging

Following is the list of possible errors you may face while setting up developing environment:

a.  [ERROR] Failed to execute goal on project jsslab-api: Could not resolve dependencies for project org.openmrs.module:jsslab-api:jar:1.0-SNAPSHOT

Possible solution:

use following command (for webservices.rest-omod and change -DartifactId if you are doing same for other artifiacts): 

mvn install:install-file -DgroupId=org.openmrs.module -DartifactId=webservices.rest-omod -Dversion=0.8 -Dpackaging=jar -Dfile=/link/to/file

(You can find the file in target folder of omod)

Another option is to change webservices to 1.0 and logic to 0.5.1 in the pom.xml

b. Test is failing

We know that jsslab is not passing test as of now and Roger is working on that. 

Possible solution:

To build successfully, either check "Skip Test" or use following flag

-Dmaven.test.skip=true

c. Restart Tomcat

You may need to re-start TomCat. The command to do so is:

Ubuntu: sudo /etc/init.d/tomcat6 restart