Skip to main content
Skip table of contents

Creating a New CC6 Component

A component contains protocol definitions; there are no concrete implementations in a component. The following procedure can be used to create a component for a query, function, report, route, or notification. For information about these services, refer to Cantara Configuration Guide. To help explain the procedure to create a new component, an example based on the JDE GetAllPurchaseOrderHeader query is referred to at each step.

To create a new component, each of the following protocols (interfaces) must be created:

protocols for example Component

To create a Component
  1. Create a new Entity.

    Entity

    Filename

    <Entity>    

    Eg: PurchaseOrderHeader

    Location

    schema/<ModuleName>/    

    Eg: schema/logistics/PurchaseOrderHeader

    Conforms toDecodable and UniqueEntity
    LibrarySchema
    Properties

    The Entity's data structure can be obtained by using the Cantara Administration Console to view the parameters for the required JDE service.

    Following the example mentioned above, this would be the query "PurchaseOrderHeader" object.

    Code

    Swift Example

    JAVA
    import Foundation
    /// Definition for a PurchaseOrderHeader object
    public protocol PurchaseOrderHeaderBase: UniqueEntity {
      var orderNumber: Int { get set }
      var orderType: String { get set }
      var company: String { get set }
      var suffix: String { get set }
      var approverNumber: String { get set }
      var approverName: String { get set }
      var approvalRoute: String { get set }
      var costCenter: String { get set }
      var supplier: String { get set }
      var supplierName: String { get set }
      var originatorNumber: String { get set }
      var originatorName: String { get set }
      var orderDate: Date? { get set }
      var amount: Double { get set }
    }
    public protocol PurchaseOrderHeader: PurchaseOrderHeaderBase, Decodable, MediaObjectable {
    }
    extension PurchaseOrderHeader where Self: MediaObjectable {
      public var mediaObjectName: String {
        return "GT4301"
      }
      public var mediaObjectKey: String {
        return "\(orderNumber)|\(orderType)|\(company)|\(suffix)"
      }
    }

    Kotlin Example

    JAVA
    /**
     * Definition for a PurchaseOrderHeader object.
     *
     * @constructor
     */
    
    interface PurchaseOrderHeader : Decodable<PurchaseOrderHeader>, UniqueEntity, MediaObjectable {
      var approvalRoute: String
      var orderNumber: Int
      var orderType: String
      var company: String
      var suffix: String
      var approverNumber: String
    
      override val mediaObjectName: String
        get() = "GT4301"
    
      override val mediaObjectKey: String
        get() = "$orderNumber|$orderType|$company|$suffix"
    }



  2. Create a Request.

    Request   

    Filename

    Get<ComponentName>

    Eg:  GetPurchaseOrderHeader

    Location

    component/<moduleName>/resource/<ComponentName>/request 

    Eg:  component/logistics/resource/PurchaseOrderHeader/request/GetPurchaseOrderHeader

    Conforms to

    QueryRequestable, FunctionRequestable, or both (depending on the usage).

    LibraryComponents
    Properties
    Code
    Create a default implementation within the protocol for android or in an extension for ios that should create and return a query/function request. 
    Make sure the properties match the query filters in Cantara Console for the request(s) you are creating.


    Swift Example

    JAVA
    import CCCore
    import CCSchema
    import Foundation
    /// Definition for a getting a PurchaseOrderHeader
    public protocol GetPurchaseOrderHeader: QueryRequestable {
      var orderNumber: Int { get set }
      var orderType: String { get set }
      var company: String { get set }
      var suffix: String { get set }
    }
    extension GetPurchaseOrderHeader {
      /// Creates a query request for a PurchaseOrderHeader
      public var queryRequest: QueryRequest {
        var queryRequest = QueryRequest(name: "LOG_GetPurchaseOrderHeader")
        queryRequest.addCriteriaParameter(name: "DocumentOrderInvoiceE", criteriaLiteral: orderNumber)
        queryRequest.addCriteriaParameter(name: "CompanyKeyOrderNo", criteriaLiteral: company)
        queryRequest.addCriteriaParameter(name: "OrderSuffix", criteriaLiteral: suffix)
        return queryRequest
      }
    }
    extension GetPurchaseOrderHeader {
      public var filterPredicate: NSPredicate? {
        return NSCompoundPredicate(andPredicateWithSubpredicates: [
          NSPredicate(format: "%K == %i", "orderNumber", orderNumber),
          NSPredicate(format: "%K == %@", "orderType", orderType),
          NSPredicate(format: "%K == %@", "suffix", suffix),
          NSPredicate(format: "%K == %@", "company", company)
        ])
      }
    }
    

    Kotlin Example

    JAVA
    /**
     * Definition for a getting a PurchaseOrderHeader.
     *
     * @constructor
     */
    
    interface GetPurchaseOrderHeader : QueryRequestable<PurchaseOrderHeader> {
      var orderNumber: Int
      var orderType: String
      var company: String
      var suffix: String
    
      override var queryName: String
        get() = "LOG_GetPurchaseOrderHeader"
        set(_) {}
    
      override fun toQueryRequest(): QueryRequest {
        val queryRequest = QueryRequest(queryName)
        queryRequest.addCriteriaParameter("DocumentOrderInvoiceE", orderNumber)
        queryRequest.addCriteriaParameter("CompanyKeyOrderNo", company)
        queryRequest.addCriteriaParameter("OrderSuffix", suffix)
        queryRequest.addCriteriaParameter("OrderType", orderType)
    
        return queryRequest
      }
    
      override fun applyFilter(entity: List<PurchaseOrderHeader>): List<PurchaseOrderHeader> {
        return entity.filter { it.orderNumber == this.orderNumber }
          .filter { it.orderType == this.orderType }
          .filter { it.suffix == suffix }
          .filter { it.company == this.company }
      }
    
      override fun applyFilterForFirst(entity: List<PurchaseOrderHeader>): PurchaseOrderHeader? {
        return entity.filter { it.orderNumber == this.orderNumber }
          .filter { it.orderType == this.orderType }
          .filter { it.suffix == suffix }
          .firstOrNull { it.company == this.company }
      }
    }



  3. Create an API

    API   

    Filename

    <ComponentName>API

    Eg:  PurchaseOrderHeaderAPI

    Location

    component/<moduleName>/resource/<ComponentName>/        

    Eg:  component/logistics/resource/PurchaseOrderHeader/PurchaseOrderHeaderAPI

    Conforms to
    LibraryComponents
    Properties

    Create a default implementation within the protocol for android or in an extension for ios that should create and return a query/function request. 
    Make sure the properties match the query filters in Cantara Console for the request(s) you are creating.

    Code

    It should have a generic type that conforms to the Entity that you created above, Eg PurchaseOrderHeader

    Write get function(s) that will be used to execute a query or function request. It should take the Request that has been made already as a parameter, and return an observable that represents an array of the model in the protocol.

    Swift Example

    JAVA
    import CCSchema
    import Foundation
    import RxSwift
    
    public protocol PurchaseOrderHeaderAPI {
      associatedtype PurchaseOrderHeaderType: PurchaseOrderHeader
    
      func get(for uuid: UUIDString) -> Maybe<PurchaseOrderHeaderType>
    
      /// Get a PurchaseOrderHeader for the given request
      ///
      /// - Parameter request: The request used to get the PurchaseOrderHeader
      /// - Returns: An observable value which represents a PurchaseOrderHeader if no error is thrown
      func get(_ request: GetPurchaseOrderHeader) -> Maybe<PurchaseOrderHeaderType>
    
      /// Get orders waiting for approval for the given request
      ///
      /// - Parameter request: The request used to get the PurchaseOrderHeaders
      /// - Returns: An observable value which represents an array of PurchaseOrderHeaders if no error is thrown
      func get(_ request: GetPurchaseOrdersAwaitingApproval) -> Observable<[PurchaseOrderHeaderType]>
    
      func get(_ request: GetOrdersForApprovalRoute) -> Observable<[PurchaseOrderHeaderType]>
    
      func delete(_ request: DeletePurchaseOrderHeader) -> Observable<Void>
    }

    Kotlin Example

    JAVA
    /**
     * The PurchaseOrderHeaderAPI is responsible for handling dao and resource requests for a
     * PurchaseOrderHeader
     *
     * @constructor
     */
    
    interface PurchaseOrderHeaderAPI<PurchaseOrderHeaderType : PurchaseOrderHeader> {
    
      /**
       * Get a purchaseOrderHeader from the database using the unique Id
       *
       * @param uuid: The identifier for the purchaseOrderHeader
       * @return A Maybe value that represents a purchaseOrderHeader or null
       */
      fun executeFetchPurchaseOrderHeader(uuid: UUIDLong): Maybe<PurchaseOrderHeaderType>
    
      /**
       * Get a purchaseOrderHeader for a given request
       *
       * @param request: The request used to get the purchaseOrderHeader
       * @param response: The class the response from the server should be formatted to
       * @return A single value that represents a purchaseOrderHeader
       */
      fun executeGetPurchaseOrderHeader(
          request: GetPurchaseOrderHeader,
          response: PurchaseOrderHeaderType
      ): Maybe<PurchaseOrderHeaderType>
    
      /**
       * Get orders waiting for approval for a given request
       *
       * @param request: The request used to get the purchaseOrderHeader
       * @param response: The class the response from the server should be formatted to
       * @return An observable value that represents a purchaseOrderHeader
       */
      fun executeGetPurchaseOrdersAwaitingApproval(
          request: GetPurchaseOrdersAwaitingApproval,
          response: PurchaseOrderHeaderType
      ): Observable<List<PurchaseOrderHeaderType>>
    
      /**
       * Get orders for approval for a given request
       *
       * @param request: The request used to get the purchaseOrderHeader
       * @return An observable value that represents a purchaseOrderHeader
       */
      fun executeGetOrdersForApprovalRoute(
          request: GetOrdersForApprovalRoute,
          response: PurchaseOrderHeaderType
      ): Observable<List<PurchaseOrderHeaderType>>
    
      /**
       * performs approve or reject of a purchase order
       *
       * @param request: The request that performs the approval or rejection
       * @return A completable that returns a success or failure
       */
      fun executeApproveRejectPurchaseOrder(request: ApproveRejectPurchaseOrder): Completable
    
      /**
       * Deletes a Purchase order header matching the provided unique ID from the database
       *
       * @param uuid: Unique identifier for the purchase order header object
       * @return A completable that returns a success or failure
       */
      fun executeDeleteApprovedRejectedPurchaseOrder(uuid: Long): Completable
    
    }



  4. Create a Dao

    Dao

    Filename

    <ComponentName>Dao

    Eg:  PurchaseOrderHeaderDao

    Location

    component/<moduleName>/resource/<ComponentName>/        

    Eg:  component/logistics/resource/PurchaseOrderHeader/PurchaseOrderHeaderDao

    Conforms to

    DaoProtocol for the (eg) PurchaseOrderHeader

    LibraryComponents
    Properties

    Create a default implementation within the protocol for android or in an extension for ios that should create and return a query/function request. 
    Make sure the properties match the query filters in Cantara Console for the request(s) you are creating.

    Code

    Defines a standard on how to perform CRUD operations on any given object.
    Write any object specific method stubs that is not covered in the DaoProtocol. Here is an example for a UserDefinedCodeDao:

    Swift Example

    JS
    /// A store that defines how to perform CRUD operations on a PurchaseOrderHeader
    /// object
    public protocol PurchaseOrderHeaderDao: DaoProtocol where Entity: PurchaseOrderHeader {}
    
    

    Kotlin Example

    JAVA
    /**
     * A store that defines how to perform CRUD operations on a PurchaseOrderHeader object
     *
     * @constructor
     */
    
    interface PurchaseOrderHeaderDao : DaoProtocol<PurchaseOrderHeader>



  5. Create a Service

    Service   

    Filename<ComponentName>Service
    Location

    component/<moduleName>/resource/<ComponentName>/        

    Eg:  component/logistics/resource/PurchaseOrderHeader/PurchaseOrderHeaderService

    Conforms to

    ServiceProtocol for the (eg) PurchaseOrderHeader

    LibraryComponents
    Properties

    Create a default implementation within the protocol for android or in an extension for ios that should create and return a query/function request. 
    Make sure the properties match the query filters in Cantara Console for the request(s) you are creating.

    Code

    Defines the standard for how either a function or query request would communicate with a service.
    Create a default implementation within the protocol for android or in an extension for ios for a specific instance not covered in the ServiceProtocol.

    Swift Example

    JAVA
    /// Service that defines how to interact with a PurchaseOrderHeader
    public protocol PurchaseOrderHeaderService: ServiceProtocol where Entity: PurchaseOrderHeader {}
    
    

    Kotlin Example

    JAVA
    /**
     * Service that defines how to interact with a PurchaseOrderHeader
     *
     * @constructor
     */
    
    interface PurchaseOrderHeaderService : ServiceProtocol<PurchaseOrderHeader> 



  6. Create a Worker

    Worker   

    FileName

    <ComponentName>Worker

    Eg:  PurchaseOrderHeaderWorker

    Location

    component/<moduleName>/resource/<ComponentName>/        

    Eg:  component/logistics/resource/PurchaseOrderHeader/PurchaseOrderHeaderWorker

    Conforms to

    <ComponentName>API and WorkerProtocol

    LibraryComponents
    Properties

    Create a default implementation within the protocol for android or in an extension for ios that should create and return a query request. 
    Make sure the properties match the query filters in Cantara Console for the request(s) you are creating.

    Code

    Defines the standard for how the worker should interact with the Dao and service components. It will need to have a Dao and Service as properties, whose types are the Dao and Service created above.
    Define a default implementation within the protocol for android or in an extension for ios. The default implementation should contain functions to get the component, get from the dao, and get from the service.
    The functions should take a component request as a parameter and return an observable array of the component type.

    Swift Example

    JS
    /// The PurchaseOrderHeaderWorker is responsible for handling dao and service requests for a
    /// PurchaseOrderHeader
    public protocol PurchaseOrderHeaderWorker: PurchaseOrderHeaderAPI, WorkerProtocol
    where Entity == PurchaseOrderHeaderType, Dao: PurchaseOrderHeaderDao, Service: PurchaseOrderHeaderService {}
    extension PurchaseOrderHeaderWorker {
      public func get(for uuid: UUIDString) -> Maybe<PurchaseOrderHeaderType> {
        return dao.entity(for: uuid)
      }
      public func get(_ request: GetPurchaseOrdersAwaitingApproval) -> Observable<[PurchaseOrderHeaderType]> {
        return entities(for: request)
      }
      public func get(_ request: GetPurchaseOrderHeader) -> Maybe<PurchaseOrderHeaderType> {
        return entity(for: request)
      }
      public func get(_ request: GetOrdersForApprovalRoute) -> Observable<[PurchaseOrderHeaderType]> {
        return dao.entities(for: request)
      }
      public func delete(_ request: DeletePurchaseOrderHeader) -> Observable<Void> {
        return deleteEntities(for: request)
      }
    }
    
    

    Kotlin Example

    JAVA
    /**
     * Definition for a PurchaseOrderHeaderWorker. Conforms to PurchaseOrderHeaderAPI
     * 
     * The PurchaseOrderHeaderWorker is responsible for handling dao and service requests for a PurchaseOrderHeader
     *
     * @constructor
     */
    
    interface PurchaseOrderHeaderWorker : PurchaseOrderHeaderAPI<PurchaseOrderHeader>, WorkerProtocol<PurchaseOrderHeader> {
    
      override val dao: PurchaseOrderHeaderDao
      override val service: PurchaseOrderHeaderService
    
      override fun executeFetchPurchaseOrderHeader(uuid: UUIDLong): Maybe<PurchaseOrderHeader> {
        return dao.fetchEntityWith(uuid)
      }
    
      override fun executeGetPurchaseOrderHeader(request: GetPurchaseOrderHeader, response: PurchaseOrderHeader): Maybe<PurchaseOrderHeader> {
        return fetchEntity(request, response)
      }
    
      override fun executeGetPurchaseOrdersAwaitingApproval(
          request: GetPurchaseOrdersAwaitingApproval,
          response: PurchaseOrderHeader
      ): Observable<List<PurchaseOrderHeader>> {
        return fetchEntities(request, response)
      }
    
      override fun executeGetOrdersForApprovalRoute(
          request: GetOrdersForApprovalRoute,
          response: PurchaseOrderHeader
      ): Observable<List<PurchaseOrderHeader>> {
        return dao.queryEntities()
      }
    
      override fun executeApproveRejectPurchaseOrder(request: ApproveRejectPurchaseOrder): Completable {
        return service.approveReject(request)
      }
    }




JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.