CAP Java plugin providing out-of-the-box attachment storage and handling via the Attachments CDS aspect.
- Think before coding. Read the relevant source files before proposing changes. Understand the handler chain, event flow, and CDS model before touching anything.
- Simplicity first. Follow existing patterns exactly. No new abstractions, helpers, or "improvements" beyond the task.
- Surgical changes. Change only what is needed. Don't refactor neighbors, add comments to untouched code, or introduce feature flags.
- Goal-driven execution. Every edit must serve the stated task. If unsure, ask.
cds-feature-attachments/ # Core plugin (handlers, services, CDS model)
storage-targets/
cds-feature-attachments-fs/ # File system storage (dev only)
cds-feature-attachments-oss/ # Object store (AWS S3, Azure, GCS)
integration-tests/ # Spring Boot integration tests
generic/ # Default storage tests
mtx-local/ # Multi-tenancy tests
oss/ # Object store tests
samples/bookshop/ # Sample CAP Java app
Root package: com.sap.cds.feature.attachments
Java 17+ and Maven 3.6.3+ required.
mvn clean install # Full build with tests
mvn clean install -DskipTests # Build only
mvn test # Unit tests
mvn verify # Unit + integration tests
mvn test -Dtest=FooTest # Single test class
mvn test -Dtest=FooTest#barMethod # Single test method
mvn spotless:apply # Fix formatting
mvn verify -Platest-test-version # Test against latest CAP JavaNote: mvn clean compile or mvn clean install can occasionally fail due to a file lock. If this happens, run mvn clean and mvn compile/mvn install as separate commands, or just drop the clean.
- Formatter: Google Java Format via Spotless. Run
mvn spotless:applybefore committing. - License header required on every Java file:
/* * © YEAR SAP SE or an SAP affiliate company and cds-feature-attachments contributors. */
- Imports: static first, then non-static, both alphabetical (handled by Spotless).
Handlers are CAP event handlers registered for all services of a given type.
ApplicationService handlers (CRUD on attachment entities):
CreateAttachmentsHandler/UpdateAttachmentsHandler/DeleteAttachmentsHandler/ReadAttachmentsHandler
DraftService handlers (draft lifecycle):
DraftActiveAttachmentsHandler/DraftPatchAttachmentsHandler/DraftCancelAttachmentsHandler
Handler registration pattern:
@ServiceName(value = "*", type = ApplicationService.class)
public class FooHandler implements EventHandler {
@Before @HandlerOrder(HandlerOrder.EARLY)
void processBefore(CdsXxxEventContext context) { ... }
}AttachmentService- interface defining events: CREATE, READ, MARK_AS_DELETED, RESTOREDefaultAttachmentsServiceHandler- default on-handler (stores in DB)- Malware scanning in
service/malware/(optional, via SAP Malware Scanning Service)
ModifyAttachmentEventFactory selects the right strategy per attachment: CreateAttachmentEvent, UpdateAttachmentEvent, MarkAsDeletedAttachmentEvent, or DoNothingAttachmentEvent.
Registration implements CdsRuntimeConfiguration and wires everything: services, handlers, malware scanner, outbox, CSV paths.
Defined in cds-feature-attachments/src/main/resources/cds/com.sap.cds/cds-feature-attachments/:
attachments.cds-sap.attachments.Attachmentsaspect,MediaDataaspect,StatusCodeenum,ScanStatesentity- Generated CDS4J classes:
com.sap.cds.feature.attachments.generated
| Pattern | Where |
|---|---|
| Constructor null-check | requireNonNull(param, "param must not be null") in every constructor |
| Class-under-test var | cut in all unit tests |
| Logging | private static final Logger logger = LoggerFactory.getLogger(Foo.class) |
| Assertions | AssertJ (assertThat(...)) preferred over JUnit assertions |
| Mocking | Mockito; tests follow Arrange/Act/Assert |
| Error handling | throw new ServiceException(ErrorStatuses.BAD_REQUEST, msg) |
| Outbox | Persistent outbox for delete operations (reliability) |
| Thread-local | ThreadLocalDataStorage passes draft activation context |
| Type | Convention | Example |
|---|---|---|
| Handler | *Handler.java |
ReadAttachmentsHandler |
| Unit test | *Test.java |
ReadAttachmentsHandlerTest |
| Integration test | *IT.java |
AWSClientIT |
| Event context | *EventContext.java |
AttachmentReadEventContext |
All enforced in CI:
- JaCoCo: 95% minimum (instruction, branch, complexity), 0 missed classes
- Mutation testing (Pitest): 90% aggregated threshold on
handler.*andservice.* - SpotBugs: max effort, includes tests
- PMD: SAP Cloud SDK rules, excludes generated code and tests
- Spotless: Google Java Format check
- Use
cds-mcptool to search CDS model definitions before building queries or modifying models. - Use
cds-mcpto search CAP documentation before using CAP APIs. - Generated CDS4J classes are in
com.sap.cds.feature.attachments.generated-- do not hand-edit.