+ Start a Discussion
unidhaunidha 

The method is not called when add @future

Hi,

 

I did some code that doing callout.It works and I planned to put in trigger based on the requirement.But when I put it inside trigger it required me to put @future in the callout method.So I did that, but my method no longer works.I suspect it due @future because when I run at Apex Execute it not able to return value but when I remove @future it return it successfully.I am not sure why this happen? Any idea?

 

Here the snippet of my code 

 

for(User us : mapUserToProcess.values()){

   system.debug('@email== '+us.email);//this one is return the value
   getUserByEmail(us.email);
   String strXML = returnStr;

}


@future(callout=true)
       static void getUserByEmail(string email)

    {
        String baseUrl = url+'/2.0/admin/users/'+email;
        GetAccessToken();
        
        system.debug(' baseUrl for getUserByEmail  '+ baseUrl );

        HTTPRequest request = new HTTPRequest();              
        request.setEndpoint(baseUrl);
        String authorizationHeader = 'WRAP access_token=' + accessToken;
        request.setHeader('Authorization', authorizationHeader);
        request.setHeader('Content-Type', 'application/json');
        request.setMethod('GET');
        request.setTimeout(120000);

        HTTP http = new HTTP();
        HTTPResponse response =  http.send(request);
        
        if(response.getStatusCode()!=200){
           returnStr=response.getStatusCode() +' : '+  response.getStatus();
           errorCode=response.getStatusCode();
           errorMessage=returnStr;
         }
        
        else {
        
           returnStr=response.getBody();
        
        }
        
        system.debug(' returnStr  '+ returnStr);
    }

 If I removed @future, it will go into the getUserByEmail and retrieve the returnStr value.But if I put @future, it not even print out the system.debug and not even return value for returnStr.

 

Thanks.

 

 

 

 

MaxPowerForceMaxPowerForce

When you use a future call, the method is executed in a different execution thread.  You should still get debug logs for it, but the operation will be seperate and say "FutureHandler".   The return type is void so you will not be returning anything to the caller.  The future call runs after the current thread has exited so that only makes sense.

unidhaunidha
If this the case, how I will be able to retrieve the value from the call out process?Example here returnStr is response.getBody(), how I can get returnStr value?
digamber.prasaddigamber.prasad

In this case, you will not be able to access response of callout in trigger(I assume first code block is of trigger). You will need to modify user records from callout method after getting response.

 

Let me know if you have any question.

 

Happy to help you!

unidhaunidha

Oh,no!
Actually let me explain what I want to do.I need to  call external server using Http (RESTFUL) by passing sessionId to get the token.
After that, with the token I can proceed with retrieve,check the condition then do update,add,delete data at external server.
This process will need to do in batch/schedule which run daily.

 

Initially, I completed all those http call out class and test them with Apex Execute Anonymous.It works great.But now, when I try to attach it to Trigger
it required me to add @future.I added and the call out 'not working' anymore.After I read some post here and other resources, it impossible to get the value because of @future, mean it will handle it later.

 

So I plan to do it in schedule batch.Now I am facing the real issue whereby it return UserInfo.getSessionId() = null.It seem critical because I need the session id to get the token in order to call external server.Some of suggestion in my head is to store the session id in custom setting then use it when the batch running.But will the session expired?

 

I am stuck now,how I am going to do schedule job that able to call external server by passing session id? This is my actual issue, I believe.

 

Thanks a lot.

crop1645crop1645

unidha

 

 

You are correct, an @future method executing UserInfo.getSessionId() will return null. However, you can pass the sessionId as known to the trigger to the @future method as an argument. 

unidhaunidha
Thank a lot Eric, it passed the sessionId, but by adding @future i m not able to monitor if it retrieve the token successfully or not plus I will need to use the token to check the data in external server and then run action(add/update/delete) based on the condition. All the method required @future and with it I am not able to control the result of callout.

If I use batch, am I able to do callout without using @future?Am I able to pass the session id in Batch/Schedule?Seem I need to brainstorm on this.

unidhaunidha

If you notice , above in my code I post method to check the existing user using in email from external server.It required to pass the token.

 

Here the sample code to retrieve the token.I upgrade it by passing the session Id , but seem like adding @future is not suit for my application.It is not workable for something that required to check and act in real time, right?I am thinking about Batch now and how I am able to get sessionId and also remove @future from the code.

 

 public static void GetAccessToken(String sessionId)

    {
       system.debug('@unid check Profile Key --'+ profileKey);
       system.debug('@unid check  --'+ externalURL );
     
      String baseUrl=externalURL+'/2.0/Authentication/';
      String Hosturl = 'https://'+URL.getSalesforceBaseUrl().getHost()+'/services/Soap/u/7.0';
        
      system.debug('@unid Hosturl'+Hosturl);
      system.debug('@unid baseURL for GetAccessToken =='+ baseUrl);
      
       HTTPRequest r = new HTTPRequest();              
       r.setEndpoint(baseURL);
       r.setMethod('POST');
       r.setBody('sessionId=' + sessionId + '&url=' + Hosturl + '&profileKey='+profileKey);  
       r.setTimeout(120000);

      
        HTTP http = new HTTP();
        HTTPResponse response = http.send(r);      
        XmlStreamReader reader = response.getXmlStreamReader();
        
        
         accessToken = '';
        
        if(response.getStatusCode()!=200){
           returnStr=response.getStatusCode() +' : '+ response.getStatus();
           errorCode=response.getStatusCode();
           errorMessage=returnStr;
         }
        else {
	        while(reader.hasNext()) { 
	        	if (reader.getEventType() == XmlTag.START_ELEMENT) {
		           if(reader.getLocalName() == 'input'){               
		              string access_token_id = reader.getAttributeValue(null, 'id');
		
		           if(access_token_id == 'access_token')
		                {
		                    accessToken = reader.getAttributeValue(null, 'value');
		
		                }
		            }
		        }
		       reader.next();
	        }
        }

        system.debug('@unid accesstoken === '+ accessToken); 

    
    }

 

crop1645crop1645

Unidha

 

  1. I'm a bit confused now. Why does the non-SFDC system need the SFDC sessionId in order to generate an access token?
  2. Batch jobs can certainly do callouts without a future method; limit is 10 callouts per batch execute() invocation.
  3. Something has to start a batch job (like a trigger, VF controller, or scheduled apex) In the first two, there will be a sessionId that can be passed to the batchable class's constructor; in the scheduled apex - I'm not sure - an experiment would confirm. Batch processes have a batch process Id - would that suffice as a surrogate for the sessionId?

 

 

 

unidhaunidha

Thanks a lot for your replies.I have been absent in order to confirm all on those issue.

-Regarding @future , I replace it with Batch Processing and call using Scheduler.

-To pass session to Batch, we can pass it in Developer console in Execute anonymous by pass in Schedule constructor, I get to know this at http://salesforce.stackexchange.com/questions/21435/how-to-get-userinfo-getsessionid-in-scheduler-batch but due to the risk, I will not use this way.I m going to have permanent token instead of sessionId.

 

Again Thank you for the replies.I really appreciate it.

 

-unidha