• G2WIntegration
  • NEWBIE
  • 75 Points
  • Member since 2011

  • Chatter
    Feed
  • 3
    Best Answers
  • 1
    Likes Received
  • 0
    Likes Given
  • 11
    Questions
  • 18
    Replies

Do upgrade scripts run on push upgrades?  This ran fine in test code, but didn't run with manual tests of push upgrades from something like 2.20 to 3.5.  The test has the optional boolean to test push upgrades as well, but it fails manually. 

 

The goal is to clean up some scheduled jobs (CronTrigger) that are no longer needed with the latest version so that uninstall can be easy if anyone decides to get rid of the app later.  

 

global class g2wInstall implements InstallHandler {
    global void onInstall(InstallContext context) {
    	//If this isn't a new install, do the work
    	if(context.previousVersion()!=null){
	    	String getRegistrantsSchedulerStartTime='47 25 20 * * ?';
    		String getRegistrantDetailsSchedulerStartTime='47 25 21 * * ?';
    		String getSessionsSchedulerStartTime='47 25 22 * * ?';
 		    String getAttendeesSchedulerStartTime='47 25 23 * * ?';
    		List<CronTrigger> cts=[SELECT Id, NextFireTime, State FROM CronTrigger WHERE (CronExpression =:getRegistrantsSchedulerStartTime OR CronExpression =:getSessionsSchedulerStartTime OR CronExpression =: getRegistrantDetailsSchedulerStartTime OR CronExpression =: getAttendeesSchedulerStartTime) AND State != 'DELETED'];

			//Abort all the old jobs that aren't needed anymore
    		if(cts.size()>0)
    			for(CronTrigger ct:cts)
                	system.abortJob(ct.Id );
    	}
    }//onInstall
}

 This test passes, but manual tests don't show the scheduled jobs deleted:

    //runTest 0
	static void testInstallScript() {
        if(runTest[0]==TRUE){
	  		g2wInstall postinstall = new g2wInstall();
	  		
	  		String getRegistrantsSchedulerStartTime='47 25 20 * * ?';
	    	String getRegistrantDetailsSchedulerStartTime='47 25 21 * * ?';
	    	String getSessionsSchedulerStartTime='47 25 22 * * ?';
	 		String getAttendeesSchedulerStartTime='47 25 23 * * ?';
	
	        system.schedule('Get Registrants', getRegistrantsSchedulerStartTime, new g2wGetRegistrantsSchedulerExecute()); 
	        system.schedule('Get Registrant Details', getRegistrantDetailsSchedulerStartTime, new g2wGetRegistrantDetailsSchedulerExecute()); 
	        system.schedule('Get Sessions', getSessionsSchedulerStartTime, new g2wGetSessionsSchedulerExecute()); 
	        system.schedule('Get Webinar Attendees', getAttendeesSchedulerStartTime, new g2wGetWebinarAttendeesSchedulerExecute());
	
	    	Test.testInstall(postinstall, null);
	
	   		List<CronTrigger> cts=[SELECT Id, NextFireTime, State FROM CronTrigger WHERE (CronExpression =:getRegistrantsSchedulerStartTime OR CronExpression =:getSessionsSchedulerStartTime OR CronExpression =: getRegistrantDetailsSchedulerStartTime OR CronExpression =: getAttendeesSchedulerStartTime) AND State != 'DELETED'];
			system.assertNOTEquals(0, cts.size());
	
	    	Test.testInstall(postinstall, new Version(3,4), true);
			cts=[SELECT Id, NextFireTime, State FROM CronTrigger WHERE (CronExpression =:getRegistrantsSchedulerStartTime OR CronExpression =:getSessionsSchedulerStartTime OR CronExpression =: getRegistrantDetailsSchedulerStartTime OR CronExpression =: getAttendeesSchedulerStartTime) AND State != 'DELETED'];
			system.assertEquals(0, cts.size());
        }
  	}//testInstallScript

 

Gotta start first with a rant - the libraries used for DateTIme methods are a piece of crap due to bugs & missing basic functionality.

 

Now that that's out of the way, anyone have ideas on how to get the difference of 2 different DateTime's?  The use case is to ensure that our time stamps are correct so that when we use DateTime1>DateTIme2, it works as expected, which we've manually verified. 

 

Attempt 1: Simple subtraction doesn't work as its not supported

Attempt 2: Convert to double doesn't work as it converts the DateTime to # miliseconds (??) which is more than a 64bit double can handle.  (nevermind that you can't even set milliseconds)

Attempt 3: Convert both to date, use .daysBetween() -too much work as have to basically rebuild the library to handle midnight, new hours, new minutes, etc. 

It seems that as of Winter '12, there was a change in how tests handle scheduled jobs.

 

Before Winter '12, we had code that woke up a scheduler, but the execute method wasn't fired.

 

After Winter '12, that same code fails as the scheduler is now firing the execute method (which happens to create 2nd batch job in the same test).

 

Bug or expected behavior?

 

Example:

test.startTest();                    
  system.schedule('Some scheduled job', varForStartTime, new someSchedulerClass()); 
test.stopTest();

 

global with sharing class someSchedulerClass implements Schedulable{
    global void execute(SchedulableContext ctx) {
		someMethodThatFiresBatchJob();
    }//execute
}

 Removing test.startTest() and test.stopTest() fixes the problem as then the execute method doesn't fire.  

On our na3 & na11 orgs, we have the Winter '13 icon so I'm assuming we are on Winter '13, but when clicking Versions, then Push Uprades, we can't select any major release, only patch versions.  Selecting an existing patch org doesn't list any possible orgs either from other major versions. 

 

What are we missing here? How do we enable push major?  

 

The doc doesn't say any special perms are needed and we've had the patch perm for a while now. We don't have any install scripts yet, but will have to create one due to the questionable decision to only allow admins to get new features by default.  

 

 

One of our customers is seeing this error when our app tries to insert campaign members:

INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY, insufficient access rights on cross-reference id: []

 

The gist of the code:

1) Find leads & contacts that match the criteria

2) Add them with the same campaignId to a CampaignMember list

3) Try to insert the CM list, which then errors

 

An admin is the context user, sharing is public, though there is a lead assignment rule that changes the lead owner to another admin, though she doesn't have the Marketing user checkbox (shouldn't matter though).

 

Any ideas?

 

Code snippets:

                            List<Contact> contacts=[SELECT Id, FirstName, LastName, Email, AccountId FROM Contact WHERE Email IN: emailToRegistrant.keySet()];
                            if(contacts.size()>0){
                                Set<string> contactEmailsAlreadyProcessed=new Set<String>();
                                for (contact ct:contacts){
                                    //This handles the case where there are 2+ contacts with the same
                                    //email address.  Otherwise, emailToRegistrant will be blank for the 2nd
                                    //one as we remove the emails so they aren't processed for Leads
                                    if(contactEmailsAlreadyProcessed.contains(ct.email)==FALSE){
                                        contactEmailsAlreadyProcessed.add(ct.email);
                                        CampaignMember cmToInsert=new CampaignMember();
                                        cmToInsert.ContactId=ct.Id;
                                        cmToInsert.CampaignId=c.Id;
                                        cmToInsert.status=g2wUtils.setCMStatus(emailToRegistrant.get(ct.email).status);
                                        cmToInsert.g2wRegistrantKey__c=emailToRegistrant.get(ct.email).registrantKey;
                                        cmsToInsert.add(cmToInsert);                                
                                        emailToRegistrant.remove(ct.email);
                                    }//if 5
                                }//for 1
                            }//if 4
                            
                            List<Lead> leads=[SELECT Id, FirstName, LastName, Email, Company FROM Lead WHERE Email IN: emailToRegistrant.keySet()];
                            if(leads.size()>0){
                                Set<string> leadEmailsAlreadyProcessed=new Set<String>();
                                for (Lead l:leads){
                                    if(leadEmailsAlreadyProcessed.contains(l.email)==FALSE){
                                        leadEmailsAlreadyProcessed.add(l.email);
                                        CampaignMember cmToInsert=new CampaignMember();
                                        cmToInsert.LeadId=l.Id;
                                        cmToInsert.CampaignId=c.Id;
                                        cmToInsert.status=g2wUtils.setCMStatus(emailToRegistrant.get(l.email).status);
                                        cmToInsert.g2wRegistrantKey__c=emailToRegistrant.get(l.email).registrantKey;
                                        cmsToInsert.add(cmToInsert);                                
                                        emailToRegistrant.remove(l.email);
                                    }//if 5
                                }//for 1
                            }//if 4
Database.insert(cmsToInsert);

 The last line is where the error occurs.  

I was hoping to make <apex:tabPanel> behave nice and select one tab if the app hasn't been set up and the other if it has but ran into two problems:

1) Trying to set selectedTab to a dynamic value doesn't seem to work

2) Using value= doesn't work as then the user can't ever click on the other tab

 

Any tips I'm missing?  I hoped something like this would have worked:

<apex:page id="thePage" controller="controller">
    <apex:tabPanel switchType="client" selectedTab="{!selectedTab}" id="theTabPanel">
        <apex:tab label="One" name="name1" id="tabOne">content for tab one</apex:tab>
        <apex:tab label="Two" name="name2" id="tabTwo">content for tab two</apex:tab>
    </apex:tabPanel>
</apex:page>

And the apex class, where "schedulersActive" is set in another method.  This code works if using value="{!selectedTab}" but not for selectedTab as shown above.

public with sharing class controller{
	public String selectedTab{
		get{
			if (schedulersActive==TRUE)
				return 'name1';

			else
				return 'name2';
			
		}
		set;
	}//getSelectedTab
}

 

Salesforce lists have a View & Del link for every row.  I know how to make the view link, but haven't been able to figure out how to get any other action to target that specific row. 

 

Currently I'm using Dynamic Binding to show the list as the target is a protected custom setting, but I can probably use any list code like a pageBlockTable if that's easier.  The use case here is to show the name of each row (which is the userId), and delete the row using a button, similar to Salesforce lists.

 

Current sample code:

 

<apex:page standardController="Account"  extensions="DynamicAccountFieldsLister"> 

    <apex:pageMessages /><br/>
    
    <apex:form>
        <apex:pageBlock title="Edit Account" mode="edit">
            <apex:pageBlockSection columns="1">
                        <apex:commandLink value="View"  action="/{!r.Id}"/>                                        
                <apex:repeat value="{!editableFields}" var="f">
                    <apex:inputField value="{!Account[f]}"/>
                </apex:repeat>
           </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
    
</apex:page>

 

 

public class DynamicAccountFieldsLister {

    public DynamicAccountFieldsLister(ApexPages.StandardController controller) { 
        controller.addFields(editableFields);
    }

    public List<String> editableFields {
        get {
            if (editableFields == null) {
                editableFields = new List<String>();
                editableFields.add('Industry');
                editableFields.add('AnnualRevenue');
                editableFields.add('BillingCity');
            }
            return editableFields ;
        }
        private set;
    }
}

 

 

A customer received this exception:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Apex script unhandled exception by user/organization: <userId>/<orgId>

Visualforce Page: /apex/g2wintegration__g2wInitialize

 

caused by: System.ListException: Row with duplicate Name at index: 2

Class.g2wIntegration.g2wUtils.g2wAccessTokenURL: line 99, column 1
Class.g2wIntegration.g2wInitializeController.autoRun: line 24, column 1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Line 99 refers to this line, which invokes the code to grab the custom list setting rows:

Map<String, G2WAccessTokens__c> tokens = G2WAccessTokens__c.getAll();

 

I interpret that error as there are two custom setting rows with the same name - is that accurate? If so, there seems to be a bug in Custom Settings.

In any custom list setting, the name must be unique, but somehow this was not the case for this customer.

 

We set the name to the UserId and have additional checks to ensure if the setting exists, that it gets updated versus trying to insert a new one. Even if code wasn't in place, inserting a 2nd row with the same name throws an exception in Apex, but that didn't happen.

 

Is there any way 2 custom list setting rows can be inserted twice?  All of our tests to reproduce this issue throw exceptions as Apex doesn't allow inserting 2 with the same name.  

This smells like a bug:

1) Create button that inserts cron triggers

2) Create button that aborts these same cron triggers

3) Have standard or read only (non-admin) user click the button 

4) Have that same user click button to delete crontriggers

 

Expected:

Same permissions apply to #3 & #4

 

Actual:

User can insert, but gets Insufficient Privileges error on abort

 

Is there any way to drop into system mode for these users?  Everything works fine with admins.

 

Insert code sample:

                                    system.schedule('Get Webinars', getWebinarsSchedulerStartTime, new g2wGetWebinarsSchedulerExecute()); 
                                    system.schedule('Get Registrants', getRegistrantsSchedulerStartTime, new g2wGetRegistrantsSchedulerExecute()); 
                                    system.schedule('Get Registrant Details', getRegistrantDetailsSchedulerStartTime, new g2wGetRegistrantDetailsSchedulerExecute()); 
                                    system.schedule('Get Sessions', getSessionsSchedulerStartTime, new g2wGetSessionsSchedulerExecute()); 
                                    system.schedule('Get Webinar Attendees', getAttendeesSchedulerStartTime, new g2wGetWebinarAttendeesSchedulerExecute()); 

 

 

Abort code sample:

List<CronTrigger> cts=[SELECT Id, NextFireTime, State FROM CronTrigger WHERE (CronExpression =: g2wUtils.getWebinarsSchedulerStartTime OR CronExpression =:g2wUtils.getRegistrantsSchedulerStartTime OR CronExpression =:g2wUtils.getSessionsSchedulerStartTime OR CronExpression =: g2wUtils.getRegistrantDetailsSchedulerStartTime OR CronExpression =: g2wUtils.getAttendeesSchedulerStartTime) AND State != 'DELETED'];
        if (cts.size()>0){
            for(CronTrigger ct:cts){
                system.abortJob(ct.Id );
            }//for 1
        }//if 1

 

 

After wasting 1.5hrs, I can't get a standard controller test to even run, let alone pass, as the test thinks the campaign var in the controller is set to null, which hints that the constructor isn't running, but I can't figure out why.  I tried manually assigning a campaign to the controller var, but that didn't work either.

 

Anyone have any ideas?

 

Page

<apex:page standardController="Campaign" extensions="g2wPollChart1Controller">
    <apex:image url="{!chartData}"></apex:image>
</apex:page>

 

Controller (fails with getChartData calling g2wUtils.pollChartQuerySQL as the test thinks the campaign is null)

public with sharing class g2wPollChart2Controller {
    private String chartData;
//    private String chartTitle;
    private Integer pollNum;    

    private Campaign camp;
    
    public g2wPollChart2Controller (ApexPages.StandardController stdController) { 
        pollNum=2;//This is the only thing that changes between the 5 chart controllers
        
        this.camp = (Campaign)stdController.getRecord();  
        String query=g2wUtils.pollChartQuerySql(pollNum, camp.Id);
        camp=database.query(query);
    }//g2wPollChart1Controller Constructor
    
    public String getChartData(){
	    Integer width=500;
	    Integer height=200;
	    String chartData=g2wUtils.pollChartURL(camp, pollNum, width, height);
	    return chartData;                
  }//getChartData

}//g2wPollChart1Controller

 

Test

