1

In an apex funtion - getAttachments() - i'm requesting some attachments and their body:

Set<Id> attIds = new Set<Id>{id1, id2};
List<Attachment> attLst = [Select Name, Body From Attachment Where id in :attIds];

When calling this function from standard apex context i'm receiving the correct data. When calling this function from a rest context (let said that the rest WS calls a global doPost() function, and this function calls our getAttachments() function, I'm receiving the correct attachments name, but the body of the second attachment is the same body as the one of the first attachment.

code:

class A{
 public static List<Attachments> getAttachments(Set<Id> ids){
  List<Attachments> attLst = [Select Name, Body From Attachment Where id in :ids];
 }
}

@RestResource(urlMapping='/merge2')
global class WS1{
 @HttpPost
 global static doPost(List<Id> idLst){
  Set<Id> ids = new Set<Id>(idLst);
  List<Attachment> attLst = A.getAttchments(ids);
 }
}    

When calling A.getAttachments I'm receiving the espected Attachments. When calling A.getAttachments from The WS, all the attachment's body are the same.

Any Idea? Thanks,

Ilan

2

3 Answers 3

3

I know this is four months old, but I just ran into this myself, and may have a reason as to why this occurs. There is a very small blurb at the bottom of this page on the developers site :

You can access all of the fields using a query() call. However, you can't receive the Body field for multiple records in a single query() call. If your query returns the Body field, your client application must ensure that only one row with one Attachment is returned; otherwise, an error occurs. A more effective approach is to return IDs (but not Attachment records in the Body field) from a query() call and then pass them into retrieve() calls that return the Body field.

I've seen two different permutations of this "side effect"; the first is the behavior where each subsequent Attachment record after the first will contain the Body of the first, the second is more explicit, in that only a single record is returned, even though there's clearly more than one attachment applied to the Case.

To fix this, I'm basically following the suggestion of, getting the Id's of the attachments first, then iterating over those separately to build the full object with the proper Body content.

1

While this doesn't make any sense, this also appears to be fixed by adding the Id as a Select field in the Query. IE:

List attLst = [Select Id, Name, Body From Attachment Where id in :attIds];

When running this in Workbench it now will return the body data correctly for each entry in the list. Here is my code to reproduce this issue. Changing only the Select to include the Id field will fix this case as well.

@RestResource(urlMapping='/TestAttachmentIssue/*')
global with sharing class TestAttachmentIssue {
    @httpGet
    global static void doGet()
    {
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;

        res.responseBody = Blob.valueOf(JSON.serialize(getAttachmentData()));
    }

    public static Map<String, String> getAttachmentData()
    {
        Savepoint savePoint = Database.setSavepoint();
        Contact cont = new Contact(LastName='Smith');
        insert cont;

        List<Id> contIds = new List<Id>{ cont.Id };

        insert new Attachment(ParentId=cont.Id, Name='A', Body=Blob.valueOf('A'));
        insert new Attachment(ParentId=cont.Id, Name='B', Body=Blob.valueOf('B'));
        insert new Attachment(ParentId=cont.Id, Name='C', Body=Blob.valueOf('C'));
        insert new Attachment(ParentId=cont.Id, Name='D', Body=Blob.valueOf('D'));
        insert new Attachment(ParentId=cont.Id, Name='E', Body=Blob.valueOf('E'));
        insert new Attachment(ParentId=cont.Id, Name='F', Body=Blob.valueOf('F'));

        Map<String, String> attachmentData = new Map<String, String>();

        for (Attachment att : [Select Name, Body from Attachment where ParentId in :contIds ])
        {
            attachmentData.put(att.Name, att.Body.toString());
        }

        System.debug(LoggingLevel.ERROR, JSON.serialize(attachmentData));

        Database.rollback(savePoint);

        return attachmentData;
    }
}
0

I have had the same problem and concluded it is a Salesforce bug. In my case it was only a few attachments so I now query them one by one as a work-around.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .