• jkucera2
  • NEWBIE
  • 104 Points
  • Member since 2010

  • Chatter
    Feed
  • 4
    Best Answers
  • 1
    Likes Received
  • 0
    Likes Given
  • 8
    Questions
  • 14
    Replies

For example - would this work?

feedItem f=new feedItem();
//some code to assign required fields;
feedComment c=new feedComment();

c.feedItemId=f.Id;

insert f;
insert c;

 

Really confused here - batch jobs are allowed 1 callout execute(), and I made 1, and then got this error.

 

I set the batch size to 1 as well.

 

In fact, I basically copy & pasted a different batch job where I'm doing something very similar, with the only change here being I'm using the standard  "implements Database.Batchable<sObjects> " instead of a custom iterable.  Any thoughts?

 

global with sharing class g2wGetRegistrantDetailsBatch implements Database.Batchable<sObject> {

   public String sObjectQuery ='Select Id, CampaignId FROM CampaignMember' ;
   
   global Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator(sObjectQuery);
   }

    global void execute(Database.BatchableContext BC, List<sObject> scope){
        //Process this 1 campaignMember.  The batch size is always 1 due to 1 callout / batch job limit
        CampaignMember cm=(CampaignMember)scope[0];
        Campaign campaign=[SELECT Id FROM Campaign WHERE id=:cm.campaignId LIMIT 1];
        String requestURL='<my API request URL>';
        
        try{
            //Get registrant details
            system.debug('The request URL is'+requestURL);
            HttpResponse response=g2wUtils.getResponse(requestURL);//send out the request to the other server
        }catch(DMLException e){
           
        }//try
        
    }//execute

    global void finish(Database.BatchableContext BC){
   
    }//finish

    
}//g2wGetRegistrantDetailsBatch

 Called by:

    public static void scheduleQueuedBatchJobs(){
       g2wGetRegistrantDetailsBatch job=new g2wGetRegistrantDetailsBatch();
       String query='Select Id, CampaignId FROM CampaignMember';
       job.sObjectQuery=query;
       Id getRegistrantDetailsBatchJobId = Database.executeBatch(job, 1);//need the batch size at 1 due to callout limit of 1 per batch
    }//scheduleQueuedBatchJobs

 

I have an app making a callout to a service that returns the web form details (think web to lead), but the fields change from request to request, and sometimes include custom fields.


Is there a way to use JSON.deserialize() to handle this case or should I stick with a manual parser given the changing result set?

I ran the Check for Updates and rebooted eclipse but it still always creates new Apex Classes with API version 20.0.

 

How can I get new classes to default to the latest version?  Its a bit annoying to have to go into the browser to create classes in the latest version.

There seems to be a bug in the date methods.  Steps to repro:

 

        Integer year=2012;    
        Integer month=12;
        Integer day=29;
        Integer hourInUTC=4;
        DateTime dt=dateTime.newInstanceGMT(year, month, day, hourInUTC,0,0);
        system.debug('dateTime is:'+dt.format());
        //Stupid function creates a date in GMT even though the DateTime value is clearly the previous day and doc clearly states that it should return the local time zone
        Date d=date.ValueOf(dt);
        system.debug('date is:'+d.format());

 Expected - the date is actually the 28th (9pm)

 

Actual - the date d is shown as the 29th.

 

Also, the dateTIme.now() doesn't return a GMT value, it returns the local timezone.  Either the documentation is wrong, or there's a bug in the method.

I'm pulling data from another system on a regular basis and wrote a method to match existing field values with the new field values.

 

If none of the fields are changed and I try to update in Apex, will that update actually do anything such as fire triggers, create chatter posts, etc?

 

Example to illustrate the question:

Campaign c=[select Id, Name from Campaign where Name = 'name'];
Campaign c2=new Campaign();

c2.Name='name';

        if(c.Name!=JSONCampaign.NAME&&c2.NAME!=NULL){
    		c.Name=c2.Name;
    	}//if 1

update c; // does this actually do anything?

 

I'm an OAuth noob and strugging to get a login page to pop up where Apex is the client and GoToWebinar is the Service.  How do I make the login screen pop up?  Does it somehow magically take over the VF page via redirect or do I need some javascript to open a new window?  Below is my attempted approach using HttpRequest:

 

My first attempt is something like this:

public class G2WButtonController{
    public G2WButtonController(ApexPages.StandardController stdController){
    }
    
    //Code that will run upon button click
    public void autoRun(){
        callG2W(args);
    }

