7

The question is fairly self-explanatory, but to add a little background, here's the scenario that has made me ask. First a (very basic) SSCCE:

public void createAttachments(List<Account> accounts) {
    Map<Attachment, Account> attachmentAccountMap = getMap(accounts);

    for (Attachment attachment : attachmentAccountMap.keySet()) {
        System.debug(attachment.Name);

        Account account = attachmentAccountMap.get(attachment);
        System.assertNotEquals(null, account);
    }
}

private Map<Attachment, Account> getMap(List<Account> accounts) {
    Map<Attachment, Account> attachmentAccountMap = new Map<Attachment, Account>();
    List<Attachment> attachments = new List<Attachment>();

    for (Account account : accounts) {
        Attachment attachment = new Attachment();
        attachment.Name = 'test';
        attachments.add(attachment);

        attachmentAccountMap.put(attachment, account);
    }

    insert attachments;

    return attachmentAccountMap;
}

The problem I had seemed to be a race condition at the System.assertNotEquals() line - on most occasions the assertion passed, and the account was not null, but sometimes it would fail. Increasing the logging seemed to cause it to fail consistently, and reducing it seemed to make it pass consistently, which is why I think it was a race condition.

There are 2 relatively simple triggers on Attachment (before and after insert), which (I don't think) should affect my attachments, but I'm not certain.

What seems to be happening is that somewhere between the start of the for loop in createAttachments(), where attachment is assigned as the first key in the map, and the assertion, the attachment in the map is changed (maybe because the ID gets set?), so when we try to use it to retrieve an account from the map, the two objects are no longer equal, and the get returns null.

Does anyone know if this sounds right???

I seem to have managed to resolve it for my case by just swapping the objects in the map, so making it Map<Account, Attachment>, because I'm really just using the map to keep the two objects associated - the better solution would probably have been to make a new class with the two objects, but I didn't do that!

2
  • 2
    We're gonna need to see those other triggers... ;) Feb 5, 2014 at 17:48
  • Unfortunately the triggers are pretty huge, or at least, they potentially call off into other stuff, depending on a bunch of if statements that I don't want to work through right now (not my code :)). My workaround is OK for now, but when I get a chance I'll do some more digging and maybe come back here with my findings :) Feb 5, 2014 at 21:43

1 Answer 1

5

Triggers run synchronously. They can call future methods however which run asynchronously.

In this case...the map stands out to me. A map of <Attachment, Account> is interesting, because its not clear what defines a unique attachment to me. Is it the memory location, the id, or maybe all fields being equal? I wouldn't be suprised if in getMap you are overwriting elements in your map because of this ambiguity, and end up getting some nulls. Typically, someone would use a map of <Id, Account> for this kind of thing.

1
  • Thanks for this; I can't see that they are calling out to any future methods, but as I've mentioned above, I haven't worked all the way through the various code paths - it's pretty maze-like... :S On your second point, I totally get your point, and that's why I mention that I regret not making it a new class with Attachment and Account members, but I don't think elements are getting overwritten just because the outcome isn't consistent, even though the input is (from a unit test). Feb 5, 2014 at 21:50

You must log in to answer this question.

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