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:
![](../../__attachments/8586213/Component%20Interfaces.png?inst-v=d656f64a-d9f2-4e03-9d65-6c5227554a07)
protocols for example Component
To create a Component
Create a new Entity.
Entity
Filename <Entity>
Eg: PurchaseOrderHeader
Location schema/<ModuleName>/
Eg: schema/logistics/PurchaseOrderHeader
Conforms to Decodable and UniqueEntity Library Schema 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
JAVAimport 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" }
Create a Request.
Request
Filename Get<ComponentName>
Eg: GetPurchaseOrderHeader
Location component/<moduleName>/resource/<ComponentName>/request
Eg: component/logistics/resource/PurchaseOrderHeader/request/GetPurchaseOrderHeaderConforms to QueryRequestable, FunctionRequestable, or both (depending on the usage).
Library Components 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
JAVAimport 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 } } }
Create an API
API
Filename <ComponentName>API
Eg: PurchaseOrderHeaderAPI
Location component/<moduleName>/resource/<ComponentName>/
Eg: component/logistics/resource/PurchaseOrderHeader/PurchaseOrderHeaderAPI
Conforms to Library Components 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
JAVAimport 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 }
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
Library Components 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>
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
Library Components 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>
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
Library Components 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) } }