You need to sign in to do that
Don't have an account?

bug: @future methods run in user, not system, context
Apex code should run in system context (except when running executeAnonymous, or using "with sharing", or testing with "runAs").
Specifically, @future calls should run in system context (or, at least, in the same context as their caller).
Instead, they are running in the user context.
Here's a quick example of an api method that queries for a private contact belonging to 'user1':
If I call this api method as 'user1', everything works fine (here's the debug output, from the non-future call at line 2):
If I call it as 'user2', who is a standard user & thus isn't normally able to see the private contact, the line 2 call to queryPrivateContact works fine (because the code is running in system context). As a result, the debug output is what you would expect:
However, an exception is thrown when the @future method queryLater runs, and the developer org gets an an error email:
This shows that the @future method is running in the user context, rather than the system context. As a result, the SOQL in "queryPrivateContact" returns empty, and thus we get the "List has no rows for assignment" error.
Message Edited by jhart on 11-17-2008 04:32 PM
Message Edited by jhart on 11-17-2008 04:32 PM
Specifically, @future calls should run in system context (or, at least, in the same context as their caller).
Instead, they are running in the user context.
Here's a quick example of an api method that queries for a private contact belonging to 'user1':
Code:
1 Webservice static void now_and_later() { 2 queryPrivateContact(); 3 queryLater(); 4 } 5 public static void queryPrivateContact() { 6 Contact c = [select Name from Contact where Id = '0037000000cWgTXAA0']; 7 System.debug(c); 8 } 9 @future static void queryLater() { 10 queryPrivateContact(); 11 }
If I call this api method as 'user1', everything works fine (here's the debug output, from the non-future call at line 2):
Code:
$ perl api.pl -u user1 -------------------------------------------------------------------------------- Calling 'i.aa_api.now_and_later' as user1 -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- DEBUG LOG: 20081118002023.813:Class.i.aa_api.queryPrivateContact: line 7, column 9: Contact:{Name=Carrie Sloan, Id=0037000000cWgTXAA0} --------------------------------------------------------------------------------
Code:
$ perl api.pl -u user2 -------------------------------------------------------------------------------- Calling 'i.aa_api.now_and_later' as user2 -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- DEBUG LOG: 20081118002029.727:Class.i.aa_api.queryPrivateContact: line 7, column 9: Contact:{Name=Carrie Sloan, Id=0037000000cWgTXAA0} --------------------------------------------------------------------------------
However, an exception is thrown when the @future method queryLater runs, and the developer org gets an an error email:
Code:
Apex script unhandled exception by user/organization: 00570000001IdET/00D70000000Jqpv Failed to invoke future method 'static void queryLater()' Debug Log: System.QueryException: List has no rows for assignment to SObject Class.i.aa_api.queryPrivateContact: line 6, column 21 Class.i.aa_api.queryLater: line 10, column 9
Message Edited by jhart on 11-17-2008 04:32 PM
Message Edited by jhart on 11-17-2008 04:32 PM
What happens if I declare the class having @future method as without sharing. Will it run in System mode then?
No - none of the sample code above is declared with sharing.
That's why this is a bug. Any @future method runs in the wrong context.
Not true. I tested & verified this a similar problem I had today.
I needed to give normal users the ability to delete Contact record to which they only have Edit permissions granted via their Territory access rules. (The user does not own the Contact record). By unchecking a custom Active checkbox field in the Contact record, an after update trigger fires which schedules an @future method to archive and then delete the inactive Contact record.
Declaring the @future Contact deletion method in a class "with sharing" executes the @future method in User context. When an unprivileged User marks the Contact record Inactive, the @future method fails with an INSUFFICIENT_ACCESS_OR_READONLY error.
Declaring the @future Contact deletion method in a class without the sharing attribute executes the @future method in system context (modify all data). When an unprivileged User marks the Contact record Inactive, the @future method succeeds and the Contact record is deleted.
ddkpe1,
I haven't had time to regress this issue to see if it's been fixed, but your example does not show that it has been fixed.
Your trigger is executing in system context. I would therefore expect any @future calls invoked from that trigger to run in @future context as well (unless "with sharing" is declared).
The problem is if the @future caller is running in user context, then the @future method *also* runs in user context even if it's not declared "with sharing". Your example does not test this path.
thanks,
john
Hello @jhart!
I was playing recently with @future and was just wondering if you got a response from SFDC guys?
Thank you,
Adi
Hi Adrian,
The bug report I submitted got deleted during one of their upgrades of the partner portal, so I can't actually find out their response.
What I am pretty sure of, though, is that they did not fix it at the time. I don't know if it even made it out of the morass of Tier1 partner support.
easy enough for you to ascertain, though.
I have a batch job which is updating the records, init i have one future method.Now i am running the batch from execute anonymous. But in the debug log future method is running in API user context. its showing sumitted by that user.
Could anyone please explain what would be the reason for this.
Thanks,
Rahim