2

This is similar to this question, but I'm wondering about the object I'm sending into the Queueable Class.

Here's the Queuable Class (not much more than debug statements at this point)

public class CalloutLogger implements Queueable{
  public transient HttpRequest req;

  public CalloutLogger(httpRequest request){
    system.debug('Queueable Class Constructor invoked....');
    system.debug('Constructor Input "request": ' + request.toString());
    req = request;
    system.debug('Instance Var "req": ' + req.toString());
  }
  public void execute(QueueableContext context){
    system.debug('CalloutLogger.execute invoked...');
    system.debug('httpRequest.toString() : ' + req.toString());
  } 
}

Here's a demo Class that enqueues the job

public class DemoCallout {
    public void simulatedCallout(){
    //setup HttpRequest
    HttpRequest req = new HttpRequest();
    req.setEndpoint('http://www.notarealendpoint.com/service');
    req.setMethod('GET');
    //Examine operations....
    system.debug('HttpRequest.toString() : ' + req.toString());
    CalloutLogger logger = new CalloutLogger(req);
    system.debug('logger var: ' + logger.req);
    ID jobID = System.enqueueJob(logger);
    system.debug('Enqueued Job with Id: ' + jobID);
  }
}

And here's a bit of anonymous Apex that kicks it all off..

DemoCallout demo = new DemoCallout();
demo.simulatedCallout();

The anonymous Apex is successful with a debug log like this... enter image description here

But the debug log for the Queuable Class give a null reference error for the HttpRequest object variable "req"...

enter image description here

Any suggestions? Is it even possible to pass an HttpRequest object to a Queuable Class (I'm going to want to pass the HttpResponse in too eventually!)

  • Without that transient keyword, I get Line: -1, Column: -1 System.SerializationException: Not Serializable: System.HttpRequest – John Thompson Feb 10 '17 at 20:43
7

Remove the transient keyword. It causes the variable not to get serialized.

Using the transient Keyword

Use the transient keyword to declare instance variables that can't be saved, and shouldn't be transmitted as part of the view state for a Visualforce page. For example:

Transient Integer currentTotal;

You can also use the transient keyword in Apex classes that are serializable, namely in controllers, controller extensions, or classes that implement the Batchable or Schedulable interface. In addition, you can use transient in classes that define the types of fields declared in the serializable classes.

Problem is...you can't serialize the request and response classes. You might find something like the below helpful:

Serializable Request

public class GenericRequest
{
    String requestType;
    String requestMethod;
    String requestURI;
    String requestParams;
    String requestHeaders;
    String requestBody;
    public GenericRequest(RestRequest request)
    {
        this.requestType = 'Inbound';
        this.requestMethod = request.httpMethod;
        this.requestURI = request.requestURI;
        this.requestParams = (request.params != null) ? JSON.serialize(request.params) : null;
        this.requestHeaders = (request.headers != null) ? JSON.serialize(request.headers) : null;
        this.requestBody = (request.requestBody != null) ? request.requestBody.toString() : null;
    }
    public GenericRequest(HttpRequest request)
    {
        this.requestMethod = request.getMethod();
        this.requestURI = request.getEndpoint();
        this.requestBody = request.getBody();
        this.requestType = 'Outbound';
    }
}

Serializable Response

public class GenericResponse
{
    String responseBody;
    Integer responseStatus;
    public GenericResponse(RestResponse response)
    {
        if (response == null) return;
        responseStatus = response.statusCode;
        if (response.responseBody != null)
            responseBody = response.responseBody.toString();
    }
    public GenericResponse(HttpResponse response)
    {
        if (response == null) return;
        responseStatus = response.getStatusCode();
        responseBody = response.getBody();
    }
}

Queueable Constructor

final GenericRequest request;
public MyQueueable(HttpRequest input)
{
    request = new GenericRequest(input);
}
| improve this answer | |
  • Thanks Adrian. I was afraid that the answer would come back along those lines... I appreaciate those generic Class definitions. So where would I be able to find out which Classes are serializable, and which ones aren't? – John Thompson Feb 13 '17 at 13:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.