Skip to content

Support inline single attachments via Attachment type#768

Open
busehalis-sap wants to merge 19 commits intomainfrom
feature/support-single-attachments
Open

Support inline single attachments via Attachment type#768
busehalis-sap wants to merge 19 commits intomainfrom
feature/support-single-attachments

Conversation

@busehalis-sap
Copy link
Copy Markdown
Contributor

What

Adds support for inline (single) attachments using the Attachment type directly on an entity field (e.g. profilePicture: Attachment), in addition to the existing composition-based Composition of many Attachments pattern.

Key Changes

  • Inline attachment detection via @_is_media_data annotation at element level
  • Prefix-based extraction to normalize flattened DB columns (e.g. coverImage_contentIdcontentId)
  • All CRUD + draft handlers extended for inline path (read, create, update, delete, patch, cancel)
  • Malware scan support for inline attachments
  • Bookshop sample updated with inline attachment example
  • Comprehensive unit tests for all new paths

How it works

When an entity has field: Attachment, CDS flattens the Attachment fields into the parent table with a prefix (e.g. coverImage_content, coverImage_contentId). The handlers detect this via the @_is_media_data annotation at element level, extract the prefixed data into normalized Attachments maps, and inject parent entity keys for downstream matching.

@hyperspace-insights
Copy link
Copy Markdown
Contributor

Summary

The following content is AI-generated and provides a summary of the pull request:


Support Inline Single Attachments via Attachment Type

New Feature: Adds support for inline (single) attachments using the Attachment type directly on an entity field (e.g., profileIcon: Attachment), complementing the existing Composition of many Attachments pattern.

Changes

When an entity declares a field as field: Attachment, CDS flattens the Attachment fields into the parent table with a prefix (e.g., coverImage_content, coverImage_contentId). The handlers now detect this via the @_is_media_data annotation at the element level, extract the prefixed data into normalized Attachments maps, and inject parent entity keys for downstream matching.

CDS Model:

  • attachments.cds: Introduces a new type Attachment @(_is_media_data) and makes MediaData extend it, enabling inline usage.
  • attachments-annotations.cds: Annotates Attachment.content with a static Core.MediaType to expose it as Edm.Stream.

Handler Infrastructure:

  • ApplicationHandlerHelper.java: New utility methods for inline attachment detection: getInlineAttachmentFieldNames, getInlineAttachmentPrefix, extractInlineAttachment, isInlineAttachmentContentField, hasInlineAttachmentElements, isDirectMediaEntity. Updated MEDIA_CONTENT_FILTER and condenseAttachments to support both inline and composition-based patterns.
  • BeforeReadItemsModifier.java: Extended to add prefixed contentId, status, and scannedAt fields to SELECT queries for inline attachments.
  • ReadAttachmentsHandler.java: Detects inline prefix during read/after-read processing and uses it for status transitions and malware scan triggering.
  • UpdateAttachmentsHandler.java: associationsAreUnchanged now also checks inline prefixed fields.
  • ReadonlyDataContextEnhancer.java: Handles preserve/restore of readonly fields using prefixed keys for inline attachments.

Modify Events:

  • CreateAttachmentEvent.java: Detects inline prefix, reads mimeType/fileName from prefixed fields, and writes contentId/status/scannedAt back using prefixed keys.
  • MarkAsDeletedAttachmentEvent.java: Clears all prefixed fields (including mimeType, fileName) on deletion for inline attachments.

Draft Handlers:

  • DraftPatchAttachmentsHandler.java: Extracts inline attachment data from flattened DB results and injects parent keys for event matching.
  • DraftCancelAttachmentsHandler.java: contentIdFilter and deepSearchForAttachments updated to detect inline attachment fields.

Malware Scanning:

  • AsyncMalwareScanExecutor, AttachmentMalwareScanner, EndTransactionMalwareScanProvider, EndTransactionMalwareScanRunner: Added Optional<String> inlinePrefix parameter throughout the malware scan pipeline.
  • DefaultAttachmentMalwareScanner.java: All read/update queries now use resolved (prefixed) column names for inline attachments.
  • DefaultAttachmentsServiceHandler.java: Detects inline prefix post-create and passes it to the malware scan provider.

