• Steve Berley [Left Propeller]
  • NEWBIE
  • 25 Points
  • Member since 2015

  • Chatter
    Feed
  • 0
    Best Answers
  • 1
    Likes Received
  • 0
    Likes Given
  • 23
    Questions
  • 37
    Replies
I'm sending emails generated in Apex from Lightning.  The emails are sending but they're coming through without an email body, despite a classic email template being set.
 
EmailTemplate template = [Select id, subject from EmailTemplate where name = 'My Template' limit 1];
...
Messaging.SingleEmailMessage msg = new Messaging.SingleEmailMessage();
msg.setTemplateId(template.Id);   // <<--- look
...
system.debug(Messaging.sendEmail(emails,false) );

The SendEmailResult generated by the system.debug shows...
15:34:51:342 USER_DEBUG [35]|DEBUG|Messaging.SingleEmailMessage[
getBccAddresses=null;
getCcAddresses=null;
getCharset=null;
getEntityAttachments=null;
getFileAttachments=null;
getHtmlBody=null;
getInReplyTo=null;
getOptOutPolicy=SEND;
getOrgWideEmailAddressId=0D20U0000008P2cSAE;
getPlainTextBody=null;
getReferences=null;
getTargetObjectId=0030U00000eXdLNQA0;
getTemplateId=00Xf4000000h8eaEAA;    // <<--- look
getToAddresses=null;
getWhatId=null;
isTreatBodiesAsTemplate=false;
isTreatTargetObjectAsRecipient=true;
isUserMail=false;
]

getTemplateId is showing the correct id for the Classic Email Template.

So -- all is perfect, except the template isn't coming through in the email.

What am I missing?

Thanks,

Steve 
 
I know this is pretty obscure, but has anyone been successful running the command line FuseIT tool in a wine bottle? I'm trying to run it on my mac without needing a vm.

Alternatively, if you've found a way to automatically download backup files natively on a mac, I'd love to know.

Sometimes you just have to ask...

Thanks,

Steve 
I have three users. 
  • All use the standard System Administrator profile, Salesforce license as well as the same role and permission sets 
  • They're all using the same connected app client_id and client_secret.
  • The passwords are always submitted as PasswordToken
  • IP Relaxation is set to: Relax IP restrictions
  • Permitted users is set to: All users may self-authorize
  • I can login to the UI with any of the user id/password combinations 
  • I have an older app still that relies on password+token to login and have verified that the tokens are all working as well.
One userid/password combination is always successful the other two always fail.  When I curl with either of the two that fail, I get the dreaded 

{"error":"invalid_grant","error_description":"authentication failure"} errors and the login history for those users shows a status of Invalid Password, even though the password and token test to be good.

The only difference I can think of is the login that works is one that was used to create the org.

Needless to say this is driving me batty...

What do you all suggest?

Steve 
Using curl, we're able to connect to a sandbox and salesforce returns an access_token.

However, when we update curl to use the endpoint and credentials (client_id, client_secret, username, and password) for production, the system returns -- 

{"error":"invalid_grant","error_description":"authentication failure"}

The curl stament is as you'd expect...
curl https://login.salesforce.com/services/oauth2/token -d "grant_type=password" -d "client_id=ididididid" -d "client_secret=secretsecretsecretsecretsecretsecret" -d "username=usernameusername" -d "password=passwordtokenpasswordtoken"

The login accessing both environments is configured as an admin with api access.

The connected apps in the sandbox and prod are configured identically.

Stumped!

Thanks for your advice on this...

Steve 
I have a utility routine (pasted below) that I use for all writes to the database which lets me catch errors.  This works perfectly in all but one of my orgs.  In that org, I generate a ton of UNABLE_TO_LOCK_ROW errors.  This is probably because it's a very complex org with lots of processes, many external, updating data.

The method receives a list of SObjects which it acts upon. 

How would I go about re-querying the objects in the received list from this method using FOR UPDATE so I can quickly commit the changes while minimizing the lock time?
 
public static void saveList(string command, list<sobject> objList, string caller){
		if ( objList == null || objList.size() == 0 ) return;
		try {
			if (command == 'insert') insert objlist;
			else if (command == 'update') update objlist;
			else if (command == 'upsert') upsert objlist;
			else if (command == 'delete') delete objlist;
		} catch (exception e){
			logError(caller, e);
		}
	}



Thanks,

Steve 
I'm running into the dreaded too many query rows error on an iterable batch.  No matter the batch size I use, it immediately errors out; even if I set the batch size to 1.  Looking at the logs, it seems to happen while still in the start() method.

This is driving me nuts - I look forward to your insights...

Thanks!

Here's the batch...
global with sharing class update_MBI implements Database.Batchable<AggregateResult> {
	global update_MBI() { }
    global string mbiQuery = 'select account__c, sum(spend__c) spendLast12 from spend__c where age__c < 0 and age__c >= -12 group by account__c ';

	global Iterable<AggregateResult> start(Database.BatchableContext BC) {  
		return new mbiIterable(mbiQuery);
	}

   	global void execute(Database.BatchableContext BC, List<AggregateResult> scope) {
		list<account> u = new list<account>();
		for (AggregateResult ar : scope){
			id acctID = id.valueOf(string.valueOf(ar.get('account__c')));
			decimal newMBI = decimal.valueOf(string.valueOf(ar.get('spendLast12'))) / 12;
			u.add(new account(id=acctID, MBI_Monthly_Spend_Current__c = newMBI));
		}
		update u;
	} 

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

The Iterable 
public with sharing class mbiIterable implements Iterable<AggregateResult> {
    private String query;

    public mbiIterable(String soql){
		query = soql;
    }

    public Iterator<AggregateResult> Iterator(){
		return new mbiIterator(query);
    }
}

The iterator
public class mbiIterator implements Iterator<AggregateResult> {

  AggregateResult[] results { get;set; }
  Integer index { get;set; }

  public mbiIterator(String query) {
	  index = 0;
	  results = Database.query(query);
  }

  public Boolean hasNext(){
	  return results != null && !results.isEmpty() && index < results.size();
  }

  public AggregateResult next() {
	  return results[index++];
  }
}

 
I have a batch class that implements database.stateful so global values are visible across batches.  I then save the data in the finish method.

All worked fine until there was enough data involved that the save is now generating a Too Many DML rows error. 

I could use some guidance about a pattern to use to get around this issue as changing the batch size won't matter since the save needs to be in the finish method.

I realize this is a simplistic approach, but could I do something as basic as breaking the list to be saved into multiple lists then inserting them with separate commands but within the same context?
 
global class batchClass implements Database.Batchable<sObject>, database.stateful {

	global map<id, sobject> dataStruct;
        global string q = 'select whatever from sObject';

	global Database.QueryLocator start(Database.BatchableContext BC) {
		dataStruct = map<id, sobject>();
		return Database.getQueryLocator(q);
	}

   	global void execute(Database.BatchableContext BC, list<Item__History> scope) {
		dataStruct = batchClass_tools.processScope(scope, dataStruct);
	}

	global void finish(Database.BatchableContext BC) {
        insert dataStruct.values();
	}
}

 
Let’s say you’re helping someone run the errands of daily life.  A trip may contain the following segments…each is its own record in an object that are all children of an umbrella trip object
  1. pick them up
  2. go to the doctor
  3. stop at the drug store
  4. get groceries
  5. return them home
Each segment includes driving directions between the specific addresses, so #3 includes the directions from the doctor’s office to the drug store and #4 starts at the drug store’s address.
 
Let’s say #3 changes because you have to go to a different drug store, then #4 will also need updating since its origin changed.
 
Typically, you’d update #3 using a before trigger.  No problem.  The trigger’s scope is naturally limited to the updated record (#3) and doesn’t include #4 which also needs updating since its origin changed.  As you’d expect, doing all of the updates in an after trigger causes trigger recursion.
 
Here’re the questions…
  1. How do I structure my trigger so it updates the changed record and related records without causing trigger recursion?
  2. Is it possible to expand the scope of the before trigger to include the related records?
For a bit of extra fun… Above includes mention driving directions.  Those are being populated by an @future call out to Google Maps, which also needs to update the same records without causing trigger recursion.
 
Note:  I've left out the code since issue is more about patterns and coding strategy.
 
Thanks for your help…
 
When I search this site for help, i'm continually finding dead links.  Any idea why?  Is something wrong with the CMS?

For example, 6 of the 10 links on the first page of results for the following query are dead, saying "Sorry, the document you are looking for doesn't exist or could not be retrieved"

https://developer.salesforce.com/search?q=configuring%20communities

What's going on?
I'm experiencing the strangest change set problem.

I have a change set containing 88 items in my sandbox on CS1

I upload the changeset to prod and...
  1. the change set received in prod only contains one item - that's not even in the original set
  2. the change set in the sandbox now only contains the one unrelated item sent to prod.
  3. if I clone the sent in the sandbox - all 88 items re-appear
  4. If i promote the clone - the cycle starts over again.

What on earth could be going wrong?

Thanks...
 
Hello all,

I'd like to call Conga from batch apex and having no luck getting the Conga call to work.

Has anyone had success? 

Thanks,
I'm writing some generic code and want to refer to an sobject type using a variable.  The goal being to write code similar to ...
string t = 'custom_object__c';
list<t> objs = new list<t>(); // creating a list of custom_object__c's
Of course, string is not the right type for t, but thi sis the idea I'm trying to accomplish

Can this even be done in apex?  

Thanks,

 
I'm devleoping a batch apex engine that's data driven so the query string is stored in record of a custom object.

the start() method pulls the query string from the designated record of the custom object and returns it as its queryLocator.

If the start method finds that designated record has no query string, I want batch apex to quit gracefully.

How do I make this happen - form within the start method?

Thanks,

Steve 
I've got a requirement to handle a situation one way if a user changed a field and another way if it was changed by an automated process.  By automated process I mean anything other than a user on a keyboard (apex, batch apex, trigger, wfr, flow, process builder - you name it.).

I'm actually quite flexible on how I determine it - the challenge here is being accurate and scalable.

Thanks,
I love the weekly export service and how it can generates a full zip snapshot of your org.

While they're nice, what can yo do with them?  Specifically, is there a way to populate a sandbox by uploading zip file into the test org?

Thanks,
I'm running some code in a sandbox and am getting the error...
NO_MASS_MAIL_PERMISSION, Single email is not enabled for your organization or profile.: []

However, my as you can see in my email settings - my deliverability is set to All Email.  What am I missing?  
User-added image

Thanks,

Steve 
I'm working on a task where I need to analyze the changes users have made to lead and account data.  Querying and analyzing their respective history tables is easy.  However, I'm stuck on how to associate the changes with the corresponding user.

Any suggestions?

Thanks,
The following is example code but it gets the point across...
string query = 'select id, lastName, account.name, account.customField__c from contact';
list<contact> queryResults = Database.query(query);
How can I determine the fields in the query result using code?  


 
I often have SOQL queries that I'd like to make readibly available as custom report types for users.  However I find the custom report type UI to be quite unintuitive.

Has any one seen or created a cheat sheet that gives tips on representing soql queries as custom reports?

Thanks,
I am already certified as Dev-401.  If I continue to take my release tests and maintain my certification, what happens if I just ignore the new structure?
I love the weekly export service and how it can generates a full zip snapshot of your org.

While they're nice, what can yo do with them?  Specifically, is there a way to populate a sandbox by uploading zip file into the test org?

Thanks,
I'm sending emails generated in Apex from Lightning.  The emails are sending but they're coming through without an email body, despite a classic email template being set.
 
EmailTemplate template = [Select id, subject from EmailTemplate where name = 'My Template' limit 1];
...
Messaging.SingleEmailMessage msg = new Messaging.SingleEmailMessage();
msg.setTemplateId(template.Id);   // <<--- look
...
system.debug(Messaging.sendEmail(emails,false) );

The SendEmailResult generated by the system.debug shows...
15:34:51:342 USER_DEBUG [35]|DEBUG|Messaging.SingleEmailMessage[
getBccAddresses=null;
getCcAddresses=null;
getCharset=null;
getEntityAttachments=null;
getFileAttachments=null;
getHtmlBody=null;
getInReplyTo=null;
getOptOutPolicy=SEND;
getOrgWideEmailAddressId=0D20U0000008P2cSAE;
getPlainTextBody=null;
getReferences=null;
getTargetObjectId=0030U00000eXdLNQA0;
getTemplateId=00Xf4000000h8eaEAA;    // <<--- look
getToAddresses=null;
getWhatId=null;
isTreatBodiesAsTemplate=false;
isTreatTargetObjectAsRecipient=true;
isUserMail=false;
]

getTemplateId is showing the correct id for the Classic Email Template.

So -- all is perfect, except the template isn't coming through in the email.

What am I missing?

Thanks,

Steve 
 
I have three users. 
  • All use the standard System Administrator profile, Salesforce license as well as the same role and permission sets 
  • They're all using the same connected app client_id and client_secret.
  • The passwords are always submitted as PasswordToken
  • IP Relaxation is set to: Relax IP restrictions
  • Permitted users is set to: All users may self-authorize
  • I can login to the UI with any of the user id/password combinations 
  • I have an older app still that relies on password+token to login and have verified that the tokens are all working as well.
One userid/password combination is always successful the other two always fail.  When I curl with either of the two that fail, I get the dreaded 

{"error":"invalid_grant","error_description":"authentication failure"} errors and the login history for those users shows a status of Invalid Password, even though the password and token test to be good.

The only difference I can think of is the login that works is one that was used to create the org.

Needless to say this is driving me batty...

What do you all suggest?

Steve 
I have a utility routine (pasted below) that I use for all writes to the database which lets me catch errors.  This works perfectly in all but one of my orgs.  In that org, I generate a ton of UNABLE_TO_LOCK_ROW errors.  This is probably because it's a very complex org with lots of processes, many external, updating data.

The method receives a list of SObjects which it acts upon. 

How would I go about re-querying the objects in the received list from this method using FOR UPDATE so I can quickly commit the changes while minimizing the lock time?
 
public static void saveList(string command, list<sobject> objList, string caller){
		if ( objList == null || objList.size() == 0 ) return;
		try {
			if (command == 'insert') insert objlist;
			else if (command == 'update') update objlist;
			else if (command == 'upsert') upsert objlist;
			else if (command == 'delete') delete objlist;
		} catch (exception e){
			logError(caller, e);
		}
	}



Thanks,

Steve 
I'm running into the dreaded too many query rows error on an iterable batch.  No matter the batch size I use, it immediately errors out; even if I set the batch size to 1.  Looking at the logs, it seems to happen while still in the start() method.

This is driving me nuts - I look forward to your insights...

Thanks!

Here's the batch...
global with sharing class update_MBI implements Database.Batchable<AggregateResult> {
	global update_MBI() { }
    global string mbiQuery = 'select account__c, sum(spend__c) spendLast12 from spend__c where age__c < 0 and age__c >= -12 group by account__c ';

	global Iterable<AggregateResult> start(Database.BatchableContext BC) {  
		return new mbiIterable(mbiQuery);
	}

   	global void execute(Database.BatchableContext BC, List<AggregateResult> scope) {
		list<account> u = new list<account>();
		for (AggregateResult ar : scope){
			id acctID = id.valueOf(string.valueOf(ar.get('account__c')));
			decimal newMBI = decimal.valueOf(string.valueOf(ar.get('spendLast12'))) / 12;
			u.add(new account(id=acctID, MBI_Monthly_Spend_Current__c = newMBI));
		}
		update u;
	} 

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

The Iterable 
public with sharing class mbiIterable implements Iterable<AggregateResult> {
    private String query;

    public mbiIterable(String soql){
		query = soql;
    }

    public Iterator<AggregateResult> Iterator(){
		return new mbiIterator(query);
    }
}

The iterator
public class mbiIterator implements Iterator<AggregateResult> {

  AggregateResult[] results { get;set; }
  Integer index { get;set; }

  public mbiIterator(String query) {
	  index = 0;
	  results = Database.query(query);
  }

  public Boolean hasNext(){
	  return results != null && !results.isEmpty() && index < results.size();
  }

  public AggregateResult next() {
	  return results[index++];
  }
}

 
Let’s say you’re helping someone run the errands of daily life.  A trip may contain the following segments…each is its own record in an object that are all children of an umbrella trip object
  1. pick them up
  2. go to the doctor
  3. stop at the drug store
  4. get groceries
  5. return them home
Each segment includes driving directions between the specific addresses, so #3 includes the directions from the doctor’s office to the drug store and #4 starts at the drug store’s address.
 
Let’s say #3 changes because you have to go to a different drug store, then #4 will also need updating since its origin changed.
 
Typically, you’d update #3 using a before trigger.  No problem.  The trigger’s scope is naturally limited to the updated record (#3) and doesn’t include #4 which also needs updating since its origin changed.  As you’d expect, doing all of the updates in an after trigger causes trigger recursion.
 
Here’re the questions…
  1. How do I structure my trigger so it updates the changed record and related records without causing trigger recursion?
  2. Is it possible to expand the scope of the before trigger to include the related records?
For a bit of extra fun… Above includes mention driving directions.  Those are being populated by an @future call out to Google Maps, which also needs to update the same records without causing trigger recursion.
 
Note:  I've left out the code since issue is more about patterns and coding strategy.
 
Thanks for your help…
 
While MavensMate is riding off into the sunset, it's going to remain relevant for a bit.  That said, what's The Thing to use moving forward to connect VS Code, Atom, or Sublime to the Salesforce backend?

Thanks,

Steve 
I'm experiencing the strangest change set problem.

I have a change set containing 88 items in my sandbox on CS1

I upload the changeset to prod and...
  1. the change set received in prod only contains one item - that's not even in the original set
  2. the change set in the sandbox now only contains the one unrelated item sent to prod.
  3. if I clone the sent in the sandbox - all 88 items re-appear
  4. If i promote the clone - the cycle starts over again.

What on earth could be going wrong?

Thanks...
 
I'm devleoping a batch apex engine that's data driven so the query string is stored in record of a custom object.

the start() method pulls the query string from the designated record of the custom object and returns it as its queryLocator.

If the start method finds that designated record has no query string, I want batch apex to quit gracefully.

How do I make this happen - form within the start method?

Thanks,

Steve 
I've got a requirement to handle a situation one way if a user changed a field and another way if it was changed by an automated process.  By automated process I mean anything other than a user on a keyboard (apex, batch apex, trigger, wfr, flow, process builder - you name it.).

I'm actually quite flexible on how I determine it - the challenge here is being accurate and scalable.

Thanks,
I'm running some code in a sandbox and am getting the error...
NO_MASS_MAIL_PERMISSION, Single email is not enabled for your organization or profile.: []

However, my as you can see in my email settings - my deliverability is set to All Email.  What am I missing?  
User-added image

Thanks,

Steve 

I am following the guidelines from the Chatter guide and somehow I can't get the OAuth to work. 

 

It's not working from Java or curl.   Here is what I am doing:

 

mike$ curl --form client_id=3MVG9yZ.WNe6bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxu5AjB4oT9kxi8SEhY --form client_secret=26542xxxxxxxxxxx78  --form grant_type=password --form username=xxxxxxxx@gmail.com --form password=xxxxxxx https://na11.salesforce.com/services/oauth2/token

 

What I am getting is:

{"error":"invalid_grant","error_description":"authentication failure - Invalid Password"}

 

I double checked and I am getting into na11 with the right password.  Is there anything else I need to do?

 

Here are the settings in my remote access:

 



Applicationchatter



Callback URLhttps://na11.salesforce.com/ConnectTest/oauth/_callback /// temp one



No user approval required for users in this organizationNot Checked