3

I've been researching this and I am trying to use a VF page method of invoking an Apex class through a custom button. The method I am attempting to use is this :

Invoking Apex Code With a Custom Button Using a Visual Force Page

Right now, my code looks like this.

public class VFController {

    // Constructor - this only really matters if the autoRun function doesn't work right
    private final Contract_Overview__c o;
    public VFController(ApexPages.StandardController stdController) {
        this.o = (Contract_Overview__c)stdController.getRecord();
    }

    // Code we will invoke on page load.
    public PageReference autoRun() {

        String theId = ApexPages.currentPage().getParameters().get('id');

        if (theId == null) {
            // Display the Visualforce page's content if no Id is passed over
            return null;
        }

        for (Contract_Overview__c o:[select id, name from Contract_Overview__c where id =:theId]) {
            // Do all the dirty work we need the code to do

            public void CreateOpportunityWithChildren(Id  accountId) {

            // Query the countries related to this account
            List<Client_Profile__c> countryProfiles = [SELECT Id
                                            , Name
                                        FROM Client_Profile__c 
                                        WHERE Account_Name__c = :accountId];
            // Lists for DML operations
            List<Opportunity> OpportunitiesToInsert         = new List<Opportunity>();                                  
            List<Country_by_Country__c> OppyChildrenToInsert  = new List<Country_by_Country__c>();                              

            // create an opportunity to dangle opportunity children from
            Opportunity oppy = new Opportunity(Name = 'Your Oppy Name'
                                        , AccountId = accountId 
                                        , StageName = 'Prospecting'
                                        , CloseDate = Date.today().addDays(7));

            // add it to the list for later DML
            OpportunitiesToInsert.add(oppy);

            // for each countryProfile queried earlier, create an OpportunityChild
            for (Client_Profile__c countryProfile: countryProfiles) {

                // set the fields on the OpportunityChild
                Country_by_Country__c oppyChild   = new Country_by_Country__c();
                //oppyChild.Stage__c              = 'Prospecting';
                oppyChild.Account_Name__c        = accountId;
                oppyChild.Client_Country_Profile__c            = countryProfile.Id;

                // presumably there's a name like 'Argentina' in the name field
                //oppyChild.Name                  = 'CBC ' + countryProfile.Name;

                // set a reference between this child object and it's parent
                // (presuming there is a relationship between the two named Opportunity)
                oppyChild.Opportunity__r = oppy;

                // add this child to the list for later DML
                OppyChildrenToInsert.add(oppyChild);
            }

            // set up a transaction so that we can roll back in the event anything fails
            System.Savepoint sp1 = Database.setSavepoint();

            // try / catch around all of this DML
            try {
                // if any exist, first insert the parents
                if (!OpportunitiesToInsert.isEmpty()) {
                    insert OpportunitiesToInsert;
                }

                // if any exist, insert the children
                // ( Note: probably wouldn't do this work if there weren't any parents )
                if (!OppyChildrenToInsert.isEmpty()) {

                    // for all of the children that we are inserting, reach through the
                    // relationship between the two objects and get the ID assigned
                    // on the parent earlier during that DML operation
                    for (Country_by_Country__c oppyChild : OppyChildrenToInsert) {

                        // is there a relationship to a parent?
                        if (oppyChild.Opportunity__r != null) {

                            // reach through the relationship and get the ID from the parent
                            // and set that id value on the child
                            oppyChild.Opportunity__c = oppyChild.Opportunity__r.Id; 
                        }
                    }

                    // now that all of the children have the ID values of their parents
                    insert OppyChildrenToInsert;
                }

            } catch (Exception ex) {
                // log the exception
                system.debug(ex);

                // something failed, roll back the entire transaction
                Database.rollback(sp1);
            }
        }
        }

        // Redirect the user back to the original page
        PageReference pageRef = new PageReference('/' + theId);
        pageRef.setRedirect(true);
        return pageRef;

    }

}

I am currently getting this error on that code :

Save error: expecting a semi-colon, found '('

for line 22 which is this :

