Unable to retrieve custom member variable of Person class through REST

I’m using the following development environment: OpenMRS Platform 1.11.4 OpenMRS Reference Application 2.3.1 and bundled modules

I’ve added a custom member organization of type Organization in Person class and I’m trying to access organization for patient being searched using Find Patient app of Reference Application.

I’ve updated patientSearchWidget.js code specifying representation of REST call as follows: var customRep = 'custom:(uuid,' + 'patientIdentifier:(uuid,identifier),' + 'person:(gender,age,birthdate,birthdateEstimated,personName,organization))';

I’m getting all the attributes of person except for organization. JSON response of REST call contains a null against organization key: http://pastebin.com/BKKtW0QJ

What could be the issues behind the same? I went through the application logs but didn’t find anything.

Note:

  • I have defined getter and setter methods for organization.
  • Organization class extends BaseOpenmrsData and implements java.io.Serializable

I’m a little confused by your question, what do you mean by you added ‘a custom member organization of type Organization in Person class’ this doesn’t make sense. You extend a core domain object from a module via attribute types or may be by adding a new class in your module that extends the one in core and map it as a joined subclass in hibernate.

Sorry for being vague. I meant to say that I’ve added a member variable of data-type Organization in existing Person class as follows:

public class Person extends BaseOpenmrsData implements java.io.Serializable {

...

protected Integer personId;

private Set<PersonAddress> addresses = null;

private Set<PersonName> names = null;

private Set<PersonAttribute> attributes = null;

private String gender;

private Date birthdate;

...

private Organization organization;

...
}
  • I have defined getter and setter methods for organization.
  • Organization class extends BaseOpenmrsData and implements java.io.Serializable

If you have modified the person class you need to override the person resource, and specify this additional available property.

-Darius (by phone)

@darius, I already tried doing that by adding description.addProperty("organization"); and implementing @PropertyGetter and @PropertySetter methods for property organization under PersonResource1_11.

The problem here is when I query a person using ~/mrs/ws/rest/v1/person?q=xyz&v=full, I get organization property with details.

But, when I query a patient using /mrs/ws/rest/v1/patient?q=xyz&v=full, I get a null value for organization property.

You probably also need to override the patient resource and ensure it is including the person object using your custom resource.

(This is a guess without looking at the code.)

-Darius (by phone)

@themoonraker13, you probably already know this, but it’s worth noting that customizing core classes is the reason behind having “attribute” tables in the model. For example, as Wyclif suggested, you should be able to add Organization as a person attribute, See it and search by it via REST.

@burke, I totally understand that. But in my case Organization is a primary entity of the system as I’m working on multi-tenant architecture design and hence will need it as field on the person table instead of an attribute (PersonAttribute).

Thanks @darius, I’m on the route you suggested. I’m stuck on how to attach custom(new) PatientResource1_X resource with custom(new) PersonResource1_X.

Let me give it a try and circle back later.

@ulrich I’m still a little confused, how are you adding a field to the person when Person.java is in core? Bytecode manipulation? Did you fork core? :slight_smile:

@wyclif. Let me explain what I’ve done.

  1. Added field organization of type Organization to Person class
  2. Built the platform code and obtained openmrs-api.jar
  3. Placed openmrs-api.jar in webservices-rest module as external jar and changed pom.xml path of openmrs-api to system-path of the jar I just placed
  4. Consumed platform api code in PersonResource1_11.java to add property organization

Now when I fetch person using REST with v=full, I get database value in organization key of JSON response. But, when I fetch patient using REST with v=full, I get a null value in organization key of JSON response.

Hope I’m clear now. :grinning:

I am not following. How is using a person attribute prevent you from using the Organization even though it is a primary entity? My understanding is PersonAttributeTypes can be of other core/primary entities like Location. Obviously you could create an attribute of type Organization. Am I missing something?

Can you debug PatientResource to see what’s happening? I’d guess is using the wrong Person class (the one from core, not the one you modified).

According to my data model this is the entity relationship tree:

  1. Organization > Person > PersonAttribute
  2. Organization > Branch > Location and so on…

In this manner Organization is one of the primary entities and hence cannot be a person attribute.

@lluismf , I checked the response JSON data and it’s picking up PersonResource1_11 (where I’ve made changes) while fetching patient and person.

And as I mentioned in one of the comments:

  • When I fetch person using REST with v=full, I get database value in organization key of JSON response.
  • But, when I fetch patient using REST with v=full, I get a null value in organization key of JSON response.

@themoonraker13 first and foremost, I’d never advise someone to do the things you did because it sounds like and actually is the kind that would get you into all sorts of problems just like what you’re running into. Taking source code of a repository that is actively developed and making non compatible changes to it that you don’t intend to merge/harmonize with the code in the main repo can be extremely painful and can even get near to impossible to maintain. It’s similar to forking a repo hoping to steer it in a different direction but for some reason you still need to fetch and integrate changes from where you forked it. The other fundamental thing that plays to your disadvantage is that you also need to use the rest module which is dependent on the openmrs core code you’re ‘forking away’ from and altering in a non compatible way, do you smell an issue am trying to describe here? On the other hand I understand that you could be working on a proof of concept and will probably keep it at that.

In theory as Burke mentioned you should be using person attributes rather than what you’re doing because it’ll make things a lot easier.

The issue could be because resources in the rest module are written in an openmrs version sensitive way, you somehow have to make sure that the resources you’re experimenting with support the version set in your local openmrs core repo, this is something that continually changes based on changes in core, it would mean you have to constantly integrate changes in core as well as the rest module into your forks/repos for things to work seamlessly which is no piece of cake based on what I mentioned at the start of this post.

And why do you have to build a jar for openmrs core and add it to web services module that way? Personally If I was doing a proof of concept for core and rest webservices module assuming it’s what you’re doing, I would take core and the webservices module repos at two compatible versions/revisions and change them together without pulling in latest changes to any, this means I’d just make sure the openmrs version in the module’s dependency is set to whatever it is in the openmrs-core’s pom.xml file in my repo and just keep letting maven dependency mechanism work its magic as opposed to manually creating a jar and adding it to the module.

Wyclif

Thanks for the insight @wyclif. I was just trying to know the possibilities to introduce custom members in base classes.

I’m trying to develop a multi-tenant version of OpenMRS with specific version of platform and modules(personal interest). I’ve no intention to update the code version until I achieve my goal.

Personally I liked the suggestion you briefed towards the end of your comment. I’ll surely try that to relieve myself from all the mess of handling jars.

I’m not 100% sure if multi-tenancy and altering application code go together.

I assume to solve your problem you need to make sure the person resource you’ve updated has the version for your openmrs-core included as a supported version, supported versions are specified via the supportedOpenmrsVersions attribute of the @Resource annotation at the class level of a resource.