Background
I'm trying to build upon Daniel Peter's approach in his HyperBatch
library to build a HyperQuery
tool that will allow me to get better insight into some large tables we have without needing to export the whole table to do external analysis.
Problem
Unfortunately, I stalled out at a pretty early stage, as I'm having trouble getting any Javascript code to identify which classes extend an interface. That's because every single class is returning a null SymbolTable
.
Analysis
- I simplified the AJAX as far as I could and still I get
SymbolTable = null
for every singleApexClass
. - The below MVR works just fine in other sandbox environments, so it seems like the problem is specific to this sandbox.
- The exact same query in the developer workbench returns a populated
SymbolTable
, so the problem does not appear to be my class(es) or profile. - The
SymbolTable
is null for everyApexClass
record, even after I recompiled all classes. - If I run the query via
Execute Anonymous
, theSymbolTable
is populated. I can pass that same session id into my AJAX call instead of what I get from theGETSESSIONID
merge variable and the behavior remains unchanged.
Question
Why might my SymbolTable
values be null
only when queried via Javascript
?
Repro
Javascript
Page/Script
<apex:page showHeader="false" sidebar="false">
<script>
"use strict";
var query = "SELECT Name, SymbolTable FROM ApexClass WHERE NamespacePrefix = null",
url = "/services/data/v39.0/tooling/query/?q=" + encodeURIComponent(query),
request = new XMLHttpRequest();
request.open("GET", url, /*async*/ true);
request.setRequestHeader("Authorization", "Bearer {!GETSESSIONID()}");
request.onreadystatechange = function () {
if (request.readyState === 0 || request.readyState === 4) {
var i, records = JSON.parse(request.responseText).records;
console.debug(records); // results show up
for (i = 0; i < records.length; i++) {
if (records[i].SymbolTable) {
console.debug(records[i]); // nada
}
}
}
}
request.send();
</script>
</apex:page>
Console Log
Workbench
Endpoint
/services/data/v39.0/tooling/query/?q=SELECT+SymbolTable+FROM+ApexClass+WHERE+Name='HyperQuery'
Result
Execute Anonymous
Script
String query = 'SELECT+Name,SymbolTable+FROM+ApexClass+WHERE+Name=\'HyperQuery\'';
String root = URL.getSalesforceBaseUrl().toExternalForm();
String endpoint = root + '/services/data/v39.0/tooling/query/?q=' + query;
HttpRequest request = new HttpRequest();
request.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId());
request.setEndpoint(endpoint);
request.setMethod('GET');
Map<String, Object> response = (Map<String, Object>)
JSON.deserializeUntyped(
new Http().send(request).getBody()
);
List<Object> records = (List<Object>)response.get('records');
Map<String, Object> result = (Map<String, Object>)records[0];
system.assertNotEquals(null, result.get('SymbolTable'));
system.debug(result.get('SymbolTable'));
Debug Excerpt
{constructors=({annotations=(), location={column=5, line=6}, modifiers=(private) ...
request.responseText
look like? – Daniel Ballinger Apr 5 '17 at 21:47