    public static void callG2W(String[] args) 
    {
        String postURL='https://api.citrixonline.com/oauth/authorize?client_id=<myClientId>';
        Http http = new Http();
        HttpRequest req = new HttpRequest();
        req.setEndpoint(postURL);
        req.setMethod('POST');
        HttpResponse res = http.send(req);

        //Class to parse the results
        XmlStreamReader reader = res.getXmlStreamReader();
    }
}

 VF

<apex:page standardController="G2W_Login__c" extensions="G2WButtonController" action="{!autoRun}">
  <apex:pagemessages />

    <apex:sectionHeader title="Auto-Running Apex Code"/>
  <apex:outputPanel >
      You tried calling Apex Code from a button.  If you see this page, something went wrong.  You should have
      been redirected back to the record you clicked the button from.
  </apex:outputPanel>

</apex:page>

 Once I get the login page to pop up, I'm assuming I would then parse the HttpResponse to get a param from the redirect URL- is that correct?

 

Any code samples others have would be greatly appreciated!

I have an app that does stuff with OpptyTeamMembers, but that app can't be installed in orgs that dont' have it turned on, and I don't want to have to create 2 versions of the app.

 

My solution to this is to make all the opptyTemMember references dynamic using sObjects, but I'm stuck on how to create new records as I get an error trying to do this:

sObject ot=new sObject();

 Error: Type cannot be constructed:sObject

 

I can't simply copy & update an existing opptyTeamMember as the ID fields aren't updatable.  

 

I realize the Apex guide says this isn't possible:

The new operator still requires a concrete sObject type, so all instances are specific sObjects.

 

...but an old thread on the partner API hints that it should be possible:

http://boards.developerforce.com/t5/NET-Development/getting-error-when-using-create-with-the-Partner-wsdl/m-p/27483/highlight/true

I'm an OAuth noob and strugging to get a login page to pop up where Apex is the client and GoToWebinar is the Service.  How do I make the login screen pop up?  Does it somehow magically take over the VF page via redirect or do I need some javascript to open a new window?  Below is my attempted approach using HttpRequest:

 

My first attempt is something like this:

public class G2WButtonController{
    public G2WButtonController(ApexPages.StandardController stdController){
    }
    
    //Code that will run upon button click
    public void autoRun(){
        callG2W(args);
    }

    public static void callG2W(String[] args) 
    {
        String postURL='https://api.citrixonline.com/oauth/authorize?client_id=<myClientId>';
        Http http = new Http();
        HttpRequest req = new HttpRequest();
        req.setEndpoint(postURL);
        req.setMethod('POST');
        HttpResponse res = http.send(req);

        //Class to parse the results
        XmlStreamReader reader = res.getXmlStreamReader();
    }
}

 VF

<apex:page standardController="G2W_Login__c" extensions="G2WButtonController" action="{!autoRun}">
  <apex:pagemessages />

    <apex:sectionHeader title="Auto-Running Apex Code"/>
  <apex:outputPanel >
      You tried calling Apex Code from a button.  If you see this page, something went wrong.  You should have
      been redirected back to the record you clicked the button from.
  </apex:outputPanel>

</apex:page>

 Once I get the login page to pop up, I'm assuming I would then parse the HttpResponse to get a param from the redirect URL- is that correct?

 

Any code samples others have would be greatly appreciated!

For example - would this work?

feedItem f=new feedItem();
//some code to assign required fields;
feedComment c=new feedComment();

c.feedItemId=f.Id;

insert f;
insert c;

 

Really confused here - batch jobs are allowed 1 callout execute(), and I made 1, and then got this error.

 

I set the batch size to 1 as well.

 

In fact, I basically copy & pasted a different batch job where I'm doing something very similar, with the only change here being I'm using the standard  "implements Database.Batchable<sObjects> " instead of a custom iterable.  Any thoughts?

 

global with sharing class g2wGetRegistrantDetailsBatch implements Database.Batchable<sObject> {

   public String sObjectQuery ='Select Id, CampaignId FROM CampaignMember' ;
   
   global Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator(sObjectQuery);
   }

    global void execute(Database.BatchableContext BC, List<sObject> scope){
        //Process this 1 campaignMember.  The batch size is always 1 due to 1 callout / batch job limit
        CampaignMember cm=(CampaignMember)scope[0];
        Campaign campaign=[SELECT Id FROM Campaign WHERE id=:cm.campaignId LIMIT 1];
        String requestURL='<my API request URL>';
        
        try{
            //Get registrant details
            system.debug('The request URL is'+requestURL);
            HttpResponse response=g2wUtils.getResponse(requestURL);//send out the request to the other server
        }catch(DMLException e){
           
        }//try
        
    }//execute

    global void finish(Database.BatchableContext BC){
   
    }//finish

    
}//g2wGetRegistrantDetailsBatch

 Called by:

    public static void scheduleQueuedBatchJobs(){
       g2wGetRegistrantDetailsBatch job=new g2wGetRegistrantDetailsBatch();
       String query='Select Id, CampaignId FROM CampaignMember';
       job.sObjectQuery=query;
       Id getRegistrantDetailsBatchJobId = Database.executeBatch(job, 1);//need the batch size at 1 due to callout limit of 1 per batch
    }//scheduleQueuedBatchJobs

 

Hi,

 

We have an Apex app that will make occasional web service calls to our own web site. We use OAuth to authenticate the SF user against our provider. In order to successfully make the call from SF to us, our Apex app needs to know the consumer key and secret required to create and sign the request.

 

We need to store the consumer key and secret somewhere in SF, but it needs to be protected. Ideally, we would like these values to be shipped with our managed package so our customers do not need to manually enter the key and secret into Salesforce.

 

Is there a best practice to include sensitive information, particular the OAuth consumer key and secret, in a SF managed package? If not, what are the alternatives?

 

Thanks,

 

Steve

I ran the Check for Updates and rebooted eclipse but it still always creates new Apex Classes with API version 20.0.

 

How can I get new classes to default to the latest version?  Its a bit annoying to have to go into the browser to create classes in the latest version.

There seems to be a bug in the date methods.  Steps to repro:

 

        Integer year=2012;    
        Integer month=12;
        Integer day=29;
        Integer hourInUTC=4;
        DateTime dt=dateTime.newInstanceGMT(year, month, day, hourInUTC,0,0);
        system.debug('dateTime is:'+dt.format());
        //Stupid function creates a date in GMT even though the DateTime value is clearly the previous day and doc clearly states that it should return the local time zone
        Date d=date.ValueOf(dt);
        system.debug('date is:'+d.format());

 Expected - the date is actually the 28th (9pm)

 

Actual - the date d is shown as the 29th.

 

Also, the dateTIme.now() doesn't return a GMT value, it returns the local timezone.  Either the documentation is wrong, or there's a bug in the method.

I'm pulling data from another system on a regular basis and wrote a method to match existing field values with the new field values.

 

If none of the fields are changed and I try to update in Apex, will that update actually do anything such as fire triggers, create chatter posts, etc?

 

Example to illustrate the question:

Campaign c=[select Id, Name from Campaign where Name = 'name'];
Campaign c2=new Campaign();

c2.Name='name';

        if(c.Name!=JSONCampaign.NAME&&c2.NAME!=NULL){
    		c.Name=c2.Name;
    	}//if 1

update c; // does this actually do anything?

 

I'm an OAuth noob and strugging to get a login page to pop up where Apex is the client and GoToWebinar is the Service.  How do I make the login screen pop up?  Does it somehow magically take over the VF page via redirect or do I need some javascript to open a new window?  Below is my attempted approach using HttpRequest:

 

My first attempt is something like this:

public class G2WButtonController{
    public G2WButtonController(ApexPages.StandardController stdController){
    }
    
    //Code that will run upon button click
    public void autoRun(){
        callG2W(args);
    }

    public static void callG2W(String[] args) 
    {
        String postURL='https://api.citrixonline.com/oauth/authorize?client_id=<myClientId>';
        Http http = new Http();
        HttpRequest req = new HttpRequest();
        req.setEndpoint(postURL);
        req.setMethod('POST');
        HttpResponse res = http.send(req);

        //Class to parse the results
        XmlStreamReader reader = res.getXmlStreamReader();
    }
}

 VF

<apex:page standardController="G2W_Login__c" extensions="G2WButtonController" action="{!autoRun}">
  <apex:pagemessages />

    <apex:sectionHeader title="Auto-Running Apex Code"/>
  <apex:outputPanel >
      You tried calling Apex Code from a button.  If you see this page, something went wrong.  You should have
      been redirected back to the record you clicked the button from.
  </apex:outputPanel>

</apex:page>

 Once I get the login page to pop up, I'm assuming I would then parse the HttpResponse to get a param from the redirect URL- is that correct?

 

Any code samples others have would be greatly appreciated!