static testMethod void verifyPollChartControllers(){
//Bunch of code to create a campaign with the right data
//...
//Then the heart of the test
		PageReference pageRef=Page.g2wPollChart1;
		Test.setCurrentPage(pageRef);
		ApexPages.StandardController sc=new ApexPages.StandardController(campaigns[0]);
				
        	g2wPollChart1Controller cont = new g2wPollChart1Controller(sc);

//This is where the Error occurs:
	String getChartData=cont.getChartData();

    }

 

What is the full URL for a VF page called "myPage" in a sandbox?  For a 3rd party developer key, I need to register all of the subdomains for visualforce the various instances like CS0-CS15, but I don't know what the sandbox URL structure for VF pages is.

 

For example - this is the URL on na11 in production:

https://c.na11.visual.force.com/apex/myPage

 

What would it be in CS1?  Something like these?

https://c.tapp.cs1.visual.force.com/apex/myPage

 

or

https://c.tapp.cs1.visual.force.com/apex/myPage


Thanks!



A customer received this exception:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Apex script unhandled exception by user/organization: <userId>/<orgId>

Visualforce Page: /apex/g2wintegration__g2wInitialize

 

caused by: System.ListException: Row with duplicate Name at index: 2

Class.g2wIntegration.g2wUtils.g2wAccessTokenURL: line 99, column 1
Class.g2wIntegration.g2wInitializeController.autoRun: line 24, column 1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Line 99 refers to this line, which invokes the code to grab the custom list setting rows:

Map<String, G2WAccessTokens__c> tokens = G2WAccessTokens__c.getAll();

 

I interpret that error as there are two custom setting rows with the same name - is that accurate? If so, there seems to be a bug in Custom Settings.

In any custom list setting, the name must be unique, but somehow this was not the case for this customer.

 

We set the name to the UserId and have additional checks to ensure if the setting exists, that it gets updated versus trying to insert a new one. Even if code wasn't in place, inserting a 2nd row with the same name throws an exception in Apex, but that didn't happen.

 

Is there any way 2 custom list setting rows can be inserted twice?  All of our tests to reproduce this issue throw exceptions as Apex doesn't allow inserting 2 with the same name.  

Gotta start first with a rant - the libraries used for DateTIme methods are a piece of crap due to bugs & missing basic functionality.

 

Now that that's out of the way, anyone have ideas on how to get the difference of 2 different DateTime's?  The use case is to ensure that our time stamps are correct so that when we use DateTime1>DateTIme2, it works as expected, which we've manually verified. 

 

Attempt 1: Simple subtraction doesn't work as its not supported

Attempt 2: Convert to double doesn't work as it converts the DateTime to # miliseconds (??) which is more than a 64bit double can handle.  (nevermind that you can't even set milliseconds)

Attempt 3: Convert both to date, use .daysBetween() -too much work as have to basically rebuild the library to handle midnight, new hours, new minutes, etc. 

It seems that as of Winter '12, there was a change in how tests handle scheduled jobs.

 

Before Winter '12, we had code that woke up a scheduler, but the execute method wasn't fired.

 

After Winter '12, that same code fails as the scheduler is now firing the execute method (which happens to create 2nd batch job in the same test).

 

Bug or expected behavior?

 

Example:

test.startTest();                    
  system.schedule('Some scheduled job', varForStartTime, new someSchedulerClass()); 
test.stopTest();

 

global with sharing class someSchedulerClass implements Schedulable{
    global void execute(SchedulableContext ctx) {
		someMethodThatFiresBatchJob();
    }//execute
}

 Removing test.startTest() and test.stopTest() fixes the problem as then the execute method doesn't fire.  

On our na3 & na11 orgs, we have the Winter '13 icon so I'm assuming we are on Winter '13, but when clicking Versions, then Push Uprades, we can't select any major release, only patch versions.  Selecting an existing patch org doesn't list any possible orgs either from other major versions. 

 

What are we missing here? How do we enable push major?  

 

The doc doesn't say any special perms are needed and we've had the patch perm for a while now. We don't have any install scripts yet, but will have to create one due to the questionable decision to only allow admins to get new features by default.  

 

 

One of our customers is seeing this error when our app tries to insert campaign members:

INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY, insufficient access rights on cross-reference id: []

 

The gist of the code:

1) Find leads & contacts that match the criteria

2) Add them with the same campaignId to a CampaignMember list

3) Try to insert the CM list, which then errors

 

An admin is the context user, sharing is public, though there is a lead assignment rule that changes the lead owner to another admin, though she doesn't have the Marketing user checkbox (shouldn't matter though).

 

Any ideas?

 

Code snippets:

                            List<Contact> contacts=[SELECT Id, FirstName, LastName, Email, AccountId FROM Contact WHERE Email IN: emailToRegistrant.keySet()];
                            if(contacts.size()>0){
                                Set<string> contactEmailsAlreadyProcessed=new Set<String>();
                                for (contact ct:contacts){
                                    //This handles the case where there are 2+ contacts with the same
                                    //email address.  Otherwise, emailToRegistrant will be blank for the 2nd
                                    //one as we remove the emails so they aren't processed for Leads
                                    if(contactEmailsAlreadyProcessed.contains(ct.email)==FALSE){
                                        contactEmailsAlreadyProcessed.add(ct.email);
                                        CampaignMember cmToInsert=new CampaignMember();
                                        cmToInsert.ContactId=ct.Id;
                                        cmToInsert.CampaignId=c.Id;
                                        cmToInsert.status=g2wUtils.setCMStatus(emailToRegistrant.get(ct.email).status);
                                        cmToInsert.g2wRegistrantKey__c=emailToRegistrant.get(ct.email).registrantKey;
                                        cmsToInsert.add(cmToInsert);                                
                                        emailToRegistrant.remove(ct.email);
                                    }//if 5
                                }//for 1
                            }//if 4
                            
                            List<Lead> leads=[SELECT Id, FirstName, LastName, Email, Company FROM Lead WHERE Email IN: emailToRegistrant.keySet()];
                            if(leads.size()>0){
                                Set<string> leadEmailsAlreadyProcessed=new Set<String>();
                                for (Lead l:leads){
                                    if(leadEmailsAlreadyProcessed.contains(l.email)==FALSE){
                                        leadEmailsAlreadyProcessed.add(l.email);
                                        CampaignMember cmToInsert=new CampaignMember();
                                        cmToInsert.LeadId=l.Id;
                                        cmToInsert.CampaignId=c.Id;
                                        cmToInsert.status=g2wUtils.setCMStatus(emailToRegistrant.get(l.email).status);
                                        cmToInsert.g2wRegistrantKey__c=emailToRegistrant.get(l.email).registrantKey;
                                        cmsToInsert.add(cmToInsert);                                
                                        emailToRegistrant.remove(l.email);
                                    }//if 5
                                }//for 1
                            }//if 4
Database.insert(cmsToInsert);

 The last line is where the error occurs.  

Hello,

 

I have my package and a Schedulable class, I want to create a Schedule job in a Post Install Script.

 

Anybody can help me?

I was hoping to make <apex:tabPanel> behave nice and select one tab if the app hasn't been set up and the other if it has but ran into two problems:

1) Trying to set selectedTab to a dynamic value doesn't seem to work

2) Using value= doesn't work as then the user can't ever click on the other tab

 

Any tips I'm missing?  I hoped something like this would have worked:

<apex:page id="thePage" controller="controller">
    <apex:tabPanel switchType="client" selectedTab="{!selectedTab}" id="theTabPanel">
        <apex:tab label="One" name="name1" id="tabOne">content for tab one</apex:tab>
        <apex:tab label="Two" name="name2" id="tabTwo">content for tab two</apex:tab>
    </apex:tabPanel>
</apex:page>

And the apex class, where "schedulersActive" is set in another method.  This code works if using value="{!selectedTab}" but not for selectedTab as shown above.

public with sharing class controller{
	public String selectedTab{
		get{
			if (schedulersActive==TRUE)
				return 'name1';

			else
				return 'name2';
			
		}
		set;
	}//getSelectedTab
}

 