Other:

  • AssociationCascader.java: Recognizes entities with inline attachment elements and adds them to the traversal path.
  • AttachmentsReader.java: Adds inline attachment columns (prefix_contentId, prefix_status) directly to SELECT queries.
  • MediaTypeResolver.java, AttachmentValidationHelper.java: Use findElement (safe) instead of getElement and isDirectMediaEntity for composition-based checks.
  • Registration.java: Updated EndTransactionMalwareScanRunner instantiation to pass Optional.empty() for inlinePrefix.

Bookshop Sample:

  • attachments.cds, fiori-service.cds: Added profileIcon: Attachment inline attachment to the Books entity with UI facet.
  • pom.xml: Updated cds-feature-attachments version to 1.4.0-SNAPSHOT.

Tests:

  • New and extended unit tests covering all new inline paths: read, create, update, delete, patch, cancel, malware scanning, readonly field preservation, and BeforeReadItemsModifier behavior.
  • New ReadonlyDataContextEnhancerTest.java covering both composition-based and inline preserve/restore scenarios.

  • 🔄 Regenerate and Update Summary
  • ✏️ Insert as PR Description (deletes this comment)
  • 🗑️ Delete comment
PR Bot Information

Version: 1.19.3 | 📖 Documentation | 🚨 Create Incident | 💬 Feedback

  • Output Template: Default Template
  • LLM: anthropic--claude-4.6-sonnet
  • Summary Prompt: Default Prompt
  • Event Trigger: pull_request.opened
  • Correlation ID: bbb28610-2bff-11f1-8fd9-1dd0dd2b50a5

💌 Have ideas or want to contribute? Create an issue and share your thoughts with us!
📑 Check out the documentation for more information.
📬 Subscribe to the Hyperspace PR Bot DL to get the latest announcements and pilot features!

Made with ❤️ by Hyperspace.

Copy link
Copy Markdown
Contributor

@hyperspace-insights hyperspace-insights bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR introduces inline single-attachment support via the Attachment type, which is a meaningful extension of the existing composition-based approach. However, there are several substantive correctness issues that need attention before merging: a recurring "first prefix wins" bug across CreateAttachmentEvent, MarkAsDeletedAttachmentEvent, and DefaultAttachmentsServiceHandler that will produce wrong behavior for entities with more than one inline attachment field; an inverted/dead branch in ModifyApplicationHandlerHelper for contentId resolution; missing root-entity key columns in AttachmentsReader when both inline and expand columns are present; and a conflation in ReadAttachmentsHandler.getAttachmentAssociations that incorrectly treats inline-only root entities as direct media association roots. These should be resolved before the feature is considered production-ready.

PR Bot Information

Version: 1.19.3 | 📖 Documentation | 🚨 Create Incident | 💬 Feedback

  • Event Trigger: pull_request.opened
  • Correlation ID: bbb28610-2bff-11f1-8fd9-1dd0dd2b50a5
  • LLM: anthropic--claude-4.6-sonnet

Copy link
Copy Markdown
Contributor

@lisajulia lisajulia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! 👍
Please update the README file as well 📖 - then I'll approve ;)

@busehalis-sap busehalis-sap requested a review from a team as a code owner April 13, 2026 12:38
@busehalis-sap busehalis-sap force-pushed the feature/support-single-attachments branch from 8a97051 to f041e27 Compare April 13, 2026 18:27
busehalis-sap and others added 7 commits April 14, 2026 10:02
…e-attachments

# Conflicts:
#	cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/service/malware/DefaultAttachmentMalwareScanner.java
#	cds-feature-attachments/src/test/java/com/sap/cds/feature/attachments/handler/applicationservice/helper/ReadonlyDataContextEnhancerTest.java
…er mock

The feature branch added an inlinePrefix parameter to
EndTransactionMalwareScanProvider.getChangeSetListener. A test added
on main was still using the 2-arg overload.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants