0

I am trying to build an APEX Rest class that will push Salesforce data to a third party application.

I have watched some training videos and come up with the below. I am trying to run this in the developer console (Execute Anonymous Window) just to see if the code is correct and working.

Ultimately I want the body request to have Account.Name, Account.Email__c etc rather than the test info i have provided but first i want to make sure this is working.

When i try to run this however i keep getting an unexpected Token error: line 5 class.

Is it possible to test this code in the developer console?

public with sharing class AccountToFACustomer {

    public class Response{
        public integer code {get; set;}
        public String body {get; set;}
        public boolean success {get; set;}
        public String errorText {get; set;}

        public Response (integer code, String body){
                this.code = code;
                this.body = body;
                this.success = (code == 200 || code == 201);
        }
    }

    public class customerResponse{

        public string uuid {get; set;}
        public string link {get; set;}
        public string location {get; set;}
    }


    public Response CreateCustomer (string description){

        Response resp;

        string endpoint = 'https://apistaging.website.net/';
        string token = 'Token XXXXXXXXXXXXX';
        string method = 'POST';

        HttpRequest req = new HttpRequest();
        HttpResponse res = new HttpResponse();
        Http h = new http();

        req.setEndpoint(endpoint);
        req.setMethod(method);
        req.setHeader('Autorization', token);
        req.setHeader('Content-Type', 'application/json');
        req.setHeader('Accept-Type', 'application/json');

        req.setBody(
            '{"name":"Test300816",' +
            '"email":"[email protected],'+
             '"phone":"12345678",'+
             '"website":"www.website.com",'+
             '"location":{'+
                    '"name":"Account No: 300816",'+
                    '"streetName":"Street",'+
                    '"locality":"dublin",'+
                    '"postcode":"ballsbridge",'+
                    '"country":"Ireland" }}' 
        );
        try{

        res = h.send(req);
        resp = new Response(res.getStatusCode(), res.getBody()); 

            if (resp.success) {
                customerResponse custResp = (customerResponse)JSON.deserialize(res.getBody(), customerResponse.class);
            }

        }
             catch(System.CalloutException e) {
                 System.debug('Callout error: '+ e);
                 return resp;
        }        
        return resp;   

    }

}
3
  • 1
    The error come from the code you are trying to run in the Dev console. What was that code?
    – Eric
    Aug 30, 2016 at 11:11
  • @Eric I didn't get an error code, just the text "Line: 3, Column: 11 unexpected token: 'class' " Aug 30, 2016 at 11:55
  • Ahh, you are trying to run this code directly in the dev console. I typically save the code to a class and run it from the console....I would review sfdxfox's answer below as I am sure it is thorough and will help you immensely.
    – Eric
    Aug 30, 2016 at 11:57

1 Answer 1

5

It looks like your JSON is malformed. You should not be crafting JSON by hand, because it's easy to have a typo. Here's how I would generate the JSON:

req.setBody(JSON.serialize(
    new Map<String, Object> {
        'name' => 'Test300816',
        'email' => '[email protected]',
        'phone' => '12345678',
        'website' => 'www.website.com',
        'location' => new Map<Sring, Object>  {
            'name' => 'Account No: 300816',
            'streetName' => 'Street',
            'locality' => 'dublin',
            'postcode' => 'ballsbridge',
            'country' => 'ireland'
        }
    }
));

This pretty much limits my typos to compiler-catchable errors. The original error, by the way, was a missing quote character after the email address.

A proper unit test using an HttpCalloutMock would have caught this error as well. That might have looked like this:

@isTest public class MyServiceCalloutMock implements HttpCalloutMock {
    class Location {
        String name, streetName, locality, postcode, country;
    }
    class Request {
        String name, email, phone, website;
        Location location;
    }
    public HttpResponse respond(HttpRequest req) {
        HttpResponse res = new HttpResponse();
        try {
            Request payload = (Request)JSON.deserialize(req.getBody(), Request.class);
            // build a response in res, and return.
        } catch(Exception e) {
            System.assert(false, 'Unexpected exception: '+e.getMessage());
        }
        return null; // satisfy compiler
    }
}

Then, with a unit test:

@isTest class AccountToFACustomerTest {
    @isTest static void unitTest() {
        MyServiceCalloutMock m = new MyServiceCalloutMock();
        Test.setMock(HttpCalloutMock.class, m);
        AccountToFACustomer.Response res = new AccountToFACustomer().CreateCustomer('Test');
        // validate the response
    }
}

You could have also figured this out "by hand" if you debugged the request body after setting it, and validating it with a JSON validator.


After comment:

It's clear now that you're trying to put that class directly in to the Developer Console's execute anonymous window.

This won't work, because execute anonymous doesn't allow inner classes, because any top-level classes are implicitly created as inner classes, and you can't have inner-inner classes.

You'd have to restructure your code as follows:

public class Response { ... }
public class CustomerResponse { ... }
public class AccountToFACustomer { ... }

new AccountToFACustomer().CreateCustomer('Test');

That said, a unit test is probably better, because no live data can be modified using a unit test.

3
  • 1
    @denisoleary You can't have an inner class inside an inner class. Execute Anonymous implicitly creates an outer class, so any classes within become inner classes.
    – sfdcfox
    Aug 30, 2016 at 11:53
  • Ok, I got it now. I'm still getting a 405 error but will try and figure out what i have got wrong in the request. I'll build some unit tests down the line but right now I just want to see this code sending data from salesforce to the 3rd party app just to see some results. I'm sending from a SF sandbox to a test environment so i don't have to worry about messing with live data for now. Thanks! Aug 30, 2016 at 12:23
  • @denisoleary 405 means "can't use that method." You're trying to POST to a resource that doesn't allow it. You'll have to check the manual.
    – sfdcfox
    Aug 30, 2016 at 12:39

You must log in to answer this question.

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