I have an app that does stuff with OpptyTeamMembers, but that app can't be installed in orgs that dont' have it turned on, and I don't want to have to create 2 versions of the app.

 

My solution to this is to make all the opptyTemMember references dynamic using sObjects, but I'm stuck on how to create new records as I get an error trying to do this:

sObject ot=new sObject();

 Error: Type cannot be constructed:sObject

 

I can't simply copy & update an existing opptyTeamMember as the ID fields aren't updatable.  

 

I realize the Apex guide says this isn't possible:

The new operator still requires a concrete sObject type, so all instances are specific sObjects.

 

...but an old thread on the partner API hints that it should be possible:

http://boards.developerforce.com/t5/NET-Development/getting-error-when-using-create-with-the-Partner-wsdl/m-p/27483/highlight/true

Hi All,

 

I need to call two functions and want a delay of 10 seconds between then.

 

It is possible with Apex code ?

 

Thanks,

Deepak

I just added a NameSpace to my Developer org, and now 2 tests fail with an awful error message.  I'm tempted to just remove the tests so I can actually upload the package.

 

The code hasn't changed, and tests still pass in installed orgs that have the unmanaged package.

 

Error debug lines:

 

21:18:53.48|USER_DEBUG|[7,9]|DEBUG|query string: Select Id, recordId__c FROM chttrunfollow__UnfollowQueue__c WHERE scheduledUnfollowDate__c<= TODAY AND IsDeleted=FALSE
21:18:53.48|METHOD_EXIT|[7,9]|system.debug(String)
21:18:53.48|METHOD_ENTRY|[8,52]|database.query(String)
21:18:53.48|SOQL_EXECUTE_BEGIN|[8,52]|Aggregations:0|Select Id, recordId__c FROM chttrunfollow__UnfollowQueue__c WHERE scheduledUnfollowDate__c<= TODAY AND IsDeleted=FALSE
21:18:53.51|SOQL_EXECUTE_END|[8,52]|Rows:3
21:18:53.51|METHOD_EXIT|[8,52]|database.query(String)
21:18:53.51|METHOD_ENTRY|[9,9]|system.debug(String)
21:18:53.51|METHOD_ENTRY|[9,31]|LIST<chttrunfollow__UnfollowQueue__c>.size()
21:18:53.52|METHOD_EXIT|[9,31]|LIST<chttrunfollow__UnfollowQueue__c>.size()
21:18:53.52|USER_DEBUG|[9,9]|DEBUG|size: 3
21:18:53.52|METHOD_EXIT|[9,9]|system.debug(String)
21:18:53.52|METHOD_ENTRY|[10,16]|Database.getQueryLocator(String)
21:18:53.52|SOQL_EXECUTE_BEGIN|[10,16]|Aggregations:0|Select Id, recordId__c FROM chttrunfollow__UnfollowQueue__c
21:18:53.77|SOQL_EXECUTE_END|[10,16]|Rows:3
21:18:53.77|METHOD_EXIT|[10,16]|Database.getQueryLocator(String)
21:18:53.105|FATAL_ERROR|Internal Salesforce.com Error

 I saw this thread, and added my namespace, but no luck:

http://community.salesforce.com/t5/Visualforce-Development/Visualforce-An-internal-server-error-has-occurred/m-p/167376

 

Class that produces the above error:

 

global with sharing class UnfollowProcessUnfollowQueueBatch implements Database.Batchable<sObject>{

   global String sObjectQuery ='Select Id, recordId__c FROM chttrunfollow__UnfollowQueue__c WHERE scheduledUnfollowDate__c<= TODAY' ;
   
   global Database.QueryLocator start(Database.BatchableContext BC){
        system.debug('query string: '+sObjectQuery);
        List<chttrunfollow__UnfollowQueue__c> uq = database.query(sObjectQuery);
        system.debug('size: '+uq.size());
        return Database.getQueryLocator(sObjectQuery);
   }

   global void execute(Database.BatchableContext BC, List<sObject> scope){
        Set<Id> recordIds=new Set<Id>();
  
        for(sObject s : scope){
            recordIds.add(String.ValueOf(s.get('recordId__c')));
        }//for
    
        //This is the method that unfollows all people from the records 
        try{
            UnfollowRecords.UnfollowRecordsButtonAction(recordIds);
            delete scope;
        } catch (Exception e) {
        }//try
   }

   global void finish(Database.BatchableContext BC){
       AsyncApexJob a = [Select Id, Status, NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Email from AsyncApexJob where Id =:BC.getJobId()];
  }

}//UnfollowRecordsFromDelayQueueBatch

