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:
- Creating a New CC6 Component | Entity
- Creating a New CC6 Component | Request
- Creating a New CC6 Component | API
- Creating a New CC6 Component | Dao
- Creating a New CC6 Component | Service
- Creating a New CC6 Component | Worker
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
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)" } }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.
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) ]) } }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.
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> }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:JavaScript/// A store that defines how to perform CRUD operations on a PurchaseOrderHeader /// object public protocol PurchaseOrderHeaderDao: DaoProtocol where Entity: PurchaseOrderHeader {}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.Java/// Service that defines how to interact with a PurchaseOrderHeader public protocol PurchaseOrderHeaderService: ServiceProtocol where Entity: PurchaseOrderHeader {}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.JavaScript/// 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) } }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) } }