What Is Chenile Core
chenile-core is the foundational runtime layer of the Chenile ecosystem.
It provides service orchestration, interceptor chaining, context propagation, type transformation, and HTTP integration primitives used by higher-level modules.
Repository path:
/ajapro/chenile-core
Module Map And When To Use Each
From the parent POM, chenile-core contains these modules:
chenile-base: Foundational contracts, response/error models.owiz: Chain/command orchestration engine used by interceptor flows.chenile-core: Core runtime bootstrapping, service/event initialization, interceptor interpolation, context handling.chenile-http: HTTP adapter, controller support, annotation-driven service registration.stm: State transition machine engine.utils: Generic utility components used by runtime and apps.jpa-utils: JPA helper patterns for Chenile services.multi-datasource-utils: Tenant-aware datasource routing.cucumber-utils: Integration testing and BDD utilities.
Typical combinations:
- Plain HTTP service:
chenile-core+chenile-http. - Stateful workflow service: add
stm. - Multi-tenant persistence: add
jpa-utils+multi-datasource-utils. - BDD-heavy service testing: add
cucumber-utils.
Module Deep Dive
chenile-base
Contains common contracts used across modules, including base response and error model definitions. Use this when you need shared framework abstractions without bringing in full HTTP/runtime integrations.
owiz
Provides the chain/command orchestration engine used by Chenile runtime flows. This powers composition patterns such as sequential execution, interception, and context-aware command pipelines.
chenile-core module
Bootstraps Chenile runtime configuration, service/event initialization, context container wiring, and orchestrator setup. If you are extending core processing behavior, this is the primary module to inspect.
chenile-http
Adds HTTP endpoint integration through @ChenileController, ControllerSupport, URL mappings, and controller-to-operation initialization.
Use this for Spring MVC based service exposure.
stm
State Transition Machine support for stateful service flows and event-driven lifecycle transitions. Use this when service behavior depends on explicit states and allowed transitions.
utils
General utility helpers shared by framework and service implementations. Useful for cross-cutting helper functionality that is runtime-agnostic.
jpa-utils
Persistence helpers and patterns for JPA-backed Chenile services. Use this with Spring Data JPA services to reduce repetitive persistence plumbing.
multi-datasource-utils
Tenant-aware datasource routing support built around ContextContainer.getTenant().
Use this for multi-tenant deployments requiring per-tenant datasource selection.
Detailed setup and usage: Multi Datasource Utils Guide
cucumber-utils
Utilities for BDD and integration testing with Cucumber in Chenile services. Use this in test modules for standard service-invocation test patterns. Detailed setup and usage: Cucumber Utils Guide
custom id generator
Chenile supports pluggable ID generation strategies used by BaseJpaEntity.
Detailed setup and usage: Custom ID Generator Guide
Runtime Pipeline (Interceptor Highway)
The default execution flow is defined in:
chenile-core/src/main/resources/org/chenile/core/chenile-core.xml
Key stages in order:
- Header validation/copy.
- Pre-processor interpolation.
- Body type selection.
- Payload transformation.
- Service reference resolution.
- Post-processor interpolation.
- Operation/service-specific interceptors.
- Service invocation.
- Exception and response handling.
This means cross-cutting behavior should usually be introduced as pre/post/operation/service interceptors, not inside each service method.
Bootstrapping Properties (chenile.properties)
ChenileCoreConfiguration reads startup settings from chenile.properties.
A practical baseline (from sample configurations):
chenile.service.json.package=classpath*:org/chenile/samples/**/service/*.json,classpath*:org/chenile/**/service/*.json
chenile.event.json.package=classpath*:org/chenile/samples/**/event/*.json
chenile.interceptors.path=org/chenile/core/chenile-core.xml
chenile.module.name=m1
chenile.pre.processors=populateContextContainer
chenile.post.processors=
Important keys:
chenile.module.name: Module identity in Chenile configuration.chenile.service.json.package: JSON service definition scan path.chenile.event.json.package: Event definition scan path.chenile.interceptors.path: Interceptor chain XML.chenile.pre.processors/chenile.post.processors: Global interceptor hooks.
HTTP Integration Pattern (Annotation-Driven)
chenile-http provides @ChenileController + ControllerSupport.
At app startup, AnnotationChenileServiceInitializer scans controllers with @ChenileController and maps Spring route methods into Chenile operation definitions.
Example pattern:
@RestController
@ChenileController(value = "s1Service", serviceName = "_s1Service_", healthCheckerName = "s1HealthChecker")
public class S1Controller extends ControllerSupport {
@PostMapping("/s1/op1")
public ResponseEntity<GenericResponse<S1Entity>> op1(HttpServletRequest request,
@RequestBody S1Entity entity) {
return process("op1", request, entity);
}
}
Notes:
process(...)buildsChenileExchange, sets headers/body, and dispatches throughChenileEntryPoint.- Returned HTTP status and warning headers are populated from exchange metadata.
- Controller method name can be used as operation name via
process(request, args...), or passed explicitly.
Advanced Body-Type Mapping
When controller payload type differs from service method signature, use @ChenileParamType.
When body type depends on runtime input (for example path variable or event), use @BodyTypeSelector.
Pattern:
@PostMapping("/add-capacity-generic/{type}")
@BodyTypeSelector({"roomVehicleBodyTypeSelector", "subclassBodyTypeSelector"})
public ResponseEntity<GenericResponse<Capacity>> addCapacityGeneric(
HttpServletRequest request,
@PathVariable("type") String type,
@ChenileParamType(Object.class) @RequestBody String object) {
return process(request, type, object);
}
JSON Service Definition Model
You can define services through JSON files scanned by chenile.service.json.package.
A typical operation contains:
nameurlhttpMethodparamswithBODY,HEADER, orHEADERS- optional
interceptorComponentNames - optional
bodyTypeSelectorComponentNames
This model is useful when you want explicit contract metadata and/or non-annotation service bootstrapping.
Context And Header Model
ContextContainer is a thread-local request context populated from incoming headers.
Frequently used header keys are centralized in HeaderUtils, including:
x-chenile-tenant-idx-chenile-uidx-correlation-idx-request-idx-chenile-trajectory-id
Guidelines:
- Use
ContextContainerfor transport metadata (tenant/user/correlation), not business payload. - Do not rely on it in reactive/non-thread-bound execution flows.
- Clear or isolate context for async/background execution boundaries.
Specialized Guides
Build, Versioning, Release Basics
- Version source file:
chenile-core-version.txt - Current local value:
2.1.11
Build locally:
cd /ajapro/chenile-core
make build
Equivalent Maven command:
mvn -Drevision=$(cat chenile-core-version.txt) install
Common Make targets:
make cleanmake javadocmake test-javadocmake prepare-deploymake deploy
Common Pitfalls
@ChenileController(serviceName=...)not matching bean name of service implementation. Startup succeeds partially but runtime resolution fails for that service.- Missing/incorrect
chenile.interceptors.path. Requests may bypass expected processing chain. - Incorrect scan paths for
chenile.service.json.package/chenile.event.json.package. Services/events silently not initialized. - Overusing context for domain data. Creates hard-to-test coupling and cross-request leakage risk.
Recommended Dev Flow For Core Changes
- Implement/change in relevant module (
chenile-core,chenile-http,stm, etc.). - Run module build and tests.
- Validate behavior in
chenile-sampleswith a representative service. - Update docs in this Developer Docs section.