Salesforce lists have a View & Del link for every row.  I know how to make the view link, but haven't been able to figure out how to get any other action to target that specific row. 

 

Currently I'm using Dynamic Binding to show the list as the target is a protected custom setting, but I can probably use any list code like a pageBlockTable if that's easier.  The use case here is to show the name of each row (which is the userId), and delete the row using a button, similar to Salesforce lists.

 

Current sample code:

 

<apex:page standardController="Account"  extensions="DynamicAccountFieldsLister"> 

    <apex:pageMessages /><br/>
    
    <apex:form>
        <apex:pageBlock title="Edit Account" mode="edit">
            <apex:pageBlockSection columns="1">
                        <apex:commandLink value="View"  action="/{!r.Id}"/>                                        
                <apex:repeat value="{!editableFields}" var="f">
                    <apex:inputField value="{!Account[f]}"/>
                </apex:repeat>
           </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
    
</apex:page>

 

 

public class DynamicAccountFieldsLister {

    public DynamicAccountFieldsLister(ApexPages.StandardController controller) { 
        controller.addFields(editableFields);
    }

    public List<String> editableFields {
        get {
            if (editableFields == null) {
                editableFields = new List<String>();
                editableFields.add('Industry');
                editableFields.add('AnnualRevenue');
                editableFields.add('BillingCity');
            }
            return editableFields ;
        }
        private set;
    }
}

 

 

A customer received this exception:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Apex script unhandled exception by user/organization: <userId>/<orgId>

Visualforce Page: /apex/g2wintegration__g2wInitialize

 

caused by: System.ListException: Row with duplicate Name at index: 2

Class.g2wIntegration.g2wUtils.g2wAccessTokenURL: line 99, column 1
Class.g2wIntegration.g2wInitializeController.autoRun: line 24, column 1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Line 99 refers to this line, which invokes the code to grab the custom list setting rows:

Map<String, G2WAccessTokens__c> tokens = G2WAccessTokens__c.getAll();

 

I interpret that error as there are two custom setting rows with the same name - is that accurate? If so, there seems to be a bug in Custom Settings.

In any custom list setting, the name must be unique, but somehow this was not the case for this customer.

 

We set the name to the UserId and have additional checks to ensure if the setting exists, that it gets updated versus trying to insert a new one. Even if code wasn't in place, inserting a 2nd row with the same name throws an exception in Apex, but that didn't happen.

 

Is there any way 2 custom list setting rows can be inserted twice?  All of our tests to reproduce this issue throw exceptions as Apex doesn't allow inserting 2 with the same name.  

This smells like a bug:

1) Create button that inserts cron triggers

2) Create button that aborts these same cron triggers

3) Have standard or read only (non-admin) user click the button 

4) Have that same user click button to delete crontriggers

 

Expected:

Same permissions apply to #3 & #4

 

Actual:

User can insert, but gets Insufficient Privileges error on abort

 

Is there any way to drop into system mode for these users?  Everything works fine with admins.

 

Insert code sample:

                                    system.schedule('Get Webinars', getWebinarsSchedulerStartTime, new g2wGetWebinarsSchedulerExecute()); 
                                    system.schedule('Get Registrants', getRegistrantsSchedulerStartTime, new g2wGetRegistrantsSchedulerExecute()); 
                                    system.schedule('Get Registrant Details', getRegistrantDetailsSchedulerStartTime, new g2wGetRegistrantDetailsSchedulerExecute()); 
                                    system.schedule('Get Sessions', getSessionsSchedulerStartTime, new g2wGetSessionsSchedulerExecute()); 
                                    system.schedule('Get Webinar Attendees', getAttendeesSchedulerStartTime, new g2wGetWebinarAttendeesSchedulerExecute()); 

 

 

Abort code sample:

