Torque
  1. Torque
  2. TORQUE-147

Database objects should not need to inherit from BaseObject

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 4.0-beta1
    • Component/s: None
    • Labels:
      None

      Description

      Currently it is an error if database objects do not inherit from BaseObject. This makes embedding of Torque objects in other frameworks very difficult, because it does not allow to choose an own parent to inherit from.

      The minimum requirement would be that it is not required any more that database objects inherit from BaseObject.

      Ideally BaseObject dies and the base objects inherit directly from java.lang.object.

        Activity

        Hide
        CG Monroe added a comment -

        (Sorry for the direct torque-dev response.. re-doing it for the Jira issue).

        Moving methods to generated / changing interface +1 from me.

        Get/SetByName, et. al.

        IMHO, it would be NICE to have an interface that covers these. A use case for this would be common normalization or lookup functions. E.g., a function with a record object and column name as parameters that does something common to multiple table and columns, like scanning for profanity or normalizing case in across multiple tables that contains title and description fields.

        Perhaps this could be based on the java LinkedHashMap object methods or the org.apache.commons.collections.OrderedMap interface? With the key being the column name. Then allow users the choice of simple persistent objects or collection based persistent objects (which is a superset of the simple objects).

        I think you're right about getTableMap. That is Torque specific (but needed). If someone needs it inside a function using an interface parameter, they can always use the baseObject or cast

        Show
        CG Monroe added a comment - (Sorry for the direct torque-dev response.. re-doing it for the Jira issue). Moving methods to generated / changing interface +1 from me. Get/SetByName, et. al. IMHO, it would be NICE to have an interface that covers these. A use case for this would be common normalization or lookup functions. E.g., a function with a record object and column name as parameters that does something common to multiple table and columns, like scanning for profanity or normalizing case in across multiple tables that contains title and description fields. Perhaps this could be based on the java LinkedHashMap object methods or the org.apache.commons.collections.OrderedMap interface? With the key being the column name. Then allow users the choice of simple persistent objects or collection based persistent objects (which is a superset of the simple objects). I think you're right about getTableMap. That is Torque specific (but needed). If someone needs it inside a function using an interface parameter, they can always use the baseObject or cast
        Hide
        Thomas Fox added a comment -

        added a new interface ColumnAccessByName for the get/set byName, byPeerName and byPosition methods

        Show
        Thomas Fox added a comment - added a new interface ColumnAccessByName for the get/set byName, byPeerName and byPosition methods
        Hide
        Thomas Fox added a comment -

        I plan to impelemt this as follows:

        • move the isNew and modified flags (incl getters and setters) from BaseObject to the generated base classes
        • move the hashCode and equals methods from BaseObject to the generated base classes
        • remove the class BaseObject from the runtime
        • make all classes implement the org.apache.torque.om.Persistent interface
          This makes all test cases green.

        The following methods from BaseObject are not moved currently:

        • get/setByName, get/setByPeerName, get/setByPosition: I would not define those as necessary for persistent objects. Maybe these methods can be moved to a different interface which is only implemented if the user choses to generate these methods ?
        • getTableMap: Nots sure what to do with this method, if this were moved to the persistent interface it would make the interface rather Torque-specific. Currently it is not needed that the Persistent interface defines this method, and I'd rather leave this as is.

        The following methods are already implemented/overridden:

        • the save(...) methods which are defined in persistent are already generated
        • the getters/setters for the primary key which are defined in BaseObject are overridden in the generated classes. However, to retain current catch clauses in the generated classes, I'd change the throws clauses in persistent from Exception to TorqueException, plus these methods need also be implemented (throwing UnsupportedOperationExceptions) for tables without primary key.
        Show
        Thomas Fox added a comment - I plan to impelemt this as follows: move the isNew and modified flags (incl getters and setters) from BaseObject to the generated base classes move the hashCode and equals methods from BaseObject to the generated base classes remove the class BaseObject from the runtime make all classes implement the org.apache.torque.om.Persistent interface This makes all test cases green. The following methods from BaseObject are not moved currently: get/setByName, get/setByPeerName, get/setByPosition: I would not define those as necessary for persistent objects. Maybe these methods can be moved to a different interface which is only implemented if the user choses to generate these methods ? getTableMap: Nots sure what to do with this method, if this were moved to the persistent interface it would make the interface rather Torque-specific. Currently it is not needed that the Persistent interface defines this method, and I'd rather leave this as is. The following methods are already implemented/overridden: the save(...) methods which are defined in persistent are already generated the getters/setters for the primary key which are defined in BaseObject are overridden in the generated classes. However, to retain current catch clauses in the generated classes, I'd change the throws clauses in persistent from Exception to TorqueException, plus these methods need also be implemented (throwing UnsupportedOperationExceptions) for tables without primary key.
        Hide
        Thomas Fox added a comment -

        I should have been more clear before. The idea was to replace inheritance by implementing an interface. Intospection should really be the last option if everything else fails (but it will not be needed here IMO. If it will turns out it is needed, we need to discuss again)

        As for the beans, while they rdo what they are supposed to do, it turns out that in a real project you need to do a lot of convedrsion from Beans to Databse objects and vice versa. Consider e.g. a classic 3-Tier application: A database layer, a business layer and a presentation layer. The service layer would use database objects internally but its external interfaces are beans. This works well as long as a service does not call other services, (which is a perfect sensible thing to do) because then the caller service must convert ts internal object to beans, call the other service and convert the beans back to database objects. It can be done (we have a production project using this technique) but it is a pain.
        There might be good reasons for bean objects, but using beans as business objects is not a good thing to do in my opinion.

        Show
        Thomas Fox added a comment - I should have been more clear before. The idea was to replace inheritance by implementing an interface. Intospection should really be the last option if everything else fails (but it will not be needed here IMO. If it will turns out it is needed, we need to discuss again) As for the beans, while they rdo what they are supposed to do, it turns out that in a real project you need to do a lot of convedrsion from Beans to Databse objects and vice versa. Consider e.g. a classic 3-Tier application: A database layer, a business layer and a presentation layer. The service layer would use database objects internally but its external interfaces are beans. This works well as long as a service does not call other services, (which is a perfect sensible thing to do) because then the caller service must convert ts internal object to beans, call the other service and convert the beans back to database objects. It can be done (we have a production project using this technique) but it is a pain. There might be good reasons for bean objects, but using beans as business objects is not a good thing to do in my opinion.
        Hide
        CG Monroe added a comment -

        I'm -1 on making this a global change.

        I'm concerned about how you would do generic methods without BaseClass. E.g.:

        doSomethingBasedOnRecordType( BaseObject rec )

        { <use introspection to determine action> }

        Yes, I guess you can do the same thing using an object type. But IMHO, having at least an Interface to limit objects to valid records is better for documentation and compile time error checking.

        FWIW - I have a bunch of code that does just this. Some of it does generic stuff with the assumption of the presence of BaseObject methods in any record.

        IMHO, while this is a nice way to migrate, it would add require too much existing code to be changed if we just dropped BaseObject all together.

        Having an interface seems like better middle ground.

        If integration with external frameworks is a requirement for a subset of Torque users, then perhaps this could be an generation time option.

        Also, don't we handle a lot of this with the Beans generation options? If you need to interface with another framework that deals with POJO objects, just create a bean and pass it around. If the remote framework requires annotations, perhaps this is where that should happen.

        Show
        CG Monroe added a comment - I'm -1 on making this a global change. I'm concerned about how you would do generic methods without BaseClass. E.g.: doSomethingBasedOnRecordType( BaseObject rec ) { <use introspection to determine action> } Yes, I guess you can do the same thing using an object type. But IMHO, having at least an Interface to limit objects to valid records is better for documentation and compile time error checking. FWIW - I have a bunch of code that does just this. Some of it does generic stuff with the assumption of the presence of BaseObject methods in any record. IMHO, while this is a nice way to migrate, it would add require too much existing code to be changed if we just dropped BaseObject all together. Having an interface seems like better middle ground. If integration with external frameworks is a requirement for a subset of Torque users, then perhaps this could be an generation time option. Also, don't we handle a lot of this with the Beans generation options? If you need to interface with another framework that deals with POJO objects, just create a bean and pass it around. If the remote framework requires annotations, perhaps this is where that should happen.
        Hide
        Thomas Fox added a comment -

        No, there will still be BaseXXX and XXX for each table. Just the necessity that BaseXXX must inherit from BaseObject will be removed.

        Show
        Thomas Fox added a comment - No, there will still be BaseXXX and XXX for each table. Just the necessity that BaseXXX must inherit from BaseObject will be removed.
        Hide
        Christoph Engelbert added a comment -

        Personally I like the idea of removing inheritance to give the opinion of inheriting from other classes. If something is needed to recognize it as an legal Torque object it could be an marker interface or marker annotation.
        But for me, if I'm not wrong, there's a problem about (at least) the Maven plugin which regenerates the BaseClasses on every build or do you guys want to remove that double-class concept at all?

        Show
        Christoph Engelbert added a comment - Personally I like the idea of removing inheritance to give the opinion of inheriting from other classes. If something is needed to recognize it as an legal Torque object it could be an marker interface or marker annotation. But for me, if I'm not wrong, there's a problem about (at least) the Maven plugin which regenerates the BaseClasses on every build or do you guys want to remove that double-class concept at all?

          People

          • Assignee:
            Thomas Fox
            Reporter:
            Thomas Fox
          • Votes:
            1 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development