There are few things that you need to be familiar with while working on OpenMRS Code. You will learn them as you keep on working. But’s it’s nice to have an idea of what you might be encountering.
If you observe the Structure clearly, you will see a lot of terms that might be new to you. I’ll explain each part in some detail.
Let’s come in Top Down approach.
As mentioned in the image, presentation layer has two components, HTML/JSP pages and Jquery
HTML and JSP:
These are the pages that you can view when you run and try to use OpenMRS, anything you view must be in these pages. Mostly all of them are in jsp pages, you will rarely find an html page. Some new modules might have html pages.
OpenMRS strongly subscribes to the Model-View-Controller pattern. The Spring Framework is an open source application framework and inversion of control container for the Java platform, it includes several modules that provide a range of services:
- Inversion of control container
- Aspect-oriented programming
- Data access
- Transaction management
- Remote access framework
- Convention over configuration
- Authentication and authorization
- Remote management
I’m not going to go into details of what they exactly mean, if you would like to learn more about spring this link is the best place for that. As a personal preference there is also a book named “Spring in Action”, which describes it’s concepts very intuitively.
As some basic questions might arise these are the answers:
- Why is a framework useful? According to my understanding when you write code based on a framework, it gives a structure to the code we write.
- Why use Spring? It is a popular framework, so it has many great rules for the structure and also because many developers will be well versed in it.
- How can I notice this in OpenMRS? Let us assume we are trying to create a new concept in OpenMRS, when you look at the url it will be something like this http://demo.openmrs.org/openmrs/dictionary/concept.form. So, when you search in eclipse(Ctrl +shift + r), just type in conceptform and look at the results they will be something like this
I’ll explain each part :
- conceptForm.jsp: This is where the display components of the form are written.
- ConceptFormController.java: This is where the java code that handles the requests/responses from the conceptForm.jsp.
- ConceptFormValidator.java: This is where the fields of conceptForm.jsp are validated before they can be saved in the database by the controller, if the test fails then the page is redirected to the conceptForm.jsp with the list of errors dislpayed in red beside the respective field.
- ConceptFormControllerTest.java: This file’s responsibility is to test if the functions of the controller are doing their work properly.
- ConceptFormControllerTest.xml: The test on controller’s function happens when the war is being built. So there will be no database connection to test with some real data so a temporary data is provided to test the functions in this xml.
Do you think I wrote any of these files myself, that I am able to explain them? No, I didn’t even open these files while writing this tutorial. I knew all this information because of OpenMRS developers who write code in such formatted way.Each form will have a similar structure.
Service Layer/OpenMRS API:
In this layer methods are written to cater the needs of the controllers, hence the name “Service Layer”.
It has two parts,
- Service.java files: These are interfaces containing all the methods it caters.
- ServiceImpl.java files: These have the implementation of the functions mentioned in the service.java files.
uses of having such layering? well, they are the uses of basic interfacing.
Service layer creates a dao object and it has all the functions needed to interact with the database.
DAO Layer is responsible for interacting with the database, all the SQL type scripts are included in these layers. Similarly it also contains two parts:
- DAO.java files: These are interfaces containing all the methods it caters.
- HibernateDAO.java files: These have the implementation of the functions(i.e. the sql type scripts) mentioned in the DAO.java files.
One might wonder why so many layers! I had the same doubt. I later got to know that, having these many layers gives the flexibility to changing code in one layer does not affect any other layer’s code. And moreover, a person working in one layer need not know how something is happening in any other layer, knowing what is being done is enough. Something like the service layer can use a method like daoObject.getAllPatients() and be sure that he will get the patient objects without exactly knowing how.
Hibernate is an excellent Object Relational Mapper. Using just xml files, we are able to describe the relationship between all of our tables and our domain (POJO) objects.
POJO: Plain Old Java Objects are the objects we understand like Patient.java, Concept.java, etc.
For Example: Looking at the concept domain in the datamodel, we see that it consists of tables named concept, concept_answer, concept_set, concept_name. It would be very difficult to keep up with where to store each part of the concept object and the relations between them. Using Hibernate, we only need to concern ourselves with the Concept object, not the tables behind the object. The concept.hbm.xml mapping file does the hard work of knowing that the Concept object contains a collection of ConceptSet objects, a collection of ConceptName objects, etc.
Hibernate wraps the Concept object in its own object and keeps track of what has been added, removed, etc
Hibernate will not load all associated objects until they are needed – this is called lazy loading:
For Example: Say you have a parent and that parent has a collection of children. Hibernate now can “lazy-load” the children, which means that it does not actually load all the children when loading the parent. Instead, it loads them when requested to do so. You can either request this explicitly or, and this is far more common, hibernate will load them automatically when you try to access a child.
Lazy-loading can help improve the performance significantly since often you won’t need the children and so they will not be loaded.
Also beware of the n+1-problem. Hibernate will not actually load all children when you access the collection. Instead, it will load each child individually. When iterating over the collection, this causes a query for every child. In order to avoid this, you can trick hibernate into loading all children simultaneously, e.g. by calling parent.getChildren().size().
Mostly you will only be viewing tables you are working on, but still if you would like to view the data model.
If you still would like to delve more into documentation of OpenMRS data model, there is no better place than OpenMRS wiki itself. Here is the link for OpenMRS Data Model