Services and operations
Services group callable business operations. They are distinct from resources and resource methods: an operation can declare a typed result, while a resource method can declare HTTP-oriented response codes and representations.
1. Complete syntax example
package com.example.customer
import org.joinedworkz.facilities.common.base
platform Base
type Customer {
id**: Id
name*: Name
}
type SearchCriteria {
name: Name
}
abstract service BaseCustomerService with Customer {
find(id*: Id): Customer
}
service CustomerService with Customer
uses SearchCriteria
extends BaseCustomerService {
search(criteria*: SearchCriteria, limit: Integer): Customer[]
findActive(id*: Id): Customer
augments BaseCustomerService.find
uses SearchCriteria
}The snippet demonstrates every service-header relationship. Its generator meaning still depends on the selected platform.
2. Service declaration
[description] [abstract] service [<stereotypes>] Name
[with MainType]
[uses TypeOrServiceOrComponent, ...]
[property ...]
[extends BaseService] {
operation ...
}withassociates one complex type as the service's main type.usesdeclares dependencies on types, services, or components.extendsreferences one base service.- Properties occur before
extendsin the concrete syntax. - Descriptions, stereotypes, and
abstractuse the common declaration notation.
with supplies the field scope for field-based parameters, and uses is represented as a dependency in the canonical Core Model. The grammar accepts abstract and extends, but JoinedWorkz does not transfer those two service attributes into the canonical Core Model. Do not rely on service abstraction or inheritance for generated output.
3. Operation declaration
An operation is written directly by name; there is no operation keyword:
[description] [abstract] [<stereotypes>] name(parameters)
[: ResultType [cardinality]]
[augments BaseOperation]
[uses TypeOrServiceOrComponent, ...]
[property ...]
[statement ...]Documentation immediately before the operation belongs to that operation. Use the platform-independent documentation syntax; the selected facility decides which summaries, descriptions and examples are emitted into target artifacts.
Examples:
package com.example.calculation
import org.joinedworkz.facilities.common.base
platform Base
type Invoice {
id**: Id
total*: Decimal
}
service InvoiceService with Invoice {
find(id*: Id): Invoice
search(maximum: Decimal): Invoice[]
calculate(total*: Decimal): Decimal => total;;
}id*: Idis a mandatory parameter.maximum: Decimalhas no explicit mandatory marker.: Invoiceis a single typed result.: Invoice[]is a result with0..*cardinality.augmentsreferences another operation.useshas the same dependency target kinds as service-leveluses.- An operation statement starts with
=>and ends with;;. CMN transfers its normalized body as opaque text; only a supporting cartridge can assign executable meaning to it.
4. Operation statements and augmentation
An operation can contain one or more statement bodies. A body without a name is written directly after the operation declaration:
package org.example.reporting
type Report {
content: String
}
service ReportService {
render(): Report =>
OPAQUE REPORT BODY;;
}A name before => identifies a statement part:
package org.example.reporting
type Report {
content: String
}
service ReportService {
renderOpenItems(): Report
criteria => STATUS = OPEN;;
ordering => CREATED_AT DESC;;
}=> and ;; delimit the body. They are not part of the value transferred to the Core Model. CMN also removes structural indentation from multiline bodies. The remaining content is not parsed as another CMN expression language.
The augments relationship connects an operation to a base operation. This allows a facility to interpret the base statement and the named statement parts together:
package org.example.reporting
import org.joinedworkz.facilities.common.base
platform Base
type Report {
content: String
}
service ReportService {
reportTemplate(): Report =>
OPAQUE REPORT BODY;;
openItemsReport(): Report augments reportTemplate
criteria => STATUS = OPEN;;
}At the CMN and Core Model level this means only that:
reportTemplateowns one unnamed statement body;openItemsReportreferencesreportTemplateas its base operation; andopenItemsReportowns one named statement part,criteria.
augments does not define a universal text-merge algorithm and does not copy the base operation's parameters, result, properties, or stereotypes into the derived declaration. A facility that supports executable statements defines the statement language, composition rules, generated artifacts and runtime contract. For the stable SpringBoot platform, see Repository statements and composition.
Operation statement parts are distinct from component fragments included with ... Fragment. They use different grammar elements and have separate facility contracts.
5. Parameters
An operation parameter has one of two forms:
package com.example.parameters
import org.joinedworkz.facilities.common.base
platform Base
type Customer {
customerId**: Id
}
service CustomerService with Customer {
byExplicitType(id*: Id): Customer
byField(customerId): Customer
byFieldWithOverride(id ..customerId as String): Customer
mergeLabels(labels: String[String]): String[String]
}name*: Typedeclares a parameter and its type.- A field reference such as
customerIdreuses the field definition. id ..customerIdgives the reused field a parameter-local name.as Stringoverrides the field's simple type for this parameter.labels: String[String]declares a dictionary parameter withStringvalues andStringkeys. The result uses the same dictionary cardinality.
References are resolved in model context. A complete project build performs the required cross-file linking and semantic validation. Parameter cardinality is CMN syntax; a selected facility decides which parameter shapes it can expose in generated code or over a transport.
6. Result cardinality
Operation results use the same cardinality notation as fields:
package com.example.results
import org.joinedworkz.facilities.common.base
platform Base
type Result {
value: String
}
service ResultService {
optionalResult(): Result
requiredResult(): Result*
boundedResults(): Result[1..10]
resultsByName(): Result[String]
}See Complex types and fields for the exact bounds and the ValueType[KeyType] orientation. No : means that the operation declares no typed result.
7. Core syntax and facility semantics
The service, operation, parameter, result, with, uses, extends, and augments slots are CMN syntax. Stereotype names, properties, executable statement languages, and generated contracts are profile/facility concerns.
There is currently no canonical stable public example dedicated to service generation. Consequently, this page documents the CMN syntax and Core Model relationships, but makes no general promise about generated service code. Resource-driven SpringBoot APIs are covered in Build a CRUD backend.
