function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
furamagfuramag 

Eclipse and error in trigger

I have a trigger. My trigger update one field in custom object. This is code of trigger:
Code:
trigger Update on Promotions__c (after insert, after update) {

Promotions__c[] opp = trigger.new;
String title = opp[0].Title__c;



String id = opp[0].Employee__c;

SFDC_Employee__c s = [SELECT Title__c FROM SFDC_Employee__c WHERE ID = :id];

s.Title__c = title;

update s;

}

 I tested my trigger in development version of salesforce. It wirked correct. Now I want to install this trigger to real version of salesforce.
To check my trigger and transfer it to real version I use Eclipse. But I have two errors when I check my trigger:
Code:
cvc-complex-type.2.4.b: The content of element 'ApexTrigger' is not complete. One of '{"http://soap.sforce.com/2006/04/metadata":status}' is expected.
Save error: unexpected token: Update

Why I have this errors and why I can't save this trigger to server (trigger_name -> Force.com -> Save to Server).

JonPJonP
The way to migrate a Force.com metadata component (such as a trigger) from one organization to another using the Force.com IDE, is to use the Deploy to Server wizard.  You can activate this wizard by right-clicking on the src folder and choosing Force.com > Deploy to Server...

This will guide you through the process of connecting to your production organization, selecting the components to deploy, and pre-validating and/or executing the deployment.

(If you tried to deploy to another organization by creating another Force.com Project connected to that organization, and dragging-and-dropping a .trigger file to the new project, you should know that this is not a supported action.  The IDE can't prevent you from dragging files from project to project within Eclipse, but this kind of drag-and-drop generally won't work--especially against a production org, where Apex code coverage requirements are enforced.)

