You need to sign in to do that
Don't have an account?
Trigger not firing
Hi,
I'm trying to develop a very simple trigger that essentially creates a contact and a few contact share records when a User record is created.
In my dev environment the trigger and all of the unit tests work flawlessly, when I transfer to production the trigger doesn't even fire and as a result my unit tests fail.
When I run the tests I get no indication that the Trigger even attempted to run, let alone some error to tell me why it might be failing. Also, System.Debug within the Trigger doesn't show in my test output.
The trigger itself is below. I can post the support class code if needed but it doesn't seem to be getting that far so I don't know if it will help.
Any help is greatly appreciated.
Thanks
Jon
trigger User_Create_ContactSharing_Trigger on User (after insert)
{
// User Create ContactShareing Trigger
System.Debug('Inside Insert Trigger');
//get the user data and pass to the function in our support class
User[] theUsers = [select id,name,firstname,lastname,companyname, email, phone, defaultcurrencyisocode from User where id in :trigger.new];
//loop through all new users
for(User newUser :theUsers){
User_Contact_Trigger_Class.User_Create_Trigger(newUser);
}
}
I am not able to deploy to production because the unit tests fail and as a result I get 0% coverage of the code. I am testing from within Eclipse and because the trigger is not firing the test results are not what is expected and so my assertions all fail.
This same code works perfectly in my development environment.
OK - when you deploy your code, are you making sure you're deploying both these:
User_Contact_Trigger_Class
User_Create_ContactSharing_Trigger
And not just:
User_Contact_Trigger_Class
?
Yes I am deploying everything.
I have tried the standard deployment process (force.com/deploy to server... menu item) and I have also tried to create the triggers and class as a new production project in eclipse then copy/paste the code to the new project. The code will not save to production using the later method because the unit tests are failing.
Thanks for your help
Jon
I guess that gets the obvious problems out of the way. Can you post the code you've written for your unit tests for this particular trigger? In order for your trigger to fire, you'd have to have a unit test that performs an insert of a user.
I can post everything if you want, but I didn't want to confuse things by providing too much info.
To give you the full big picture. The aim of this trigger is, upon insert of a new user a contact should be created with that user's contact info, then a series of contact shares should be created to go along with it.
Anyway, I have to post this in pieces because this forum won't let me post it all at once.
First the code that the trigger should be calling.
{
//User Trigger support and unit test class
// Harvest Solutions 2009
//deal with new user create trigger
public static void User_Create_Trigger(User newUser){
//grab the current user, so that we can do user DML (Correction, this doesn't seem to help)
User theCurrentUser = [ select Id from User where Id = :UserInfo.getUserId() ];
//get the account that the new contact will belong to
Account theAccount = [select id from Account where name = :newUser.companyname];
//create a contact record for this user, linking to account specified in Company field on user record
Contact newContact = new Contact();newContact.firstname = newUser.firstname; //first
newContact.lastname = newUser.lastname; //and last
newContact.recordtypeid = '012600000000ygPAAQ';//newContact.nickname__c = 'user1';
newContact.accountid = theAccount.id;
newContact.contact_type__c = 'Employee';newContact.leadsource = 'Other';newContact.currencyisocode = newUser.defaultcurrencyisocode;
newContact.eMail = newUser.eMail;
newContact.phone = newUser.phone;
newContact.Employee_UserId__c = newUser.id;
System.Debug('AccountId: ' + theAccount.id);
System.runAs (theCurrentUser)
{
insert newContact;System.Debug('New ContactId: ' + newContact.id);}
//get list of all contacts in above company/Account
Contact[] theContacts = [select id,name,employee_userid__c from Contact where accountid = :theAccount.id];
//loop through all contacts and add new contactshare records
for(Contact aContact :theContacts){
//create a new contact share record to give the new usercontact access to each contact
ContactShare newContactShare = new ContactShare(); newContactShare.ContactAccessLevel = 'Read';newContactShare.ContactId = aContact.id; //the contactid of the existing contactuser
newContactShare.UserOrGroupId = newUser.id; //the userid of the new user
insert newContactShare;
//create a new contactshare record to give each existing contact access to the new usercontact
ContactShare newContactShare2 = new ContactShare(); newContactShare2.ContactAccessLevel = 'Read';newContactShare2.ContactId = newContact.id; //the contactId of the new user
newContactShare2.UserOrGroupId = aContact.employee_userid__c; //the userId of the existing contactuser
}
}
}
and here is the unit test code (Sorry, the forum made a mess out of it)
//************** Unit Tests *************
{
//unit test to test User_Create_ContactSharing_Trigger and associated class code
//grab the current user, so that we can do user DML
User thisUser = [ select Id from User where Id = :UserInfo.getUserId() ];System.Debug('UserId: ' + thisUser.id);//grab the account that the new user will be associated with
Account theAccount = [select id from Account where name = 'TheComanyName'];
System.Debug('AccountId: ' + theAccount.id);//grab the profile Id to use later
Profile theProfileId = [select id from Profile where name = 'Standard User'];System.Debug('ProfileId: ' + theProfileId.id);//create a contact to add a contactshare link to
Contact newContact = new Contact();newContact.firstname = 'Jane'; //first
newContact.lastname = 'Smith'; //and last
newContact.recordtypeid = '012600000000ygPAAQ';//newContact.nickname = newUser.CommunityNickname;
newContact.accountid = theAccount.id;
newContact.contact_type__c = 'Employee';newContact.leadsource = 'Other';newContact.currencyisocode =
'USD';newContact.eMail = 'jane@smith.com';newContact.phone =
'617-555-1212';newUser.firstname = 'Joey';
newUser.lastname =
'tester';newUser.companyname = 'TheComanyName';
newUser.IsActive =
false;newUser.profileid = theProfileId.id;
newUser.username = 'joetester@thehotmail.com';newuser.email = 'joetester@thehotmail.com';newuser.alias =
'jtet';newuser.localesidkey = 'en_US';newuser.timezonesidkey =
'America/Panama';newuser.emailencodingkey = 'ISO-8859-1';newuser.languagelocalekey =
'en_US'; newuser.defaultcurrencyisocode = 'USD';//newuser.communitynickname = 'JoeCool';
//run this next DML call in the current user's context, to allow us to do setup objects as well as other objects
System.runAs (thisUser)
{
insert newUser; //this should fire the create trigger, creating a contact, and some associated contact shares
}
//test to verify that the new user has been created
integer theNewUserCount = [select count() from User where firstname = 'Joey' and lastname = 'tester' and companyname 'TheComanyName']; if (theNewUserCount > 0){
System.assert(true);}
else
{
System.assert(false);}
//test to verify that our new contact has been created
integer theNewContactCount = [select count() from Contact where firstname = 'Joey' and lastname = 'tester']; if (theNewContactCount > 0){
System.Assert(true);}
else
{
System.Assert(false); //false means that the new contact has not been created (This Assertion Fails!)
}
//test to verify that our new user has been added to all other usercontacts contact shares
integer theNewContactSharesCount = [select count() from ContactShare where userorgroupid = :newuser.id]; if (theNewcontactSharesCount > 0){
System.Assert(true);}
else
{
System.Assert(false); //false ,means that the new contactshare has not been created
}
Here are some first thoughts - these relate to your unit testing code.
User thisUser = [ select Id from User where Id = :UserInfo.getUserId() ];System.Debug('UserId: ' + thisUser.id);
>> Does this properly output a User Id when running the unit testing? Are you the user it outputs since you're executing the deployment?
newContact.recordtypeid = '012600000000ygPAAQ';
>> Does this record type exist in your production instance? Any time you hard code things like this, you should make sure it exists in the production database - not sure if this will have a big impact, but worth checking.
insert newContact;
>> You might want to add an assertion/check that makes sure that this gets inserted - if this doesn't insert properly this could cause some problems later on.
integer theNewUserCount = [select count() from User where firstname = 'Joey' and lastname = 'tester' and companyname 'TheComanyName']; if (theNewUserCount > 0)
>> Is there a missing "=" after companyname? If so, the syste might interpret this wrong and assert true even though this is really where it's failing.
Thanks
Jon
System.Debug('Inside Insert Trigger');
#2) Also, put a new System.Debug inside the loop in your trigger, something like:
System.Debug('Triggering for user Id: ' + newUser.Id);
That goes inside the loop:
for(User newUser :theUsers)
I'd like to know if none, only one, or both trigger in the debug log.
No I get no System.Debug from the trigger or the code that the trigger calls.
It seems that if the trigger fails for any reason it simply fails, with no indication of the problem, no errors, no debug, nothing.
I have been banging away at this and as a test I called the User_Create_Trigger function directly, passing my created user, after dissabling the call in the trigger. I did find an error that seems to relate to the existing contacts on the production system having incorrect data, but I'm having some difficulty nailing down exactly what the problem is. It may be a security issue, just trying to figure out what exactly the issue is.
Jon
I have exaustivly debugged all of the code, eliminating the triggers by calling the functions that the triggers would call directly. The unit tests cover 86% of the code and everything work perfectly.
This brings me back to the trigger code below, it just isn't firing no matter what I do. I must be doing something wrong in the trigger. I have pasted all of the triggers below again.
Somewhere along the way the triggers began spitting out this error, which means nothing whatsoever.
'Save error: Unable to perform save on all files: An unexpected error has occurred. Please try again, or check the log file for details. '
{
// User Create ContactShareing Trigger
// 2009
//
//when a user is created we must allow that user to synch their contacts to outlook
// in order for this to happen the user must have a duplicate contact in Salesforce
// the contact must be listed as a contact share in all contacts that the user will synch
// additionaly all other contacts must list this user in their contact share list
//get the name of the account that this user's contact record will be a child of
User[] theUsers = [select id,name,firstname,lastname,companyname, email, phone, defaultcurrencyisocode from User where id in :trigger.new]; //CommunityNickname, defaultcurrencyisocode
//loop through all new users
for(User newUser :theUsers){
User_Contact_Trigger_Class.User_Create_Trigger(newUser);
}
}
{
// User Create ContactShareing Trigger
// 2009
//
//when a user is created we must allow that user to synch their contacts to outlook
// in order for this to happen the user must have a duplicate contact in Salesforce
// the contact must be listed as a contact share in all contacts that the user will synch
// additionaly all other contacts must list this user in their contact share list
// similarly when a user is re-activated we must ensure that these items are complete
//
// finally when a user is deactivated these items should be delted
//
//
{
//only do this if the user was just deactivated
if ((trigger.old[i].isactive == true) && (trigger.new[i].isactive == false)){
//get the name of the account that this user's contact record will be a child of
User[] theUsers = [select id,name,firstname,lastname,companyname, email, phone, defaultcurrencyisocode from User where id = :trigger.new[i].id];{
User_Contact_Trigger_Class.User_Deactivate_Trigger(newUser);
}
}
//only do this if the user was just reactivated
if ((trigger.old[i].isactive == false) && (trigger.new[i].isactive == true)){
//get the name of the account that this user's contact record will be a child of
User[] theUsers = [select id,name,firstname,lastname,companyname, email, phone, defaultcurrencyisocode from User where id = :trigger.new[i].id];
//loop through all new users
for(User newUser :theUsers){
User_Contact_Trigger_Class.User_Create_Trigger(newUser);
}
}
}
}
Nope, it never gives me any Debug output from within the trigger.
It's like Salesforce.com just isn't firing the trigger. Is there some Security setting somewhere that I don't know about that turns triggers off?
Jon
Then I'm totally stuck, the trigger simply does not do anything at all and gives no indication of the problem with it.
I really appreciate your help btw. Thanks a ton.
Jon
You might want to consider starting a little smaller, using a before insert/before update trigger to set the value of a custom field inside the user object, just to make sure the trigger firing is working.
I'd suggest something like a datetime custom field, and then in the before insert/before update trigger just set the value of that field to be Datetime.Now(), or it could be Datetime.Today() - check the documentation.
Then when you make any update to a user, you can easily check if the trigger fired because the field will be updated.
So this might be a good way to prove that a trigger is at least firing. You should comment out your other code in the meantime so it doesn't interfere.
Note: You don't call update/insert in a before trigger because you're making changes to the record before the record is commited to the database, so it isn't necessary.
Thanks for the advice, I will try an ultra simple trigger just to prove that Triggers can work at all in this org.
I have written a number of triggers for a number of differens orgs but never had as much trouble as this one before. Of all of the custom software I have developed for Salesforce (APEX, s-Controls, External API) I have never has as much trouble as when developing Triggers.
Thanks again
Jon
So I wrote a super simple trigger that just checks a box upon update of a contact, complete with unit test.
Big surprise, the trigger doesn't work. I can save the unit test code but the trigger will not save. The Trigger can't get any simpler but it just will not save and will not fire under test from within Eclipse.
So I called Salesforce support.
Today I'm told that the latest update (3 weeks ago!) has apparently created some issue that is effecting "some" triggers. I am told that "they are working on it" and that they don't have any idea when it will be fixed.
They have been working on it for 3 weeks now! Needless to say I am a bit irritated by the whole situation, I have been banging my head against this thing for weeks with no headway only to find that Salesforce has introduced some bug that they can't fix in 3 weeks.
My super simple trigger,
{
{
theContact.testdata__c = true; //check the box
}
}
I haven't seen any particular problems with triggers since the latest update, so I'm not really sure if the issue they're having does/doesn't apply toyou.
I would recommend trying a before insert / before update trigger rather than an after update. First, it would be good to see if at least that type of trigger works, and second, that's the better way to do a trigger that updates a value on the same object.
If you do an "update" on the same object that's inside the "after" trigger, you'll end up calling the trigger again (and again and again and again, although Salesforce prevents that kind of recursion from happening).
It's better to change your trigger to be:
trigger TestTriggerAlpha on Contact (before update, before insert)
- This will call the trigger just before it saves the record in both update and insert scenarios
And then remove the "update theContact;" line from the loop - when you make changes in a "before" trigger, you're making the changes before the record is committed to the database, so you don't have to call insert/update, and therefore won't cause the trigger to fire again (and again and again).
And just an aside - it's a best practice not to call "update" or "insert" once per loop, instead you want to build a list of objects and then call insert once on the entire list - that limits the "insert/update" calls so you don't hit governor limits.
Hi,
Thanks and good catch on the infinite loop, I realized that after posting my last post. I changed it to after insert with the same results.
Of course, this may or may not explain why the real trigger is not working.
Eclipse doesn't really give me anything.
I get an error that states that my unit test coverage is 0% and I get a warning saying that my trigger was not saved to the server, only locally. Nothing usefull.
I'm waiting for a callback from Support, maybe they can enlighten me with more information about what the apparent bug really is.
Honestly, I wouldn't rely too much on their support to help you out. While they provide the apex platform, they really don't provide much assistance with particular issues relating to coding. You very well could have a bug, but you might want to keep trying if you don't hear from them in a day or so.
I'm pretty sure I found an issue with the asynchronous job scheduler not properly reporting the job status correctly, support created a case, I provided instructions to reproduce, and I've been waiting for about 6 weeks now.
Please take a look at my suggestions for changing from an "after" to a "before" trigger and see if that produces different results.
As well, after deployment (success or failure) there should be a debug log.
thanks Justin,
I'm going to put this asside for a day or so and come back with a fresh set of eyes. I'm too frustrated to think straight, thus my infinite loop above, and I have much better things to be frustrated with then this. :)
Thanks
Jon
Jon,
Are you using the Force.com IDE directly against a production organization?
If so, all the testing minimum requirements (75% code coverage, all triggers covered 1% or more) apply every time you save a file. In terms of how the IDE uses the Metadata API, saving a file is the same as using the API's Deploy() verb.
JonP
Hi,
I am developing in Eclipse.
I started out in Dev edition where I developed the original code, it works flawlessly with 80+ code coverage and no errors. I attempted to deploy to production in the normal fashion (Force.com/Depoloy to Server menu) but the deployment failed with no indication of the problem. So I created a new eclipse project in the production environment and copy/pasted my code there. Unfortunately I am not able to save, no error provided.
After hours of debugging and proving that all of the code in my support class and unit tests is working perfectly I come to the conclusion that my trigger simply is not firing. You can see the trigger code on page 3 message 15 of this thread. (http://community.salesforce.com/sforce/board/message?board.id=apex&view=by_date_ascending&message.id=12893#M12893)
If I bypass the triggers and call the support class code directly (the code that the trigger would normally call) from my unit tests, I get 86% code coverage and no errors. I figure that this leaves only the trigger code as the problem.
I have developed several triggers in the past and understand all of the requirements for unit testing and whatnot but perhaps I am missing something simple that is keeping this trigger from doing it's job.
Thanks
Jon
If this helps at all, the way I do my apex development is I create a sandbox off the production database (I'm on Enterprise, not sure which edition you are using), create the eclipse project against the sandbox environment, create/test the code, and then use the Deploy to Server feature to deploy to production.
My understanding is you can do this just as well from a dev account, but I find using a sandbox ensures that my development environment most closely matches production (the sandbox will have all the objects, custom fields, etc. - just no data), and the deploy feature does give a proper debug log if there are issues.
Jon,
Did you ever resolve why your trigger was not firing? I have a similar situation at the moment where my after insert, after update trigger fires after an insert operation but NOT after an update operation...
No, to be honest I havn't even looked at it in about a week.
If I come up with a solution I will post, though I don't expect any resolution with zero assistance from Salesforce.
I thought JustinC was telling you to change your trigger to a (before insert, before update), not AFTER insert.
If you make changes to it before the insert/update action, those changes you make to the trigger values will get updated when it saves.
trigger TestTriggerAlpha on Contact (after update) { // YOU DON'T NEED TO QUERY THE CONTACT // Contact[] theContacts = [select testdata__c from Contact where id in :trigger.new]; for (Contact theContact : Trigger.new) { theContact.testdata__c = true; //check the box // update theContact; } }
Also, you don't need to query the Contacts. Trigger.new returns a list of Contacts that are being updated. And I'm surprised that this code was able to compile because your select statement would have failed. Like I said, Trigger.new doesn't return a list of IDs, it returns the list of Contacts that are being updated. I have commented out the code that you don't need and highlighted the changes you need to your super simple trigger.
If you want to test those changes make sure to change your trigger definition to:
In your User_Create_Trigger, you also have a lot of calls that you don't need to make. I'll make the corrections while commenting out what you don't need.
You can also streamline your code when you are creating your ContactShares that you are inserting. Create a list of ContactShares before your FOR loop:
List< ContactShare > newContactShares = new List< ContactShare >();
Now instead of saying doing your insert statements, do
newContactShares.add( newContactShare );
newContactShares.add( newContactShare2 );
Now AFTER your FOR loop is finished you can say
insert newContactShares;
This will do one DML statement for ALL your new ContactShares instead of the multiple DML statements each time you go through the FOR loop. This will help you in case you run into any govener limits where Salesforce prevents you from doing a certain number of DML statements (insert, update, delete, upsert, etc)
Hope this helps.
Wyser, thanks for the help.
I made the suggested change to the trigger and have narrowed the error down to one particular line.
{
//Salesforce does not like this next line, if I include it the trigger code will not save.
User_Contact_Trigger_Class.User_Create_Trigger(newUser);
}
It references a method in the support class that is in your eMail above. I know that the syntax is correct because I have referenced this method the exact same way in my unit test in order to verify that the code is correct. It works fine.
User_Contact_Trigger_Class.User_Create_Trigger(newUser);
This makes me think that there may be some Security or scoping issue, but the account that I am using has a profile that is given security access to the class. As a test I added every profile available and still the trigger code above will not save.
btw, I also tried simply copying the code from the class directly into the trigger and even though I know that code is 100% perfect (fully tested and working fine) the trigger will not save. Of course I don't get any error, just "Save error: Unabel to perform save on all files: An unexpected error has occured. Please try again, or check the log file for details." I don't remember where to find this log file, I seem to remember it's buried in the eclipse directory structure somewhere. I will locate it and see if it has any clues.
As for the other comments below.
The System.RunAs stuff was just part of my testing, it doesn't seem to change anything one way or another.
The Account will always exist because there is a validation rule on the account that ensures that the account exists etc...
Thanks again
Jon
I'm not really concerned with any of the TestTriggerAlpha stuff, that was a quick and dirty trigger that I wrote just to prove is ANY trigger could work. I have since corrected my hasty mistakes and proved that I can make a trigger work, so I'm back to the original problem again. Thanks.
"Save error: Unabel to perform save on all files: An unexpected error has occured. Please try again, or check the log file for details."
I get an identical error for the metadata file.
The interesting thing is that I just located the log and found these two entries.
ERROR [16:10:27] (ProjectService.java:handleDeployResult:1772) - Save failed!
.
Created Time: 2009-02-25 10:14:12.828
Info
Thu Mar 12 16:10:27 EDT 2009
INFO [16:10:27] (DeployMessageExt.java:logMessage:181) - Got the following deploy messages [2]:
(1) filename = unpackaged/package.xml, result = SUCCESS, affect = changed, id = null, fullname = package.xml
(2) filename = unpackaged/triggers/User_Create_ContactSharing_Trigger.trigger, result = SUCCESS, affect = changed, id = 01q600000008RXMAA2, fullname = User_Create_ContactSharing_Trigger
These are in reverse chronological order so it says that the files saved to salesforce Successfully then it imediatly says that it failed. The code is, of course, not updated at salesforce.
Thanks
Jon
How would I do that? It's never been allowed in the past.
Is this something new that I don't know about, or is there some secret new way to make it possible.
If you could tell me I would really appreciate it and I will give it a try.
Thanks
Jon
If you can't do it through the web UI, then that means your in an EE/UE org and not a developer/Sandbox org, which mean in order to save your trigger you need unit-tests/code coverage for it. (the trigger and the class your trigger calls).
You'd find working in a sandbox or developer edition account and deploying your finished results to your production org much easier than trying to work in the production org directly.
Hi Simon,
I did start in a developer org, where my code works flawlessly, unit tests and all. I attempted to deply to my production org but it failed. After many attempts to deploy the normal way I thought I would try creating the code in production. So, using Eclipse, I created a new project in my production org and copy/pasted my code there. This should work since the code works in the other org right? No such luck. The trigger simply won't save, but I get no error to tell me why.
This is where I was when this thread started. The code that works fine in one org doesn't work in another. I'm not using any hard coded Ids and all of the fields exist, etc... All of my code in my support class as well as my unit tests works fine, the only code that doesn't work is in the trigger itself and then only one single line of code is at fault, but I can't see why.
This isn't my first trigger, I have been writing triggers for at least a year now. The code as it stands now is not the most efficient, I figured I would make it work at all before making it work well, but I can't get past making it work so making it work well is sort of pointless to spend time on.
Btw, my code coverage is currently 86% with the exception of the trigger code, which can't be tested because it wont save to Salesforce. I have tested all of the code in my support class by bypassing the trigger and calling it directly in my unit test, it works perfectly so it should also work perfectly when the trigger calls it.
Your help is greatly appreciated, I have been banging my head against this thing for weeks.
Many thanks,
Jon
So the whole issue isn't about the Trigger not firing, but about the trigger not being able to save to your developer org?
Have you tried removing that offending line to see if your trigger saves? Or creating new trigger from scratch?
Is the class global or public? But looking at what you have so far it seems to be right... you said you also tried to copy the logic into your trigger and that didn't work either?
Is there maybe an existing trigger already there in your developer org with the same name? Eclipse likes to keep them in sync, so if you're trying to overwrite a trigger that wasn't last modified by Eclipse, you'll have to synchronize that trigger instance (either from dev org to Eclipse or the other way around).
I don't know, I'm running out of ideas
I havn't attempted a deployment from Dev in weeks but as I recall there were no errors, just the typical "didn't save" error that gives no details.
The only items in the deployment list were the triggers and the support class which contains the unit tests.
I will transfer my current code back to dev and re-attempt to deply to production but, as you say a save from Eclipse and a Deploy from eclipse are eactly the same so I don't expect to have any different results.
Thanks
Ok, so don't ask my why or how (because I dont know) but the code that didn't work before now works in production.
It's the exact same code, I just copied it back to my dev org and deployed. I had to force eclipse to copy the code up to the dev server because it refused to synchronize but once I got the code up to the server and deployed it worked this time.
The one line that was stopping me from saving before is still there but today Salesforce is happy with it.
Thanks for the help guys, this one nearly killed me. :)
I am facing the same problem. My after insert trigger on User is not firing even in sandbox even though the trigger saves successfully. The trigger is not firing both from UI and test method. When I change the trigger to before insert, the test method shows some indication of of the trigger being fired, although it is not producing desired results(which I suppose is a different matter altogether) but the creation of a user from UI does not fire the trigger.
After reading this post, I tried a simple before insert trigger which sets the value of a custom field, but no success. The triggers wont fire.
Please help!!!
Thanks