Details

    • Type: Improvement Improvement
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: JDO 2 maintenance release 1 (2.1)
    • Fix Version/s: JDO 3.2
    • Component/s: api, api2-legacy
    • Labels:
      None

      Description

      I'm putting forth a proposal to add a method to JDOHelper that allows users to determine whether or not a given object's field is loaded. There are two options to handle implementations that won't/can't support loaded field checking, especially when detached (essentially binary compatible v. non-binary compatible implementations). Option A adopts an approach that uses Boolean objects instead of primitives, leaving null as a return value for implementations that won't/can't support it. Option B takes an exception-based approach and uses boolean primitives. I'm not sure which I prefer; let's discuss.

      <proposal option="A">

      JDOHelper

      Checking whether fields are loaded

      In some use cases, an application may need to know whether or not a given field is loaded, for example when marshaling data from detached objects to data transfer objects (DTOs).

      Transient fields

      Transient fields are always considered loaded.

      Implementation support

      Some implementations may not be able to support the ability to check the loaded status of a field, especially when the object is detached. If the implementation does not support checking whether a field is loaded, then it must return null from the isLoaded methods.

      Boolean isLoaded(String fieldName, Object pc);

      If the field in the most-derived class of the given object's class identified by the given name is loaded in the given object, Boolean.TRUE is returned. If the field is not loaded, Boolean.FALSE is returned. If the given field name is not declared by the given object's class or its direct or indirect superclasses, then JDOUserException is thrown. If the implementation does not support checking the loaded state of a field, null is returned. This method is equivalent to calling isLoaded(fieldName, pc, pc.getClass());

      Boolean isLoaded(String fieldName, Object pc, Class c);

      This method exists to support the case where a class hides fields defined in a superclass and an application wants to determine the loaded state of the field in the superclass. In most cases, the given Class, c, will be identical to the class of the given object, pc (that is, c == pc.getClass() will return true). If the class of the given object, pc, is a subclass of the given Class, c, then the loaded state of the field defined on c is given. If the given Class c is not identical to the class of or a superclass of the given object, pc, then JDOUserException is thrown. If the given Class represents an interface, then JDOUserException is thrown.

      If the field of the given class is loaded, Boolean.TRUE is returned. If the field is not loaded, Boolean.FALSE is returned. If the implementation does not supporting checking the loaded state of a field, null is returned.

      </proposal>

      <proposal option="B">

      JDOHelper

      Checking whether fields are loaded

      In some use cases, an application may need to know whether or not a given field is loaded, for example, when marshaling data from detached objects to data transfer objects (DTOs).

      Transient fields

      Transient fields are always considered loaded.

      Implementation support

      Some implementations may not be able to support the ability to check the loaded status of a field, especially when the object is detached. If the implementation does not support checking whether a field is loaded, then it must throw JDOUnsupportedOperationException from the isLoaded methods.

      boolean isLoaded(String fieldName, Object pc);

      If the field in the most-derived class of the given object's class identified by the given name is loaded in the given object, true is returned, otherwise false is returned. If the given field name is not defined by the given object's class or its direct or indirect superclasses, then a JDOUserException is thrown. If the implementation does not support checking the loaded state of a field, JDOUnsupportedOptionException is thrown. This method is equivalent to calling isLoaded(fieldName, pc, pc.getClass());

      boolean isLoaded(String fieldName, Object pc, Class c);

      This method exists to support the case where a class hides fields defined in a superclass and an application wants to determine the loaded state of the field in the superclass. In most cases, the given Class, c, will be identical to the class of the given object, pc. If the class of the given object, pc, is a subclass of the given Class, c, then the loaded state of the field defined on c is given. If the given Class c is not identical to the class and is not a superclass of the given object, pc, then a JDOUserException is thrown. If the given Class represents an interface, then JDOUserException is thrown.

      If the field of the given class is loaded, true is returned, otherwise false is returned. If the implementation does not support checking the loaded state of a field, JDOUnsupportedOptionException is thrown.

      </proposal>

        Activity

        Hide
        Michael Bouschen added a comment -

        I changed my mind. Suppose you have a detached Object and use a generic method to create a different representation of that Object (e.g. JSON). The application code makes sure that all the neccessary fields are loaded. That generimethod uses reflection to get all the field values, but it needs a way to figure out which fields are loaded and should be included in the representation and which fields should not be touched. So I think it makes sense to have a method JDOHelper.isLoaded.

        Show
        Michael Bouschen added a comment - I changed my mind. Suppose you have a detached Object and use a generic method to create a different representation of that Object (e.g. JSON). The application code makes sure that all the neccessary fields are loaded. That generimethod uses reflection to get all the field values, but it needs a way to figure out which fields are loaded and should be included in the representation and which fields should not be touched. So I think it makes sense to have a method JDOHelper.isLoaded.
        Hide
        Craig L Russell added a comment -

        I agree. I don’t yet see a compelling need for the application to know the state of fields.

        The most important case I can think of is to guarantee that fields needed for serialization are loaded. This case needs to look at the entire object graph. But we already have an api for this: load with a fetch plan that specifies all of the needed fields. This lets the implementation do the hard work.

        Show
        Craig L Russell added a comment - I agree. I don’t yet see a compelling need for the application to know the state of fields. The most important case I can think of is to guarantee that fields needed for serialization are loaded. This case needs to look at the entire object graph. But we already have an api for this: load with a fetch plan that specifies all of the needed fields. This lets the implementation do the hard work.
        Hide
        Michael Bouschen added a comment -

        I think without a valid use case why an application needs to call isLoaded I do not see a need to support it. So if we do not find such a use case I propose to resolved the JIRA as won't fix.

        What do you think?

        Show
        Michael Bouschen added a comment - I think without a valid use case why an application needs to call isLoaded I do not see a need to support it. So if we do not find such a use case I propose to resolved the JIRA as won't fix. What do you think?
        Hide
        Tilmann Zäschke added a comment - - edited

        > Could you do the next level of detail on the FieldState of fields considering all of the object states?
        By "you', do you mean me?

        As I understand, ObjectState reflects the valid combinations of two orthogonal states:

        {NEW, CLEAN, DIRTY, HOLLOW} //The state of the data in the object, i.e. compared to the data in the database.

        – {TRANSIENT, PERSISTENT, DETACHED} //The state of the object
        The NEW is a bit weird, it may actually fall in it's own category, or both, I guess.

        I also think that, in a way, the ObjectState could be seen as a summary of the individual field states, so FieldState should either be a well defined subset or exactly the same as ObjectState.

        I would say the question is, should FieldState reflect ALL ObjectStates? Or just the ones related to data?
        So if the above is true (corrections are welcome) FieldState should provide one of the following:

        * all ObjectStates
        * the object's data states {NEW, CLEAN, DIRTY, HOLLOW}

        .

        Anyway, I think we first need to understand what the purpose of isLoaded() is.

        Show
        Tilmann Zäschke added a comment - - edited > Could you do the next level of detail on the FieldState of fields considering all of the object states? By "you', do you mean me? As I understand, ObjectState reflects the valid combinations of two orthogonal states: – {NEW, CLEAN, DIRTY, HOLLOW} //The state of the data in the object, i.e. compared to the data in the database. – {TRANSIENT, PERSISTENT, DETACHED} //The state of the object The NEW is a bit weird, it may actually fall in it's own category, or both, I guess. I also think that, in a way, the ObjectState could be seen as a summary of the individual field states, so FieldState should either be a well defined subset or exactly the same as ObjectState. I would say the question is, should FieldState reflect ALL ObjectStates? Or just the ones related to data? So if the above is true (corrections are welcome) FieldState should provide one of the following: * all ObjectStates * the object's data states {NEW, CLEAN, DIRTY, HOLLOW} . Anyway, I think we first need to understand what the purpose of isLoaded() is.
        Hide
        Craig L Russell added a comment -

        It would help to understand why an application would call isLoaded.

        Show
        Craig L Russell added a comment - It would help to understand why an application would call isLoaded.
        Hide
        Craig L Russell added a comment - - edited

        I like the approach of implementing FieldState and then we could implement a JDOHelper method isLoaded which would get the FieldState and then switch case the "loaded" field states: CLEAN and DIRTY.

        If an implementation doesn't track individual field states, it could return the state of the object.

        Could you do the next level of detail on the FieldState of fields considering all of the object states?

        Maybe

        {HOLLOW, CLEAN, DIRTY, DELETED, TRANSIENT}
        Show
        Craig L Russell added a comment - - edited I like the approach of implementing FieldState and then we could implement a JDOHelper method isLoaded which would get the FieldState and then switch case the "loaded" field states: CLEAN and DIRTY. If an implementation doesn't track individual field states, it could return the state of the object. Could you do the next level of detail on the FieldState of fields considering all of the object states? Maybe {HOLLOW, CLEAN, DIRTY, DELETED, TRANSIENT}
        Hide
        Tilmann Zäschke added a comment - - edited

        Clarification: My proposal mainly aims at three things:

        • Making the API easily extensible for additional field states in future. Using an enum would simplify adding new states and combination of states
        • Consistency based on similarity with the ObjectState enum
        • Avoiding 'null' as return value

        About the actual states:

        • I just listed some states as examples
        • I think it would make sense that if an implementation that does not support a given state separately for each field, then (such as isDIrty), then it simply returns the state of the surrounding object (such as the object's dirty flag).
        • The previous point got me thinking whether it may make sense to require that ObjectState and FieldState should be identical with respect to the available states, even if JDO would not support different states for each field in all cases. I imagine this could simplify code that accesses the fields' states, because otherwise one should ideally always query the ObjectState first.
        • If we don't implement FieldState, we should determine what is Loaded() returns in case of 'deleted' objects, 'detached' objects, 'new' objects (are they loaded or not?), and so on.
        Show
        Tilmann Zäschke added a comment - - edited Clarification: My proposal mainly aims at three things: Making the API easily extensible for additional field states in future. Using an enum would simplify adding new states and combination of states Consistency based on similarity with the ObjectState enum Avoiding 'null' as return value About the actual states: I just listed some states as examples I think it would make sense that if an implementation that does not support a given state separately for each field, then (such as isDIrty), then it simply returns the state of the surrounding object (such as the object's dirty flag). The previous point got me thinking whether it may make sense to require that ObjectState and FieldState should be identical with respect to the available states, even if JDO would not support different states for each field in all cases. I imagine this could simplify code that accesses the fields' states, because otherwise one should ideally always query the ObjectState first. If we don't implement FieldState, we should determine what is Loaded() returns in case of 'deleted' objects, 'detached' objects, 'new' objects (are they loaded or not?), and so on.
        Hide
        Tilmann Zäschke added a comment - - edited

        I understand that this method basically provides state interrogation for fields. Would it make sense (also building on Andy's comment) to do something like the following instead?

        FieldState getFieldState(Object pc, String field);

        enum FieldState

        { HOLLOW, CLEAN, DIRTY, NOT_SUPPORTED; }

        This could even be extended with DETACHED or similar.

        Independent of this, I'm not sure that returning Boolean/null is ideal, even if it may be consistent with other parts of JDO. I think it is a bit awkward to always have to check for (!= null) before using a return value. An API may be easier to use if 'null' is avoided as return value.

        Show
        Tilmann Zäschke added a comment - - edited I understand that this method basically provides state interrogation for fields. Would it make sense (also building on Andy's comment) to do something like the following instead? FieldState getFieldState(Object pc, String field); enum FieldState { HOLLOW, CLEAN, DIRTY, NOT_SUPPORTED; } This could even be extended with DETACHED or similar. Independent of this, I'm not sure that returning Boolean/null is ideal, even if it may be consistent with other parts of JDO. I think it is a bit awkward to always have to check for (!= null) before using a return value. An API may be easier to use if 'null' is avoided as return value.
        Michael Bouschen made changes -
        Field Original Value New Value
        Fix Version/s JDO 3.2 [ 12316653 ]
        Hide
        Andy Jefferson added a comment -

        DataNucleus already provides something related. See
        http://datanucleus.svn.sourceforge.net/viewvc/datanucleus/platform/core/trunk/src/java/org/datanucleus/jdo/NucleusJDOHelper.java?revision=9230&view=markup

        String[] NucleusJDOHelper.getDetachedObjectLoadedFields(Object obj, PersistenceManager pm);
        String[] NucleusJDOHelper.getDetachedObjectDirtyFields(Object obj, PersistenceManager pm);

        Show
        Andy Jefferson added a comment - DataNucleus already provides something related. See http://datanucleus.svn.sourceforge.net/viewvc/datanucleus/platform/core/trunk/src/java/org/datanucleus/jdo/NucleusJDOHelper.java?revision=9230&view=markup String[] NucleusJDOHelper.getDetachedObjectLoadedFields(Object obj, PersistenceManager pm); String[] NucleusJDOHelper.getDetachedObjectDirtyFields(Object obj, PersistenceManager pm);
        Matthew T. Adams created issue -

          People

          • Assignee:
            Unassigned
            Reporter:
            Matthew T. Adams
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:

              Development