Jon
furamagfuramag
In folder triggers I have two files: Update.trigger (it's my trigger) and Update.trigger-meta.xml .
Second file contain this code:
Code:
<—xml version="1.0" encoding="UTF-8" standalone="yes"–>
<ApexTrigger xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>13.0</apiVersion>
</ApexTrigger>

When I validate all my package I have many errors in Update.trigger-meta.xml:
Code:
cvc-complex-type.2.4.b: The content of element 'ApexTrigger' is not complete. One of '{"http://soap.sforce.com/2006/04/metadata":status}' is expected. (line 2)
SalesforceforGoogleAdWordsDocuments-meta.xml (line 2)
...

I don't understand why I need file Update.trigger-meta.xml and why I have errors in this file. I didn't change this file.
When I try to Deploy to Server I have an error "unexpected token: Update".


Message Edited by furamag on 10-22-2008 09:25 AM

Message Edited by furamag on 10-22-2008 09:25 AM
philbophilbo
Hey,

My 'meta' trigger files all contain the following tag:

    <status>Active</status>

Not sure why it would be missing from yours - but try adding it and see if your deploy suddenly works.  (This is within the 'ApexTrigger' block)

...you will also have to 'cover' this trigger with a Testmethod, if your target org is a Production org...


Message Edited by philbo on 10-22-2008 02:57 PM
furamagfuramag
I added "<status>Active</status>" to my 'meta' trigger file, but it didn't help me.
I already read about Testmethod, but I don't understand why I need to use Testmethod if I test my trigger in development accaunt. I tried to make Testmethod but I don't know what this method have to do and where I have to whrite this method.
philbophilbo
Hey,

Check the Apex language documentation for details (+ rationale) on how to write Testmethods for your code (can get it via the SF Help window).

Looking at your trigger...a few things to consider:

  1. It is not bulk-ready - if you ever go inserting multiple Promotion__c records via Dataloader, for example, you will only update the SFDC_Employee__c record corresponding to the zero'th Promotion__c.  Check the same documentation for info on making your triggers bulk-safe.

  2. The Employee__c lookup field on the Promotion__c object:  Can it ever be Null?  (i.e. is it a lookup rel'p, or is it master-detail?)  If it is ever null, the Select statement will throw an exception.  Also - if you can have more than one Employee__c records pointing at the same Promotion__c record, the Select statement will also throw a (different) exception, as you are then trying to assign a list of records to a non-list variable.  You should probably account for these possibilities in your trigger, unless you are super-sure they will never occur in any of your orgs.
furamagfuramag
Thanks for reply.
Where I have to write my test class? In eclipse or in my development accaunt?
furamagfuramag
Now, when I press validate, I have only one error: "Save error: unexpected token: Update". What's it mean? How can I fix this error?
philbophilbo
Is your trigger the same as up at the top of this thread, or have you made any changes (e.g. per my earlier comments)?  If it has changed, can you re-post the new code?
furamagfuramag
This is code of my trigger:
Code:
trigger update on Promotions__c (after insert, after update) {

Promotions__c[] opp = trigger.new;
String title = opp[0].Title__c;

String id = opp[0].Employee__c;
id = str.substring(0,15);
SFDC_Employee__c s = [SELECT Title__c FROM SFDC_Employee__c WHERE ID = :id];

s.Title__c = title;

update s;

}

 

philbophilbo
Hey,

My guess is that you're trying to use a reserved word 'update' as the name of your trigger.  Why not try changing the trigger name - something like 'updateEmployees' or whatever - maybe this'll squash your problem.
JonPJonP
"Update" is a reserved word, so you will probably need to rename your trigger.


Message Edited by JonP on 10-23-2008 09:06 AM
furamagfuramag
Thank you! My trigger working. When I try to "Deploy to server" it deployed but in salesforce I see only:
Code:
trigger update_emp on Promotions__c (after insert, after update) {

}

 I don't know where is main part of trigger.
furamagfuramag
Please, give me sample of trigger and test class to this trigger or give me link to page in documentation where I can to see test class.
Where in Eclipse I have to write test class and how can I work with my trigger from test class.
I am already made 4 triggers, but I can't use it's in salesforce because I can't make test class.
furamagfuramag
My trigger:
Code:
trigger Unit_update on Promotions__c (after insert, after update) {

Promotions__c[] opp = trigger.new;
String title = opp[0].Title__c;

String id = opp[0].Employee__c;
id = id.substring(0,15);
SFDC_Employee__c s = [SELECT Title__c FROM SFDC_Employee__c WHERE ID = :id];

s.Title__c = title;

update s;

}



My test class:
Code:
public class Unit_update_test {

  public static testMethod void TestObj() {

    // Create a new Obj__c
    String id = opp.Employee__c;
    id = id.substring(0,15);
    Promotions__c opp = new Promotions__c(Name = 'test_trg', Employee__c = :id);

    insert opp;

    // Retrieve the Obj__c
    //Obj_c Obj2 = [select id, xxx from Obj__c where Id = :Obj.Id];
    String id = opp.Employee__c;
    id = id.substring(0,15);
    Promotions__c s = [SELECT Employee__c FROM Promotions__c WHERE ID = :id];

    // Test that the trigger worked
    System.assertEquals('Success', s.Employee__c);

  }

}

 
In my test class I have two errors:
1. Save error: unexpected token: :   line 8
2. List has no rows for assignment to SObject    line 16

How can I fix this errors?
JonPJonP
There are a few problems you will need to fix in your test method and in the trigger itself.  But this is exactly why Apex is designed to require unit tests!  Better to find and fix these issues yourself, than for your users to find them.

Let's start with the explicit compile errors in your test class:

1. As the error pretty clearly states, on line 8 the ":" character in ":id" does not belong, and should be removed.  The SOQL query language uses ":<variable>" notation to let you inject Apex variables into your search queries.  But line 8 is normal Apex code, not a SOQL query, so you don't need the ":".

2. On line 16 of your test class, you are assigning the result of a SOQL query to a singular variable.  SOQL queries return Lists.  The List may be empty, or only have one item in it, but it's still a List object.  You have two options here:  (1) Change the assignment variable to a List type, e.g.:
Code:
Promotions__c[] promotions = [SELECT Employee__c FROM Promotions__c WHERE ID = :id];

 or (2) add the LIMIT keyword to your SOQL query to ensure it returns a maximum of one result, so you can assign it directly to your singular variable:
Code:
Promotions__c s = [SELECT Employee__c FROM Promotions__c WHERE ID = :id LIMIT 1];

In this case, option 2 makes the most sense, because your search criteria is based on ID, so in reality you will only get 0 or 1 results.



Those changes will resolve your immediate issues, but there are a few other things you'll need to do before this trigger is ready to go live:
  • Your test method begins with String id = opp.Employee__c; but the opp variable isn't defined anywhere. I'm sure the compiler will raise this issue soon, once you've resolved the issues above.  You should actually insert a SFDC_Employee__c object within your test method, and use its Id as the value of Promotions__c.Employee__c.

  • It looks like your trigger expects a value in Promotions__c.Title__c.  In your test method, you are not specifying a value for this field when you insert the new Promotions__c object.  This is a great test case -- What happens if Title__c is null?  Do you need to check that?  Do you need a Validation Rule to ensure the field is always filled in by the user? -- but you also will want a test that actually provides a value for Promotions__c.Title__c.

  • The assertion at the end of your test doesn't will never be true, and isn't a useful test.  If I understand your trigger's intentions, you actually want to test that the value of SFDC_Employee__c.Title__c matches the value of Promotions__c.Title__c, where SFDC_Employee__c.Id = Promotions__c.Employee__c.  It's simple enough to write a query that will test those values.

  • Your trigger performs an unnecessary query on SFDC_Employee__c.  Rather than querying for the SFDC_Employee__c, changing its Title__c field, and updating it, you can just create a "new" SFDC_Employee__c and set its Id and Title__c fields, and use that to perform the update.  The update command will match on SFDC_Employee__c.Id and only update the other fields you have specified.  Thus you already have everything you need to perform an update within Trigger.new[], without doing that query:

    Code:
    Promotions__c promotion = trigger.new[0];
    
    SFDC_Employee__c s = new SFDC_Employee__c();
    s.Id = promotion.Id;
    s.Title__c = promotion.Title__c;
    
    //short form of the previous 3 lines: //SFDC_Employee__c s = new SFDC_Employee__c(Id = promotion.Id, Title__c = promotion.Title__c) update s;

  • Your trigger only works for one insert.  You absolutely will need to "bulkify" it, so that it loops through all the Promotions__c records in Trigger.new[], adding each SFDC_Employee__c record to a list of records to update, and then performs a bulk-update outside the loop.  You will also need to define a bulk test method, where you construct a list of two or more Promotions__c records and then insert that list with a single insert command.  Here's how you might bulkify your trigger:

    Code:
    trigger Unit_update on Promotions__c (after insert, after update) {
       Promotions__c[] promotionsToUpdate = new Promotions__c[0];
    
       for (Promotions__c promotion : trigger.new) {
    
          SFDC_Employee__c s = new SFDC_Employee__c();
          s.Id = promotion.Id;
          s.Title__c = promotion.Title__c;
    
          promotionsToUpdate.add(s);
       }
    
       update promotionsToUpdate;
    }

  • Remove the id = id.substring(0,15); lines from all your code.  This is completely unnecessary.

Implementing these changes should get you pretty close to what you need, I hope.

Unit testing definitely requires a shift in mindset, but it pays big dividend over time.  An advanced technique that is part of the Extreme Programming (XP) discipline is called Test Driven Development, in which you write your tests before you write your code.  This way, you work out the inputs and expected outputs before you write your code, so by the time you start writing the actual code you know more or less exactly what it needs to do.  Plus you know you're done when all your tests pass!

Happy coding,
Jon


furamagfuramag

1. As the error pretty clearly states, on line 8 the ":" character in ":id" does not belong, and should be removed.  The SOQL query language uses ":" notation to let you inject Apex variables into your search queries.  But line 8 is normal Apex code, not a SOQL query, so you don't need the ":".

When I delete ":" in this string "Promotions__c opp = new Promotions__c(Name = 'test_trg', Employee__c = :id)" I have an error: "Save error: Variable does not exist: id".
philbophilbo
Hey,

As a general rule you should avoid using reserved words as variable names.  If I were you I would change my 'id' variable to 'emplId' or something.  This may be what's causing your syntax error.
furamagfuramag
Employee__c is lookup field to object SFDC_Employee__c. If I replace id to EMP_ID__c I have same error "Save error: Variable does not exist: EMP_ID__c".
philbophilbo
Why don't you post your latest code.  Sounds like you're not declaring that variable.
furamagfuramag
I changed my test class:
Code:
public class Unit_update_test {

  public static testMethod void TestObj() {

    // Create a new Obj__c

    Promotions__c opp = new Promotions__c(Employee__c = 'a0A70000002lsUj', Title__c = '123456');

    insert opp;

    String id = opp.Employee__c;
    Promotions__c[] s = [SELECT Title__c FROM Promotions__c WHERE ID = :id];

    System.assertEquals('Success', s.Title__c);

  }

}

"a0A70000002lsUj" - id one of employee.

 And I have two errors:
1. Save error: Initial term of field expression must be a concrete SObject: LIST:SOBJECT:Promotions__c.
2. System.StringException: Invalid id: Success.

I tried to use "Promotions__c[] s = [SELECT Title__c FROM Promotions__c WHERE ID = :id];" and "Promotions__c s = [SELECT Title__c FROM Promotions__c WHERE ID = :id LIMIT 1];" but I have same errors.
furamagfuramag
I changed my class:
Code:
public class Unit_update_test {

  public static testMethod void TestObj() {

    // Create a new Obj__c

    Promotions__c opp = new Promotions__c(Employee__c = 'a0A70000002lsUj', Title__c = '123456');

    insert opp;

    // Retrieve the Obj__c
    //Obj_c Obj2 = [select id, xxx from Obj__c where Id = :Obj.Id];
    String id = opp.Employee__c;
    //id = id.substring(0,15);
    Promotions__c s = [SELECT Title__c FROM Promotions__c WHERE Employee__c = :id AND Title__c = '123456' LIMIT 1];

    // Test that the trigger worked
    System.assertEquals('123456', s.Title__c);

  }

}

 
But when I try to deploy to server I have an error "zipException: zip file must have at least one entry". How can I fix it?
JonPJonP
That error message sounds like what would happen if you deselected everything from your Deploy Plan in step 3 of the Deploy to Server wizard.  Assuming that's not the case, can you post a screenshot of page 3 of the Deploy to Server wizard, along with a screenshot of the error dialog?

Thanks,
Jon
salesforce.com Product Manager
furamagfuramag
Maybe I have this error because in step 3 Apply action in my trigger and class is "No action"?
JonPJonP
Yes, if the trigger in your deploy target organization is identical to the one in your project, by default it won't be deployed.

In the latest Force.com IDE (Winter '09 / 14.0) we've added the ability to override the "No Action" decision and deploy anyway.  If you haven't done so already, you may want to upgrade.

Note that there's no direct upgrade path from the Developer Preview releases (13.0 or older) of the IDE plug-in or projects. You'll need to uninstall the old plug-in and delete your old Force.com projects before installing 14.0, then recreate your projects.  Or you can just install a second copy of Eclipse for the 14.0 plug-in and gradually transition over to it.
furamagfuramag
Thanks! It's working.