Can a GAE Spring DispatcherServlet save different Data Objects to the same PersistenceManagerFactory?

106 views Asked by At

I am working on a Spring DispatcherServlet deployed to Google App-Engine that uses a JDO PersistenceManagerFactory for storage.

I am developing in Eclipse using a combination of the eclipse Maven Plugin and the Maven appengine Plugin. (I do not have the Google App Engine Plugin for Eclipse installed because I was unsuccessful getting that setup to work.)

I’ve used this project as a basis for my own:
https://github.com/juleswhite/mobilecloud-14/tree/master/examples/12-VideoSvcAppEngineJDO Copyright 2014, Jules White

I’ll admit that although I am an experienced C++ developer I have little to no previous experience with any of the technologies/tools that I’m attempting to use here. I’ve exhausted myself trying to figure this out and I can’t say for sure where in the process the mistakes are. I have a partially working project and will be happy to post any additional code that you feel is helpful.

Topic 1:

Let me start with a fundamental presumption of my design. I am of the understanding that one PersistenceManagerFactory should be able to handle many different JDO Classes. In my example I have a Caregiver Object and a Patient Object each marked up with DataNucleus Annotation.

Caregiver.java

@PersistenceCapable
public class Caregiver {

@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Long id;

    @Persistent
    private String firstName;

    @Persistent
    private String lastName;

    @Persistent
    private String phone;

    @Persistent
    private String email;

    @Persistent
    public ArrayList<Long> patients;

    public Caregiver() {
        patients = new ArrayList<Long>();
    }
    ...

Patient.java

@PersistenceCapable
public class Patient {

    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Long sysId;

    @Persistent
    private Long caregiverId;

    @Persistent
    private String firstName;

    @Persistent
    private String lastName;

    @Persistent
    private String recordNum;

    @Persistent
    private String dob;

    @Persistent
    private ArrayList<Long> checkIns;

    @Persistent
    private ArrayList<Long> meds;

    public Patient() {
        checkIns = new ArrayList<Long>();
        meds = new ArrayList<Long>();
    }
    ...

I access the PersistenceManagerFactory through and adaptation of the interface provided in Dr. Whites Code. My adaptation is supposed to extent the PMF to multiple data types.

JDOCrudRepository.java

....
public Object save(Object entity) {
    return PMF.get().getPersistenceManager().makePersistent(entity);
}
....
public Iterable<Object> findAll(Class<?> type) {
    Query query = PMF.get().getPersistenceManager().newQuery(type);
    Object rslt = query.execute();
    return (Collection<Object>) rslt;
}
....

PMF.java

/*
 * @author jules
 * 
 */
public final class PMF {
     private final PersistenceManagerFactory pmfInstance = JDOHelper
                .getPersistenceManagerFactory("transactions-optional");

     public PMF() {
     }

     public PersistenceManagerFactory get() {
          return pmfInstance;
     }
}

I am able to build and test the project using the command “mvn appengine:dev_server” Using my spring dispatcherServlet I have wired functions to add and retrieve Caregiver Objects from the PersistenceManagerFactory.

CaregiverService.java

....
// GET ////////////////////////////////////////////////////////////////////
// TODO: Dangerous in production
@Override
@RequestMapping(value = CaregiverSvcApi.CAREGIVER_SVC_PATH, method = RequestMethod.GET)
public @ResponseBody
Collection<Caregiver> getCaregiverList() {
    ArrayList<Object> objList = Lists.newArrayList(repo
            .findAll(Caregiver.class));

    ArrayList<Caregiver> cg = new ArrayList<Caregiver>();
    for (Object object : objList) {
        cg.add(object != null ? (Caregiver) object : null);
    }

    return cg;
}
...
// POST ///////////////////////////////////////////////////////////////////
@Override
@RequestMapping(value = CaregiverSvcApi.CAREGIVER_SVC_PATH, method = RequestMethod.POST)
public @ResponseBody
Caregiver postCaregiver(@RequestBody Caregiver cg) {
    cg.setIdNull();
    Caregiver newCg = (Caregiver) repo.save(cg);
    return newCg;
}
...

These work fine as demonstrated by the results fetched from my dev server

GET http://127.0.0.1:8080/caregiver
[{"id":5676073085829120,"firstName":"Cg","lastName":"One","phone":"1234567","email":"[email protected]","patients":[]},
{"id":5682617542246400,"firstName":"z","lastName":"z","phone":"123","email":"[email protected]","patients":[]},
{"id":5715999101812736,"firstName":"c","lastName":"s","phone":"123","email":"[email protected]","patients":[]}]

To the meat of the problem…

If I apply the same methodology to my Patient Object

CaregiverSvc.java

...
// GET ////////////////////////////////////////////////////////////////////
@Override
@RequestMapping(value = CaregiverSvcApi.PATIENT_SVC_PATH, method = RequestMethod.GET)
public @ResponseBody
Collection<Patient> getPatientList() {
    ArrayList<Object> objList = Lists.newArrayList(repo
            .findAll(Patient.class));

    ArrayList<Patient> p = new ArrayList<Patient>();
    for (Object object : objList) {
        p.add(object != null ? (Patient) object : null);
    }

    return p;
}
...
// POST ///////////////////////////////////////////////////////////////////
@Override
@RequestMapping(value = CaregiverSvcApi.PATIENT_SVC_PATH, method = RequestMethod.POST)
public @ResponseBody
Patient postPatient(@Body Patient p) {
    p.setIdNull();
    Patient newP = (Patient) repo.save(p);
    return newP;
}
...

Now when I post or get Patient Objects my results are always null.

GET http://127.0.0.1:8080/patient
[{"id":5113123132407808,"caregiverId":null,"firstName":null,"lastName":null,"recordNum":null,"dob":null,"checkIns":[],"meds":[]},
{"id":5697423099822080,"caregiverId":null,"firstName":null,"lastName":null,"recordNum":null,"dob":null,"checkIns":[],"meds":[]}]

All of my patient objects are stored as null values as if my PersistenceManagerFactory does not know how to interpret the Patient Object.

Topic 2:

If I indeed am using a PersistenceManagerFactory appropriately. Is there anything more I need to do to get the PersistenceManagerFactory to properly handle the Patient Object?
Your time is greatly appreciated.

1

There are 1 answers

1
Chinmaya Samal On BEST ANSWER

@Body Annotation is used in Retrofit.. Your Service should use @RequestBody Annotation to get the Data Object.. That's why server never stored anything and thus returns Null...