Other Class that calls this class:

 

global with sharing class unfollowTryBatchJobsAgain{

    public static void unfollowTryBatchJobsAgain(){
        Integer numBatchApexJobsLimit=5;//at time of coding, there are at most 5 concurrent batch apex jobs in any org
        List<AsyncApexJob> numBatchJobs = [SELECT Id, Status FROM AsyncApexJob WHERE Status = 'Queued' OR Status = 'Processing'];

        //This is the number of jobs that can be queued up by this method
        Integer numJobsAvailable=numBatchApexJobsLimit - numBatchJobs.size();

        if(numJobsAvailable>0){
            List<UnfollowBatchJobsQueue__c> batchJobsQueued=[SELECT Id, IsDeleted, delayJob__c, delayRulesIncluded__c, evalateEachRecordForDaysDelay__c, numRulesUsedInThisObject__c, objectName__c, sObjectQuery__c FROM UnfollowBatchJobsQueue__c WHERE IsDeleted=FALSE ORDER BY  CreatedDate ASC];
            //Goal here is to process the delay queue first as it's more important than the others. Rather than do 2 queries, it's handled with variables here:
            Integer delayJobNum=1000;//initialize to huge number as a backup
            for (Integer i=0;i<batchJobsQueued.size();i++){
                if (batchJobsQueued[i].delayJob__c==TRUE){
                    delayJobNum=i;
                    break;
                }//if 2
            }//for 1
            
            for(Integer i=0; i<numJobsAvailable && i<batchJobsQueued.size(); i++){
                //if this is the high priority "delayed records scheduled for unfollow today" job, do it first
                if (delayJobNum!=1000){
                    UnfollowProcessUnfollowQueueBatch unfollowDelayedRecords= new UnfollowProcessUnfollowQueueBatch();
                    unfollowDelayedRecords.sObjectQuery=batchJobsQueued[delayJobNum].sObjectQuery__c;
                    try{
                        Id unfollowRulesProcessId = Database.executeBatch(unfollowDelayedRecords, 200); 
                        delete batchJobsQueued[delayJobNum];
                    } catch(exception e){
//                        system.debug('Either the batch failed or the job deletion from teh queue failed: '+e);
                    }//try
                } else if(batchJobsQueued[i].delayRulesIncluded__c==FALSE){
                 //is this the simple case with no "days delay" rules?
                    UnfollowRecordsBatch  unfollowRecords= new UnfollowRecordsBatch();
                    unfollowRecords.ObjectName=batchJobsQueued[i].objectName__c;
                    unfollowRecords.numRulesUsedInThisObject=batchJobsQueued[i].numRulesUsedInThisObject__c.intValue();
                    unfollowRecords.sObjectQuery =  batchJobsQueued[i].sObjectQuery__c;
                
                    try{
                        Id unfollowRulesProcessId = Database.executeBatch(unfollowRecords, 200); 
                        delete batchJobsQueued[i];
                    } catch(exception e){
//                        system.debug('Either the batch failed or the job deletion from the queue failed: '+e);
                    }//try
                } else {
                //else it's the more complex case where we need to check for the unfollow date
                    UnfollowQueueDelayRecordsBatch queueDelayRecords= new UnfollowQueueDelayRecordsBatch();
                    queueDelayRecords.ObjectName=batchJobsQueued[i].objectName__c;
                    queueDelayRecords.sObjectQuery =  batchJobsQueued[i].sObjectQuery__c;
                    queueDelayRecords.evalateEachRecordForDaysDelay=batchJobsQueued[i].evalateEachRecordForDaysDelay__c;
                    if(queueDelayRecords.evalateEachRecordForDaysDelay==TRUE){
//let's cross our fingers that the rule criteria didn't change between when this job first ran and now :(  
//Will the code fail elegantly if the rules were changed?
//I'd rather not create a 3rd queue just to save the state of the rules due to stupid batch apex limits
                        queueDelayRecords.delayRules=[Select Id, ObjectName__c, Active__c, FieldName__c, FieldType__c, Operator__c, Value__c, DaysDelay__c FROM UnfollowRule__c WHERE DaysDelay__c>0 AND Active__c = TRUE AND objectName__c=:queueDelayRecords.ObjectName]; 
                    }//if 3

                    try{
                        Id unfollowRulesProcessId = Database.executeBatch(queueDelayRecords, 200); 
                        delete batchJobsQueued[i];
                    } catch(exception e){
//                        system.debug('Either the batch failed or the job deletion from the queue failed: '+e);
                    }//try
                }//if 2
            }//for 1
        }//if 1
        
/*                        
        //This will store the job definition for the jobs over the numBatchApexJobsLimit to be run later
        List<UnfollowBatchJobsQueue__c> batchJobsQueued=new List<UnfollowBatchJobsQueue__c>();

        List<UnfollowRule__c> activeNonDelayedRules=[Select Id, ObjectName__c, Active__c, FieldName__c, FieldType__c, Operator__c, Value__c, DaysDelay__c FROM UnfollowRule__c WHERE (DaysDelay__c<1 OR DaysDelay__c=null) AND Active__c = TRUE];
        
        //now count the # rules for each object to pass into the email later
        For (UnfollowRule__c rule:activeNonDelayedRules){
            List<UnfollowRule__c> rules=new List<UnfollowRule__c>();
            if(objectRulesMap.containsKey(rule.ObjectName__c)){
                //get the existing rules in the map & add the new one
                rules=objectRulesMap.get(rule.ObjectName__c);
                rules.add(rule);
                objectRulesMap.remove(rule.ObjectName__c);
                objectRulesMap.put(rule.ObjectName__c, rules);
            } else {
                rules.add(rule);
                objectRulesMap.put(rule.ObjectName__c,rules);
            }//if 1
        }//for 1

        //Now queue up all the batch jobs
        for (String objectName:objectRulesMap.keyset()){
            //First check if there's a slot available - max of 5 concurrent jobs across all apps
            addFieldNames=FALSE;            
            query=buildQuery(objectName, objectRulesMap.get(objectName), addFieldNames);
            if(numJobsAvailable>0){
                numJobsAvailable--;//subtract one from the limit
                UnfollowRecordsBatch  unfollowRecords= new UnfollowRecordsBatch();
                unfollowRecords.ObjectName=objectName;
    
                unfollowRecords.numRulesUsedInThisObject=objectRulesMap.get(objectName).size();
                unfollowRecords.sObjectQuery =  query;
//                system.debug('The sObjectQuery string is: '+unfollowRecords.sObjectQuery);
                
                Id unfollowRulesProcessId = Database.executeBatch(unfollowRecords, 200); 
            }else{
                String sObjectQuery = query;
//                system.debug('There are 5 batch jobs already running, so this job is not scheduled.  Delay Job: TRUE, Object: '+objectName+', # Rules: '+objectRulesMap.get(objectName).size()+', Query: '+sObjectQuery );
                UnfollowBatchJobsQueue__c job=new UnfollowBatchJobsQueue__c(delayJob__c=FALSE, delayRulesIncluded__c=FALSE, objectName__c=objectName, numRulesUsedInThisObject__c=objectRulesMap.get(objectName).size(), sObjectQuery__c=sObjectQuery);
                batchJobsQueued.add(job);
            }//if 1
        }//for 1
        try{
            if(batchJobsQueued.size()>0){
                insert batchJobsQueued;
            }//if 1
        }catch (DMLException e){
//            system.debug('The batch jobs were not added to the queue successfully, likely due to dupe object name.  Error: '+e);
        }//try
*/        
    }//unfollowTryBatchJobsAgain
}//unfollowTryBatchJobsAgain

 

 

 

 

Note I'm not positive the subject of this post is the true reason for the bug.  The other possible explanation is:


Dynamic SOQL requires namespace prefixes when called in global context

 

Anyway, the bug is:

 

Our managed package occasionally uses Dynamic SOQL.  In one case, we have a controller that uses Database.query() without any namespace prefixes:

Database.query('select CustomField__c from CustomObject__c');

 

In another case, we call Database.getQueryLocator() (as part of a Database.Batchable implementation).  That query also does not include the namespace prefix:

global Database.queryLocator start(Database.BatchableContext bc) {
return Database.getQueryLocator('select CustomField__c from CustomObject__c');
}

 

 


All of this works in our DE org, but once packaged & deployed, only the first one works.

 

The second ("getQueryLocator") throws an exception:

Developer script exception from iHance : 'i.Maintenance' : common.exception.ApiQueryException: No such column 'CustomField__c' on entity 'i__CustomObject__c'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names.


I'm not sure if the bug is that getQueryLocator() requires the namespace prefix, or if Dynamic SOQL methods called in the global context do.  Without re-packaging everything to create a test case, there's no way for me to tell.

 

Salesforce support - I've created case 03501471 to track this issue.

  • April 23, 2010
  • Like
  • 0