List<CronTrigger> cts=[SELECT Id, NextFireTime, State FROM CronTrigger WHERE (CronExpression =: g2wUtils.getWebinarsSchedulerStartTime OR CronExpression =:g2wUtils.getRegistrantsSchedulerStartTime OR CronExpression =:g2wUtils.getSessionsSchedulerStartTime OR CronExpression =: g2wUtils.getRegistrantDetailsSchedulerStartTime OR CronExpression =: g2wUtils.getAttendeesSchedulerStartTime) AND State != 'DELETED'];
        if (cts.size()>0){
            for(CronTrigger ct:cts){
                system.abortJob(ct.Id );
            }//for 1
        }//if 1

 

 

After wasting 1.5hrs, I can't get a standard controller test to even run, let alone pass, as the test thinks the campaign var in the controller is set to null, which hints that the constructor isn't running, but I can't figure out why.  I tried manually assigning a campaign to the controller var, but that didn't work either.

 

Anyone have any ideas?

 

Page

<apex:page standardController="Campaign" extensions="g2wPollChart1Controller">
    <apex:image url="{!chartData}"></apex:image>
</apex:page>

 

Controller (fails with getChartData calling g2wUtils.pollChartQuerySQL as the test thinks the campaign is null)

public with sharing class g2wPollChart2Controller {
    private String chartData;
//    private String chartTitle;
    private Integer pollNum;    

    private Campaign camp;
    
    public g2wPollChart2Controller (ApexPages.StandardController stdController) { 
        pollNum=2;//This is the only thing that changes between the 5 chart controllers
        
        this.camp = (Campaign)stdController.getRecord();  
        String query=g2wUtils.pollChartQuerySql(pollNum, camp.Id);
        camp=database.query(query);
    }//g2wPollChart1Controller Constructor
    
    public String getChartData(){
	    Integer width=500;
	    Integer height=200;
	    String chartData=g2wUtils.pollChartURL(camp, pollNum, width, height);
	    return chartData;                
  }//getChartData

}//g2wPollChart1Controller

 

Test

static testMethod void verifyPollChartControllers(){
//Bunch of code to create a campaign with the right data
//...
//Then the heart of the test
		PageReference pageRef=Page.g2wPollChart1;
		Test.setCurrentPage(pageRef);
		ApexPages.StandardController sc=new ApexPages.StandardController(campaigns[0]);
				
        	g2wPollChart1Controller cont = new g2wPollChart1Controller(sc);

//This is where the Error occurs:
	String getChartData=cont.getChartData();

    }

 

What is the full URL for a VF page called "myPage" in a sandbox?  For a 3rd party developer key, I need to register all of the subdomains for visualforce the various instances like CS0-CS15, but I don't know what the sandbox URL structure for VF pages is.

 

For example - this is the URL on na11 in production:

https://c.na11.visual.force.com/apex/myPage

 

What would it be in CS1?  Something like these?

https://c.tapp.cs1.visual.force.com/apex/myPage

 

or

https://c.tapp.cs1.visual.force.com/apex/myPage


Thanks!



Does anyone have experience working with the GoToWebinar REST API (http://tinyurl.com/8y82a4f).  Specifically, I am trying to determine if Registrations could be pushed into SFDC Leads.  Is this possible?

 

We have a lot of customers on different versions of our package - this was before patch upgrades were available.

 

I would like to "push" the latest version to everyone, assume that everything is backward compatible.

 

I am wondering whether I can do the following:

 

1. Create a patch upgrade to our latest package say 1.45 - so the patch version would be 1.45.1

2. Push 1.45.1 it to all customers that might be on 1.25 or 1.34 or 1.45.

 

Note that we have added new fields/classes/vf pages. So customers with 1.25 or 1.34 should get these new components.

 

The documentation says that push upgrades can be sent to all customers with same major release - i.e 1.x version, but not 0.x version . So seems like it can be done. But patch releases cannot add new components according to documentation as well...

 


Also, do I need to know all the subscribers or salesforce knows automatically? Is there any depedency on LMA - i.e it knows only subscribers only after LMA was installed in some other org?

 

 

 

 

 

 

 

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