6

I'm quering Apex classes using Tooling API

QueryResult queryResult = toolingConnection.query("select Id, ApiVersion, Name, NamespacePrefix, SymbolTable, Body from ApexClass where NamespacePrefix = null");

and I'm getting property SymbolTable as null. All the other fields I receive as it queried.

I have two developer edition accounts and with the second one it works just fine. And with the first account it WORKED fine about a week ago. I made some changes in code after that, but that was changes in other parts of code. And even if I changed something in code that was tightly coupled I don't have any idea what could be the reason for such behavior.

When I'm trying to receive it using MetadataContainer it doesn't work also.

What could be the reasons for that?

1 Answer 1

10

As per the ApexClass documentation.

If there is not a cached version of SymbolTable, it will be compiled in the background and the query might take longer than expected. The SymbolTable returned from ApexClass does not contain references; to retrieve a SymbolTable with references, use ApexClassMember.

So you need to use ApexClassMember to get the SymbolTable. If it is null, you need to use a MetadataContainer with an ApexClassMember and then a ContainerAysnRequest to compile it and populate the SymbolTable.

Rough steps to populate the ApexClassMember SymbolTable:

  1. Create a MetadataContainer via the API can get the Id.
  2. Create an ApexClassMember with the ContentEntityId set to the Apex Class Id and the Body as the existing body. Set the MetadataContainerId with the value from step 1.
  3. Create a ContainerAsyncRequest with the MetadataContainerId from step 1. Is IsCheckOnly to true (I believe this will be sufficient to populate the SymbolTable. Set it to false if you have issues.)
  4. Poll the ContainerAsyncRequest until the State changes from "queued".
  5. Retrieve the ApexClassMember again with the SymbolTable populated.

There is an example in Using Tooling SOAP API that goes through these steps more or less.

5
  • 1
    I've tried this also. I wrote When I'm trying to receive it using MetadataContainer it doesn't work also . Maybe it was not clear that I did all this actions that you listed :) But I did and it still doesn't work. And as it is said in that piece of documentation The SymbolTable returned from ApexClass does not contain references and I'm not talking about references. I'm talking about the whole SymbolTable. It should work without using ApexClassMember Commented Nov 27, 2014 at 21:37
  • @LiudmilaLikhovid So the results after the ContainerAsyncRequest indicate that the compilation was successful? (ErrorMsg and DeployDetails). Is the ApexClass in question part of a managed package by chance? Commented Nov 27, 2014 at 21:55
  • @LiudmilaLikhovid I your SOQL query includes NamespacePrefix = null so it won't be a managed package issue. I suspect the classes aren't being successfully compiled. You could also check the ApexClass.IsValid column. Commented Nov 27, 2014 at 23:02
  • I've just found out that after doing all that steps to populate the ApexClassMember SymbolTable valid classes have SymbolTable. Thank you so much! I just didn't suppose that any of my classes are not valid. By the way could you please explain me what does that "isValid" mean? It seemed to me that SF doesn't allow to save classes that are not valid (that aren't successfully compiled). I thought that all classes that stored on server are valid Commented Nov 27, 2014 at 23:54
  • 1
    One way ApexClasses before invalid is due to changes in other Apex Classes. Deployments via the Tooling API usually pickup the compile errors with dependant classes. However, this isn't always caught. So you can end up with Apex Classes in Salesforce that can't compile. Commented Nov 28, 2014 at 0:09

You must log in to answer this question.

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