3 Replies Latest reply on Feb 10, 2016 12:06 PM by sharmon RSS
    sharmon Creator

    How can I customize or extend Axeda provided domain objects?

    A student in the Axeda Groovy course had some good questions. Instead of answering via email, I thought I'd answer here, so we could share the knowledge.


    Domain Objects - How can I customize or extend Axeda provided domain objects? (Eg., I need to store whether a user is external or internal user) How can I achieve this?


    This is a perfect use case for the Axeda Extended Data API. Documentation on the API can be found in the Axeda Platform v1 API Developer's Reference Guide. A good, "Getting Started," topic is available on Axeda Mentor - Getting Started With the Axeda Extended Data API.


    To customize/extend/decorate Axeda-provided domain objects, use Extended Objects. Extended Objects can be thought of in the abstract as a collection of custom database table rows. The analogy isn't perfect, but it helps with understanding.


    The use case in the question is very common. Extended Objects can stand on their own, or they can be associated with an Axeda domain object with the setInternalID() method. In the following sample code, we "decorate" an Axeda User object with two new fields, isExternalUser and companyID:


    private void updateAdditionalFieldsForUser(User user, boolean isExternalUser, String companyID) {   // GET OBJECT TYPE - This example assumes the ExtendedObjectType has already been created   ExtendedObjectType extObjectType = extendedObjectService.findExtendedObjectTypeByClassname("com.axeda.drm.sdk.user.User")   // GET PROPERTY TYPES   PropertyType isExternalUserPropertyType = findOrCreatePropertyType(extObjectType, "IS_EXTERNAL_USER")   PropertyType companyIdPropertyType = findOrCreatePropertyType(extObjectType, "COMPANY_ID")      /* GET THE EXTENDED OBJECT   * Note - the example provides a findExtendedObject() method that searches by INTERNAL ID. This linkage via the internal ID   * associates a domain object to an ExtendedObject, allowing us to "decorate" it with custom attributes   */   ExtendedObject extObject = findExtendedObject(extObjectType, user.id.value)   if (extObject == null)   {     extObject = new ExtendedObject()     extObject.setExtendedObjectType(extObjectType)     extObject.setInternalObjectId(user.id.value)     extObject.addProperty(createExtendedProperty(isExternalUserPropertyType, isExternalUser.toString()))     extObject.addProperty(createExtendedProperty(companyIdPropertyType, companyID))     extendedObjectService.createExtendedObject(extObject)   }   else   {     addOrUpdateExtendedProperty(extObject, isExternalUserPropertyType, "IS_EXTERNAL_USER", isExternalUser.toString())     addOrUpdateExtendedProperty(extObject, companyIdPropertyType, "COMPANY_ID", companyID)     extendedObjectService.updateExtendedObject(extObject)   } }  /**  * Adds or Updates an extended property.  *  * @param extendedObject the extended object to associate with the property  * @param propertyType the type of the property  * @param propertyName the name of the property  * @param propertyValue the value of the property  */ private void addOrUpdateExtendedProperty(ExtendedObject extendedObject, PropertyType propertyType, String propertyName, String propertyValue) {   Property extendedProperty = extendedObject.getPropertyByName(propertyName)   if (extendedProperty == null)   {   extendedProperty = createExtendedProperty(propertyType, propertyValue)   extendedObject.addProperty(extendedProperty)   }   else   {   extendedProperty.setValue(propertyValue)   } }  /**  * Retrieves and returns the extended object with the given type and internal id.  *  * @param extObjectType the type of the desired external object  * @param internalObjectId the internal id of the desired extended object  * @return the extended object matching the given details or <code>null</code> in case there's no match  */ private ExtendedObject findExtendedObject(ExtendedObjectType extObjectType, Long internalObjectId) {   ExtendedObjectSearchCriteria searchCriteria = new ExtendedObjectSearchCriteria()   searchCriteria.setExtendedObjectTypeId(extObjectType.getId())   searchCriteria.setInternalObjectId(internalObjectId)    List<ExtendedObject> extObjects = extendedObjectService.findExtendedObjects(searchCriteria, -1, 0, "name")    if (!extObjects?.isEmpty())   {    return extObjects[0]   }   return null }  /**  * Gets a property type given its name and the associated extended object type.  * If it cannot find the property type it will create it.  *  * @param extendedObjectType the associated extended object type for the property type  * @param propertyTypeName the property type name  * @return the property type  */  private PropertyType findOrCreatePropertyType(ExtendedObjectType extendedObjectType, String propertyTypeName)  {     PropertyType propertyType = extendedObjectType.getPropertyTypeByName(propertyTypeName)     if (propertyType == null)     {       propertyType = new PropertyType()       propertyType.setDataType(PropertyDataType.String)       propertyType.setName(propertyTypeName)       propertyType.setExtendedObjectType(extendedObjectType)       extendedObjectService.createPropertyType(propertyType)       extendedObjectType.addPropertyType(propertyType)     }     return propertyType  }


    By using Extended Objects, and associating them with Axeda domain objects via an internal ID, we can decorate/extend/customize those domain objects with use-case-specific attributes.

      • Re: How can I customize or extend Axeda provided domain objects?
        babraham Newbie

        Stephen,

                  Thanks for posting this.

         

        In the above example we are adding new properties to user domain objects, will the property be persisted by default?

         

        Like, I am adding new property external/internal to user domain object will that property be persisted for that user? The next time when I login into the system will that property be available for the user?

         

        Also how we are storing this data in Axeda back end? do we have a database for Axeda?


        • Re: How can I customize or extend Axeda provided domain objects?
          babraham Newbie

          Hi,

            We tried executing the above program, but we are getting error and not able to see any useful information in log files.

           

          <error>

          <faultcode>

          1. ErrorType.PlatformSDKException.ErrorCode.-1

          </faultcode>

          <faultstring>

          No signature of method: com.axeda.drm.services.customobject.groovy.ExtendedObjectType() is applicable for argument types: (null) values: [null]

          </faultstring>

          </error>

           

          Could you please suggest how to pull useful log information, I tried pulling the log file archive located down the table of custom objects. I am not able to see any useful information related to this.

            • Re: How can I customize or extend Axeda provided domain objects?
              sharmon Creator

              Whew - first of all, the migration of this question from the Axeda Community to the ThingWorx Community really did a number on the formatting, so let me post reformatted code, in case that's the problem:

               

              private void updateAdditionalFieldsForUser(User user, boolean isExternalUser, String companyID) {
                  // GET OBJECT TYPE - This example assumes the ExtendedObjectType has already been created
                  ExtendedObjectType extObjectType = extendedObjectService.findExtendedObjectTypeByClassname("com.axeda.drm.sdk.user.User")
                  // GET PROPERTY TYPES
                  PropertyType isExternalUserPropertyType = findOrCreatePropertyType(extObjectType, "IS_EXTERNAL_USER")
                  PropertyType companyIdPropertyType = findOrCreatePropertyType(extObjectType, "COMPANY_ID")
              
              
                  /* GET THE EXTENDED OBJECT
                  * Note - the example provides a findExtendedObject() method that searches by INTERNAL ID. This linkage via the internal ID
                  * associates a domain object to an ExtendedObject, allowing us to "decorate" it with custom attributes  */
                  ExtendedObject extObject = findExtendedObject(extObjectType, user.id.value)
                      if (extObject == null) {
                          extObject = new ExtendedObject()
                          extObject.setExtendedObjectType(extObjectType)
                          extObject.setInternalObjectId(user.id.value)
                          extObject.addProperty(createExtendedProperty(isExternalUserPropertyType, isExternalUser.toString()))
                          extObject.addProperty(createExtendedProperty(companyIdPropertyType, companyID))
                          extendedObjectService.createExtendedObject(extObject)
                      } else {
                          addOrUpdateExtendedProperty(extObject, isExternalUserPropertyType, "IS_EXTERNAL_USER", isExternalUser.toString())
                          addOrUpdateExtendedProperty(extObject, companyIdPropertyType, "COMPANY_ID", companyID)
                          extendedObjectService.updateExtendedObject(extObject)
                      }
              }
              
              /** Adds or Updates an extended property.
              * @param extendedObject the extended object to associate with the property
              * @param propertyType the type of the property
              * @param propertyName the name of the property
              * @param propertyValue the value of the property
              */
              private void addOrUpdateExtendedProperty(ExtendedObject extendedObject, PropertyType propertyType, String propertyName, String propertyValue) {
                  Property extendedProperty = extendedObject.getPropertyByName(propertyName)
                  if (extendedProperty == null)
                      {
                          extendedProperty = createExtendedProperty(propertyType, propertyValue)
                          extendedObject.addProperty(extendedProperty)
                      } else {
                          extendedProperty.setValue(propertyValue)
                      }
              }
              /** Retrieves and returns the extended object with the given type and internal id.
              * @param extObjectType the type of the desired external object
              * @param internalObjectId the internal id of the desired extended object
              * @return the extended object matching the given details or <code>null</code> in case there's no match  */
              private ExtendedObject findExtendedObject(ExtendedObjectType extObjectType, Long internalObjectId) {
                  ExtendedObjectSearchCriteria searchCriteria = new ExtendedObjectSearchCriteria()
                  searchCriteria.setExtendedObjectTypeId(extObjectType.getId())
                  searchCriteria.setInternalObjectId(internalObjectId)
                  List<ExtendedObject> extObjects = extendedObjectService.findExtendedObjects(searchCriteria, -1, 0, "name")
                  if (!extObjects?.isEmpty()) {
                      return extObjects[0]
                  }
                  return null
              }
              
              /** Gets a property type given its name and the associated extended object type.
              * If it cannot find the property type it will create it.
              * @param extendedObjectType the associated extended object type for the property type
              * @param propertyTypeName the property type name
              * @return the property type */
              private PropertyType findOrCreatePropertyType(ExtendedObjectType extendedObjectType, String propertyTypeName) {
                  PropertyType propertyType = extendedObjectType.getPropertyTypeByName(propertyTypeName)
                  if (propertyType == null) {
                      propertyType = new PropertyType()
                      propertyType.setDataType(PropertyDataType.String)
                      propertyType.setName(propertyTypeName)
                      propertyType.setExtendedObjectType(extendedObjectType)
                      extendedObjectService.createPropertyType(propertyType)
                      extendedObjectType.addPropertyType(propertyType)
                  }
                  return propertyType
              }
              

               

              There are a couple of things about this example you'll want to keep in mind:

              • It assumes the com.axeda.drm.sdk.user.User ExtendedObjectType has already been created. It should be there already, but if it's not, you'll have to run one-time creation code to get the ExtendedObjectType into your instance. See Axeda v2 API-Services Developer's Reference Guide 6.8 for more information and sample code.
              • The properties in the example apply to an example use case. You may want to modify them to fit your situation.

               

              To get more useful log messages, make use of logger.debug(), logger.info(), and logger.error(). (Check your logging levels in your admin pages, and make sure the right level is enabled.) For example, you could get some insights from the code above with:

               

               // GET OBJECT TYPE - This example assumes the ExtendedObjectType has already been created
                  ExtendedObjectType extObjectType = extendedObjectService.findExtendedObjectTypeByClassname("com.axeda.drm.sdk.user.User")
                  logger.debug extObjectType.toString()
                  // GET PROPERTY TYPES
                  PropertyType isExternalUserPropertyType = findOrCreatePropertyType(extObjectType, "IS_EXTERNAL_USER")
                 logger.debug isExternalUserPropertyType.toString()
                  PropertyType companyIdPropertyType = findOrCreatePropertyType(extObjectType, "COMPANY_ID")
                 ...
              

               

              You could also surround calls to external services like extendedObjectService.findExtendedObjectTypeByClassname(...) and sending detailed info about any caught errors to the log.