X

Technical Articles relating to Oracle Development Tools and Frameworks

  • JET
    February 7, 2017

JET Custom Components XI - Metadata Extensibility

Duncan Mills
Architect

Introduction

In previous articles in this series, I have discussed some of the ways in which you can extend or override the Composite Component Framework. These include the overriding of lifecycle method callback names (not recommended and no longer supported) and custom property parsing (very useful but rare). Additionally, of course you have the lifecycle methods themselves as a place to carry out the internal operations of your components. This all adds up to a pretty rich working environment, but the addition of the custom metadata capability really completes this story. In this article, I'll be looking at how to define and work with extended metadata.

Defining Custom Metadata in the Composite Component Architecture

We have already seen how the definition metadata can contain information above and beyond that which is strictly required for runtime use. The description property and method parameter properties are examples of this. The intention of course being that consumers of the component can receive a richer description of it. However, even those "Design Time" attributes may not be enough and so the framework also supports an extension mechanism.

Additional metadata of your own can be introduced anywhere within the custom component metadata definition (e.g. its component.json file) using the property extension. The value of this property can be defined as a complex object in it's own right allowing you to define an unlimited amount of ancillary information on top of the base API.

Here's an example of metadata with some extensions added:

      {
        "name" : "ccdemo-meter-reader",
        "version" : "1.0.0",
        "jetVersion" : ">=2.3.0",
        "extension": {
          "author" : "Duncan Mills",
          "license": "MIT"
        }
        "properties" : {
          "fromMonth" : {
            "description" : "Start of display range",
            "type" : "date",
            "extension": {
              "validate" : {
                "type" : "range"
                "minValue" : 1,
                "maxValue" : 12
              }
            }
          },
          "utility" : {
            "description" : "gas | electricity",
            "type" : "string",
            "extension" : {
              "validate" : {
                "type" : "enumeration"
                "values" : ['gas','electricity']
              }
            }
          }
        }
      }

In this case I've just decorated the top level and the two properties, however, you can supply an extension attribute to any of the definition objects within the metadata except the properties, methods or events root objects which would, of course interpret the extension keyword as just another property, method or event definition respectively.

 The Composite Component framework itself, will do nothing with these extension properties after the metadata is parsed. Any functionality (such as the range and enum checking that I've illustrated here) is a task for the component author1, or exists to help some design time tool that you develop in-house to use the extension.

By design, there are currently no prescribed set of attributes for any extension metadata that you define. You have total freedom as to how you use the facility, however, be aware that some further evolution and standardization of CCA metadata will be taking place over the next few releases of JET. So you should certainly keep an eye on the release notes for changes in this area,

Accessing the Extended Metadata

Just being able to extend the metadata definition without being able to read it again afterwards would not be very useful. Therefore, framework provides two ways to access the metadata including any extension information that you have supplied:

  1. From a Custom Property Parser - as I discussed in Part X, one of the attributes passed to any custom parser that you register, is the metadata for the property being parsed. This would provide a convenient place to read the extension metadata as defined for that property and use it, for example, providing a validation mechanism as illustrated here. You only see property metadata here though, not the whole metadata defintion.
  2. From oj.Composite - the oj.Composite object provides a static method called getMetadata() to retreive the whole metadata object for the Composite Component. This takes the name of the component (the same one passed to the oj.Composite.register() function) and returns a promise to the resolved metadata object. Because this function is both static and external to the custom component, it can be used both within the component itself or by external entities such as Design Time tooling that wishes to introspect the component. Note that the component has (of course) to be loaded / registered before it can be described by this API2.

Between them, these two approaches provide the access you need. The rest is up to you!

Don't Forget to Standardize!

It's all very well having the freedom to extend the CCA metadata in pretty much any way that you want. However, you want to be consistent in how you approach this task. Keep in mind that the CCA is constantly evolving and more standard metadata will be added as new releases arrive. So you should be prepared to revisit your use of metadata with each release and migrate any custom definitions to the standardized ones. This will ensure maximum compatibility with any tooling that reads the metadata. You should also never add custom attributes directly to the JSON outside of the extension property buckets. This will ensure that you don't inadvertently add a property which might clash with a future feature property added by the framework. The extension properties are your "safe zone", stick to adding value there. Furthermore, I would recommend that you namespace your extension metadata within the extension object, for example: 

"extension" : {
  "acme" : {
    "extensionProp1":"Some Value"
  }
}

This will enble you, and any of the consumers of your Composite Component, to clearly identify the relationship between the extension metatdata and it's usage. This will become particularly important if you build many CCAs, some of which will share "common" extension metadata maybe used by your "superclasses" as well as having component specific extension metadata.

What's Next?

We're almost done with the core technology aspects of the Composite Component Architecture, in the next article I wrap that all up with some of the more advanced topics around the loader script and registration process.


JET Custom Component Series

If you've just arrived at Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Learning Path


1 Actually you can look forward to basic enumeration being a core part of the formal property definition in the future, but at the time of writing this is not the case yet so this will still serve as an effective illustration.

2 In lifecycle terms the metadata promise is resolved before the CCA component viewModel constructor or initialize() is invoked so you should have no problems accessing it as you component starts up.

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.