public void CreateOpportunityWithChildren(Id  accountId) {

That happens to be the very first line of my Apex class which I inserted into this code. I took out the line which originally went ahead of that line which was this :

public class MyControllerOppAndCBC {

I didn't think I needed it since it was now being put inside this code. I also took out the right curly bracket which went with that first line, but I don't think those changes would be cause for the error, but I could be very wrong.

I can't figure out what is up with this. Anybody got any ideas on this ? Does the rest of the code look proper to you ? I haven't gotten to my VF page yet.

Thank you very much for your help ahead of time.

1
  • 1
    You should understand the syntax of Apex before trying to write it. Specifically, do you understand what "public void..." means? It is a method declaration, but you have inserted it into another method declaration, which is never valid. Simply deleting that line may fix your issue, but I think you also have some unmatched curly braces which is also illegal. You should spend an hour or two on the basics of Apex syntax, it will help you a lot. – jkraybill Apr 2 '13 at 23:35
2
public class VFController {
// This is where you want to declare your public getter and private setter methods
// String theId = ApexPages.currentPage().getParameters().get('id'); 
// The above gets passed to you by reference. Its part of your getter method and is 
// superfluous. You do the same below at Opportunity o = (Contract_Overview__c)...

// the line below **does** belong here!    
public VFController(ApexPages.StandardController stdController) {

    Opportunity o = (Contract_Overview__c)stdController.getRecord();

try {
        opp = [SELECT 
                Id,
                AccountId,
                Amount,
                Name,
                Owner.Id,
                Any other fields you want to add,
                FROM Opportunity WHERE Id =: o.AccountId = Contract_Overview__r.Account.Id];
}
    catch(Exception e) {
        ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, e.getMessage()));
    }

I'm not certain of the relationship between Contract_Overview__c and Opportunity or Accounts. If the opp doesn't already exist, then you need to be querying on Account or Contract_Overview__c and fully understand the relationships between them. (I don't know your org, so can't determine exactly how an opportunity is related to Contract_Overview__c.)

// Code we will invoke on page load.
public PageReference autoRun() { 

From your original post, I understood that you were using a button to invoke this page?? If so and the Id is null, I suggest you add code to abort the button rather than adding this code into the controller! You can add code in the try/catch block to exit gracefully such as redirecting back to the original page as you've mentioned at the bottom of your code. I think that would be a better way of handling it if doing it on the controller, but everyone has their coding preferences.

try {
            // if any exist, first insert the parents
            if (!OpportunitiesToInsert.isEmpty()) {
                insert OpportunitiesToInsert;
            }

This should be followed by it's own catch block before moving onto the next insert operation. Further, I'd suggest adding code that allows partial success. Here's an example of what I'm speaking of:

    // after insertion (failures allowed), check for failures and debug

if(OpportunitiesToInsert.IsEmpty() == false){

list<Database.SaveResult> InsertResults = Database.Insert(OpportunitiesToInsert,false);
}

Doing that allows you to add debug code following the insertion on the InsertResults list (before the closing bracket) which can be very helpful when trying to debug your code or if you want to create a log of any and all errors that occurred while also allowing the records to still be created with non-fatal errors.

I believe your lack of catch blocks is very likely the source of many of your error messages. Your class is public, will have public get methods, but you'll probably want to have private setter methods which are declared as follows immediately below your class declaration in the portion of your code where I noted it above:

public Opportunity opp {get; private set;}

I hope this gets you pointed down the right path and HIGHLY recommend you go through the VisualForce Workbook, particularly chapters 12 and 13 from the SalesForce Developer site and chapter 17 of the Apex Workbook. I think you'll find that working through the tutorials in both will go a long way towards helping you in your endeavors. :)

3
  • Thank you very much for your input. Right now, I'm still trying to get the code to save, so I haven't even gotten it to run yet. I still have that error I named in my updated original post on line 22. I know I shouldn't have an additional method in there, but I don't know exactly how to insert my code into this VF Controller. I believe that original code for creating a new Opp and multiple OppChildren will work, but I can't test it yet because I can't get this whole method of using a button to open a VF page to invoke the code. Thanks again for your insight and help. – Zoom_v Apr 3 '13 at 18:11
  • @Zoom_v If you're working in the Salesforce on-line editor, enter a few lines at a time of your code, not everything at once. Save it as you go along. Clicking on braces will highlight matching braces, so you'll want to start by creating the outer shell and then adding code from the inside to help assure things match. You won't be able to safe until you have matching braces and code that will compile, thus the reason to do a "Quick Save" after every block of code that you add. Learning to understand what you're attempting by doing the tutorials NOW, may save you a LOT of time in finishing this – crmprogdev Apr 3 '13 at 21:46
  • I understand what you are saying and you're right of course. However, in this case I had two separate (functional) classes which I am attempting to put together. The first was the portion which was only meant to bring up a VF page in order to run a button on it ; and the second which was the code which that button invoked. So, I'm essentially trying to take two pieces of code and put them together. And now by doing that, I'm having all kinds of problems. – Zoom_v Apr 9 '13 at 16:17
0
  for (Contract_Overview__c o:[select id, name from Contract_Overview__c where id =:theId]) {
        // Do all the dirty work we need the code to do

        public void CreateOpportunityWithChildren(Id  accountId) {

I see as a simple syntax error .The for loop is not closed and defining method inside method is causing issues .

Please end the for loops properly and also terminate methods properly .The rest looks ok.Its mere syntax error .

1
  • Thank you very much for your help Mohith. I placed another right curly bracket above the "//Redirect the user back to the original page" line. I thought that would be the proper way to close the For loop. However, I'm still getting the same error. Thanks again. – Zoom_v Apr 2 '13 at 20:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.