diff --git a/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMCreateAttachmentsHandler.java b/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMCreateAttachmentsHandler.java index 690210ab..84a5c73a 100644 --- a/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMCreateAttachmentsHandler.java +++ b/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMCreateAttachmentsHandler.java @@ -60,6 +60,7 @@ public SDMCreateAttachmentsHandler( @HandlerOrder(HandlerOrder.DEFAULT) public void processBefore(CdsCreateEventContext context, List data) throws IOException { logger.info("Target Entity : " + context.getTarget().getQualifiedName()); + logger.debug("CDS Data attachments : " + data); for (CdsData entityData : data) { Map> attachmentCompositionDetails = diff --git a/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMReadAttachmentsHandler.java b/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMReadAttachmentsHandler.java index 14914057..aa14eb73 100644 --- a/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMReadAttachmentsHandler.java +++ b/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMReadAttachmentsHandler.java @@ -114,67 +114,77 @@ private void setErrorMessagesInCache(CdsReadEventContext context) { @HandlerOrder(HandlerOrder.EARLY + 500) public void processBefore(CdsReadEventContext context) throws IOException { String repositoryId = SDMConstants.REPOSITORY_ID; + if (repositoryId == null) { + return; + } + setErrorMessagesInCache(context); if (context.getTarget().getAnnotationValue(SDMConstants.ANNOTATION_IS_MEDIA_DATA, false)) { try { // update the uploadStatus of all blank attachments with success this is for existing // attachments - RepoValue repoValue = - sdmService.checkRepositoryType(repositoryId, context.getUserInfo().getTenant()); - Optional attachmentDraftEntity = - context.getModel().findEntity(context.getTarget().getQualifiedName() + "_drafts"); - String upIdKey = "", upID = ""; - if (attachmentDraftEntity.isPresent()) { - upIdKey = SDMUtils.getUpIdKey(attachmentDraftEntity.get()); - CqnSelect select = (CqnSelect) context.get("cqn"); - upID = SDMUtils.fetchUPIDFromCQN(select, attachmentDraftEntity.get()); - - if (!repoValue.getIsAsyncVirusScanEnabled()) { - - dbQuery.updateInProgressUploadStatusToSuccess( - attachmentDraftEntity.get(), persistenceService, upID, upIdKey); - } - if (repoValue.getIsAsyncVirusScanEnabled()) { - processVirusScanInProgressAttachments(context, upID, upIdKey); + RepoValue repoValue = checkRepositoryTypeWithFallback(repositoryId, context); + + // Only process virus scan logic if repository info is available + if (repoValue != null) { + Optional attachmentDraftEntity = + context.getModel().findEntity(context.getTarget().getQualifiedName() + "_drafts"); + String upIdKey = "", upID = ""; + if (attachmentDraftEntity.isPresent()) { + upIdKey = SDMUtils.getUpIdKey(attachmentDraftEntity.get()); + CqnSelect select = (CqnSelect) context.get("cqn"); + upID = SDMUtils.fetchUPIDFromCQN(select, attachmentDraftEntity.get()); + + if (!repoValue.getIsAsyncVirusScanEnabled()) { + + dbQuery.updateInProgressUploadStatusToSuccess( + attachmentDraftEntity.get(), persistenceService, upID, upIdKey); + } + if (repoValue.getIsAsyncVirusScanEnabled()) { + processVirusScanInProgressAttachments(context, upID, upIdKey); + } } - } - // Get attachment associations to handle deep reads with expand - CdsModel cdsModel = context.getModel(); - List fieldNames = - getAttachmentAssociations(cdsModel, context.getTarget(), "", new ArrayList<>()); - - // Create a combined modifier that handles both expand scenarios and repositoryId filter - final SDMBeforeReadItemsModifier itemsModifier = new SDMBeforeReadItemsModifier(fieldNames); - final Predicate repositoryFilter = - CQL.or(CQL.get("repositoryId").eq(repositoryId), CQL.get("repositoryId").isNull()); - - CqnSelect modifiedCqn = - CQL.copy( - context.getCqn(), - new Modifier() { - @SuppressWarnings({"rawtypes", "unchecked"}) - @Override - public List items(List items) { - // Always handle items for expand scenarios - return itemsModifier.items(items); - } - - @Override - public Predicate where(Predicate where) { - // Always apply repositoryId filter for all reads - if (where == null) { - return repositoryFilter; + // Get attachment associations to handle deep reads with expand + CdsModel cdsModel = context.getModel(); + List fieldNames = + getAttachmentAssociations(cdsModel, context.getTarget(), "", new ArrayList<>()); + + // Create a combined modifier that handles both expand scenarios and repositoryId filter + final SDMBeforeReadItemsModifier itemsModifier = + new SDMBeforeReadItemsModifier(fieldNames); + final Predicate repositoryFilter = + CQL.or(CQL.get("repositoryId").eq(repositoryId), CQL.get("repositoryId").isNull()); + + CqnSelect modifiedCqn = + CQL.copy( + context.getCqn(), + new Modifier() { + @SuppressWarnings({"rawtypes", "unchecked"}) + @Override + public List items(List items) { + // Always handle items for expand scenarios + return itemsModifier.items(items); + } + + @Override + public Predicate where(Predicate where) { + // Always apply repositoryId filter for all reads + if (where == null) { + return repositoryFilter; + } + return CQL.and(where, repositoryFilter); } - return CQL.and(where, repositoryFilter); - } - }); - setErrorMessagesInCache(context); - context.setCqn(modifiedCqn); + }); + context.setCqn(modifiedCqn); + } else { + context.setCqn(context.getCqn()); + } } catch (Exception e) { logger.error("Error in SDMReadAttachmentsHandler.processBefore: {}", e.getMessage(), e); // Re-throw to maintain error handling behavior throw e; } + } else { context.setCqn(context.getCqn()); } @@ -340,4 +350,24 @@ private void processAttachmentVirusScanStatus( e.getMessage()); } } + + /** + * Checks the repository type with fallback handling. Returns null if the check fails, allowing + * the caller to proceed with limited functionality. + * + * @param repositoryId the repository ID to check + * @param context the CDS read event context containing user information + * @return the RepoValue if successful, null otherwise + */ + private RepoValue checkRepositoryTypeWithFallback( + String repositoryId, CdsReadEventContext context) { + try { + return sdmService.checkRepositoryType(repositoryId, context.getUserInfo().getTenant()); + } catch (Exception e) { + logger.warn( + "Failed to check repository type, proceeding without repository info: {}", + e.getMessage()); + return null; + } + } } diff --git a/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/helper/AttachmentsHandlerUtils.java b/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/helper/AttachmentsHandlerUtils.java index 5fe99633..d9997cba 100644 --- a/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/helper/AttachmentsHandlerUtils.java +++ b/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/helper/AttachmentsHandlerUtils.java @@ -201,13 +201,13 @@ public static List> fetchAttachments( String targetEntity, Map entity, String attachmentCompositionName) { String[] targetEntityPath = targetEntity.split("\\."); targetEntity = targetEntityPath[targetEntityPath.length - 1]; - entity = AttachmentsHandlerUtils.wrapEntityWithParent(entity, targetEntity.toLowerCase()); + entity = AttachmentsHandlerUtils.wrapEntityWithParent(entity, targetEntity); String[] compositionParts = attachmentCompositionName.split("\\."); String attachmentKeyFromComposition = compositionParts[compositionParts.length - 1]; // Last part (e.g., "attachments") String parentKeyFromComposition = compositionParts.length >= 2 - ? compositionParts[compositionParts.length - 2].toLowerCase() + ? compositionParts[compositionParts.length - 2] : null; // Second last part (e.g., "chapters") // Find all attachment arrays in the nested entity structure @@ -445,12 +445,11 @@ public static Map getAttachmentParentTitles( String[] targetEntityPath = targetEntity.split("\\."); String entityName = targetEntityPath[targetEntityPath.length - 1]; - Map wrappedEntity = wrapEntityWithParent(entity, entityName.toLowerCase()); + Map wrappedEntity = wrapEntityWithParent(entity, entityName); for (Map.Entry compositionEntry : compositionPathMapping.entrySet()) { String compositionPath = compositionEntry.getValue(); - String parentTitle = - findParentTitle(wrappedEntity, compositionPath, entityName.toLowerCase()); + String parentTitle = findParentTitle(wrappedEntity, compositionPath, entityName); if (parentTitle != null) { parentTitles.put(compositionPath, parentTitle); } diff --git a/sdm/src/main/java/com/sap/cds/sdm/service/SDMServiceImpl.java b/sdm/src/main/java/com/sap/cds/sdm/service/SDMServiceImpl.java index defb4943..56a37ce6 100644 --- a/sdm/src/main/java/com/sap/cds/sdm/service/SDMServiceImpl.java +++ b/sdm/src/main/java/com/sap/cds/sdm/service/SDMServiceImpl.java @@ -581,7 +581,9 @@ public JSONObject getRepositoryInfo(SDMCredentials sdmCredentials) { String responseString = EntityUtils.toString(response.getEntity()); return new JSONObject(responseString); } catch (IOException e) { - throw new ServiceException(SDMUtils.getErrorMessage("REPOSITORY_ERROR")); + throw new ServiceException(SDMUtils.getErrorMessage("REPOSITORY_ERROR"), e); + } catch (Exception e) { + throw new ServiceException(SDMUtils.getErrorMessage("REPOSITORY_ERROR"), e); } }