function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
jhartjhart 

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':

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}
--------------------------------------------------------------------------------

 
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:

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

 
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
jhartjhart
I have opened case 02249676 to track this issue.
Rajesh ShahRajesh Shah

What happens if I declare the class having @future method as without sharing. Will it run in System mode then?

Message Edited by Rajesh Shah on 10-16-2009 12:47 PM
jhartjhart

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.

ddkpe1ddkpe1

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.

 

 

jhartjhart

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

AdrianCCAdrianCC

Hello @jhart!

 

I was playing recently with @future and was just wondering if you got a response from SFDC guys? 

 

Thank you,

Adi

jhartjhart

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.

Rahim Uddin 19Rahim Uddin 19
Hi All,
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