Thursday 30 August 2012

Adding Action Methods to an Apex Controller

In this lesson, you’ll add action method to your controller to allow it to handle clicking a new Add to Cart button, as well as a new method that outputs the contents of a shopping cart. You’ll see how Visualforce transparently passes data back to your controller where it can be processed. On the Visualforce side you’ll add that button to the page, as well as form fields for shoppers to fill in.
  1. Click StoreFrontController to edit your page’s controller code.
  2. Add the following shopping cart code to the definition of StoreFrontController, immediately after the products instance variable, and then click Quick Save.
    List<DisplayMerchandise> shoppingCart = new List<DisplayMerchandise>();
    
    // Action method to handle purchasing process  
        
    public PageReference addToCart() {
        for(DisplayMerchandise p : products) {
            if(0 < p.qtyToBuy) {
                shoppingCart.add(p);
            }
        }
        return null; // stay on the same page  
        
    }
    
    public String getCartContents() {
        if(0 == shoppingCart.size()) {
            return '(empty)';
        }
        String msg = '<ul>\n';
        for(DisplayMerchandise p : shoppingCart) {
            msg += '<li>';
            msg += p.name + ' (' + p.qtyToBuy + ')';
            msg += '</li>\n';
        }
        msg += '</ul>';
        return msg;
    }
    
    Now you’re ready to add a user interface for purchasing to your product catalog.
  3. Click Catalog to edit your page’s Visualforce code.
  4. Wrap the product catalog in a form tag, so that the page structure looks like this code.
    <apex:page controller="StoreFrontController">
        <apex:form>
            <!-- rest of page code --> 
         
        </apex:form>
    </apex:page>
    The <apex:form> component enables your page to send user-submitted data back to its controller.
  5. Add a fourth column to the products listing table using this code.
    <apex:column headerValue="Qty to Buy">
        <apex:inputText value="{!pitem.qtyToBuy}" rendered="{! pitem.inStock}"/>
        <apex:outputText value="Out of Stock" rendered="{! NOT(pitem.inStock)}"/>
    </apex:column>
    
    This column will be a form field for entering a quantity to buy, or an out-of-stock notice, based on the value of theDisplayMerchandise.inStock() method for each product.
  6. Click Save and reload the page.There is a new column for customers to enter a number of units to buy for each product.
  7. Add a shopping cart button by placing the following code just before the </apex:pageBlock> tag.
    <apex:pageBlockSection>
        <apex:commandButton action="{!addToCart}" value="Add to Cart"/>
    </apex:pageBlockSection>
    If you click Save and try the form now, everything works…except you can’t see any effect, because the shopping cart isn’t visible.
  8. Add the following code to your page, right above the terminating </apex:form> tag.
    <apex:pageBlock title="Your Cart" id="shopping_cart">
        <apex:outputText value="{!cartContents}" escape="false"/>
    </apex:pageBlock>
    
  9. Click Save, and give the form a try now. You should be able to add items to your shopping cart! In this case, it’s just a simple text display. In a real-world scenario, you can imagine emailing the order, invoking a Web service, updating the database, and so on.
  10. For a bonus effect, modify the code on the Add to CartcommandButton.
    <apex:commandButton action="{!addToCart}" value="Add to Cart" reRender="shopping_cart"/>
    If you click Save and use the form now, the shopping cart is updated via Ajax, instead of by reloading the page.
    Product catalog page with custom controller, with cart

Tell Me More...

  • As you saw in this lesson, Visualforce automatically mirrored the data changes on the form back to the products variable. This functionality is extremely powerful, and lets you quickly build forms and other complex input pages.
  • When you click the Add to Cart button, the shopping cart panel updates without updating the entire screen. The Ajax effect that does this, which typically requires complex JavaScript manipulation, was accomplished with a simple reRender attribute.
  • If you click Add to Cart multiple times with different values in the Qty to Buy fields, you’ll notice a bug, where products are duplicated in the shopping cart. Knowing what you now know about Apex, can you find and fix the bug? One way might be to change a certain List to a Map, so you can record and check for duplicate IDs. Where would you go to learn the necessary Map methods…?

Using Inner Classes in an Apex Controller

In the last lesson, you created a custom controller for your Visualforce catalog page. But your controller passes custom objects from the database directly to the view, which is not ideal. In this lesson, you’ll refactor your controller to more correctly use the MVC design pattern, and add some additional features to your page.
  1. Click StoreFrontController to edit your page’s controller code.
  2. Revise the definition of the class as follows and then click Quick Save.
    public class StoreFrontController {
    
        List<DisplayMerchandise> products;
        
        public List<DisplayMerchandise> getProducts() {
            if(products == null) {
                products = new List<DisplayMerchandise>();
                for(Merchandise__c item : [
                        SELECT Id, Name, Description__c, Price__c, Total_Inventory__c 
                        FROM Merchandise__c]) {
                    products.add(new DisplayMerchandise(item));
                }
            }
            return products;
        }
        
        // Inner class to hold online store details for item 
        
        public class DisplayMerchandise {
    
            private Merchandise__c merchandise;
            public DisplayMerchandise(Merchandise__c item) {
                this.merchandise = item;
            }
    
            // Properties for use in the Visualforce view 
        
            public String name {
                get { return merchandise.Name; }
            }
            public String description {
                get { return merchandise.Description__c; }
            }
            public Decimal price {
                get { return merchandise.Price__c; }
            }
            public Boolean inStock {
                get { return (0 < merchandise.Total_Inventory__c); }
            }
            public Integer qtyToBuy { get; set; }
        }
    }
  3. Click Catalog to edit your page’s Visualforce code.
  4. Change the column definitions to work with the property names of the new inner class. Replace the existing column definitions with the following code.
    <apex:column headerValue="Product">
        <apex:outputText value="{!pitem.Name}"/>
    </apex:column>
    <apex:column headerValue="Description">
        <apex:outputText value="{!pitem.Description}"/>
    </apex:column>
    <apex:column headerValue="Price">
        <apex:outputText value="{!pitem.Price}"/>
    </apex:column>
    
    The outputField component works automatically with sObject fields, but doesn’t work at all with custom classes. outputText works with any value.
  5. Click Save to save your changes and reload the page. You’ll notice that the price column is no longer formatted as currency.
  6. Change the price outputText tag to the following code.
    <apex:outputText value="{0,number,currency}">
        <apex:param value="{!pitem.Price}"/>
    </apex:outputText>
    The outputText component can be used to automatically format different data types.
  7. Verify that your code looks like the following and then click Save.
    <apex:page controller="StoreFrontController" tabStyle="Merchandise__c">
    
        <apex:pageBlock title="Our Products">
    
            <apex:pageBlockSection columns="1">
    
                <apex:pageBlockTable value="{!products}" var="pitem">
                    <apex:column headerValue="Product">
                        <apex:outputText value="{!pitem.Name}"/>
                    </apex:column>
                    <apex:column headerValue="Description">
                        <apex:outputText value="{!pitem.Description}"/>
                    </apex:column>
                    <apex:column headerValue="Price" style="text-align: right;">
                        <apex:outputText value="{0,number,currency}">
                            <apex:param value="{!pitem.Price}"/>
                        </apex:outputText>
                    </apex:column>
                </apex:pageBlockTable>
    
            </apex:pageBlockSection>
    
        </apex:pageBlock>
    
    </apex:page>
    Your catalog page will look something like this.
    Product catalog page with custom controller, before cart

Tell Me More...

  • The DisplayMerchandise class “wraps” the Merchandise__c type that you already have in the database, and adds new properties and methods. The constructor lets you create a new DisplayMerchandise instance by passing in an existing Merchandise__c record. The instance variable products is now defined as a list of DisplayMerchandise instances.
  • The getProducts() method executes a query (the text within square brackets, also called a SOQL query) returning all Merchandise__c records. It then iterates over the records returned by the query, adding them to a list of DisplayMerchandise products, which is then returned.

Using a Custom Apex Controller with a Visualforce Page

You now have a Visualforce page that displays all of your merchandise records. Instead of using the default controller, as you did in the previous tutorial, you’re now going to write the controller code yourself. Controllers typically retrieve the data to be displayed in a Visualforce page, and contain code that will be executed in response to page actions, such as a command button being clicked.
In this lesson, you’ll convert the page from using a standard controller to using your own custom Apex controller. Writing a controller using Apexallows you to go beyond the basic behaviors provided by the standard controller. In the next lesson you’ll expand this controller and add some e-commerce features to change the listing into an online store.
To create the new controller class:
  1. Click Your Name | Setup | Develop | Apex Classes.
  2. Click New.
  3. Add the following code as the definition of the class and then click Quick Save.
    public class StoreFrontController {
    
        List<Merchandise__c> products;
        
        public List<Merchandise__c> getProducts() {
            if(products == null) {
                products = [SELECT Id, Name, Description__c, Price__c FROM Merchandise__c];
            }
            return products;
        }
    }
  4. Navigate back to your product catalog page at https://<your-instance>.salesforce.com/apex/Catalog, and open the Page Editor, if it’s not already open.
  5. Change the opening <apex:page> tag to link your page to your new controller class.
    <apex:page controller="StoreFrontController">
    Notice that the attribute name has changed from standardController to controller. You also remove the recordSetVarattribute, because it’s only used with standard controllers.
  6. Click Save to save your changes and reload the page. The only change you should see is that the Merchandise tab is no longer selected.
  7. Make the following addition to set the application tab style back to Merchandise.
    <apex:page controller="StoreFrontController" tabStyle="Merchandise__c">
  8. Notice that above the Page Editor tool bar there is now a StoreFrontController button. Click it to view and edit your page’s controller code. Click Catalog to return to the Visualforce page code.
    Visualforce Page Editor toolbars
    You’ll use this in the next lessons.

Tell Me More...

  • As in the previous lesson, the value attribute of the pageBlockTable is set to {!products}, indicating that the table component should iterate over a list called products. Because you are using a custom controller, when Visualforce evaluates the{!products}expression, it automatically looks for a method getProducts() in your Apex controller.
  • The StoreFrontController class does the bare minimum to provide the data required by the Visualforce catalog page. It contains that single method, getProducts(), which queries the database and returns a list of Merchandise__c records.
  • The combination of a public instance variable (here, products) with a getter method (getProducts()) to initialize and provide access to it is a common pattern in Visualforce controllers written in Apex.

Displaying Product Data in a Visualforce Page - Apex

Prerequisites:
  • Tutorial #1: Creating Warehouse Custom Objects
  • Tutorial #3: Creating Sample Data
In this lesson, you’ll extend your first Visualforce page to display a list of products for sale. Although this page might seem fairly simple, there’s a lot going on, and we’re going to move quickly so we can get to the Apex. If you’d like a more complete introduction to Visualforce, see theVisualforce Workbook.
  1. In your browser, open your product catalog page at https://<your-instance>.salesforce.com/apex/Catalog, and open the Page Editor, if it’s not already open.
  2. Modify your code to enable the Merchandise__c standard controller, by editing the <apex:page> tag.
    <apex:page standardController="Merchandise__c">
    This connects your page to your Merchandise__c custom object on the platform, using a built-in controller that provides a lot of basic functionality, like reading, writing, and creating new Merchandise__c objects.
  3. Next, add the standard list controller definition.
    <apex:page standardController="Merchandise__c" recordSetVar="products">
    This configures your controller to work with lists of Merchandise__c records all at once, for example, to display a list of products in your catalog. Exactly what we want to do!
  4. Click Save. You can also press CTRL+S, if you prefer to use the keyboard. The page reloads, and if the Merchandise tab is visible, it becomes selected. Otherwise you won’t notice any change on the page. However, because you’ve set the page to use a controller, and defined the variable products, the variable will be available to you in the body of the page, and it will represent a list of Merchandise__c records.
  5. Replace any code between the two <apex:page> tags with a page block that will soon hold the products list.
    <apex:pageBlock title="Our Products">
    
        <apex:pageBlockSection>
    
            (Products Go Here)
    
        </apex:pageBlockSection>
    
    </apex:pageBlock>
    
    The pageBlock and pageBlockSection tags create some user interface elements on the page, which match the standard visual style of the platform.
    Note
    From here we’ll assume that you’ll save your changes whenever you want to see how the latest code looks.
  6. It’s time to add the actual list of products. Select the (Products Go Here) placeholder and delete it. Start typing <apex:pageB and use your mouse or arrow keys to select apex:pageBlockTable from the drop-down list, and press RETURN.
    Visualforce editor auto-complete accelerates development
    Notice that the editor inserts both opening and closing tags, leaving your insertion point in the middle.
  7. Now you need to add some attributes to the pageBlockTable tag. The value attribute indicates which list of items thepageBlockTable component should iterate over. The var attribute assigns each item of that list, for one single iteration, to the pitemvariable. Add these attributes to the tag.
    <apex:pageBlockTable value="{!products}" var="pitem">
  8. Now you’re going to define each column, and determine where it gets its data by looking up the appropriate field in the pitem variable. Add the following code between the opening and closing pageBlockTable tags.
    <apex:pageBlockTable value="{!products}" var="pitem">
        <apex:column headerValue="Product">
            <apex:outputText value="{!pitem.Name}"/>
        </apex:column> </apex:pageBlockTable>
    
  9. Click Save and you’ll see your product list appear.
    A simple Visualforce-based products listing
    The headerValue attribute has simply provided a header title for the column, and below it you’ll see a list of rows, one for each merchandise record. The expression {!pitem.Name} indicates that we want to display the Name field of the current row.
  10. Now, after the closing tag for the first column, add two more columns.
    <apex:column headerValue="Description">
        <apex:outputField value="{!pitem.Description__c}"/>
    </apex:column>
    <apex:column headerValue="Price">
        <apex:outputField value="{!pitem.Price__c}"/>
    </apex:column>
    
  11. With three columns, the listing is compressed because the table is narrow. Make it wider by changing the<apex:pageBlockSection> tag.
    <apex:pageBlockSection columns="1">
    This changes the section from two columns to one, letting the single column be wider.
  12. Your code will look something like this.
    <apex:page standardController="Merchandise__c" recordSetVar="products">
    
        <apex:pageBlock title="Our Products">
    
            <apex:pageBlockSection columns="1">
    
                <apex:pageBlockTable value="{!products}" var="pitem">
                    <apex:column headerValue="Product">
                        <apex:outputText value="{!pitem.Name}"/>
                    </apex:column>
                    <apex:column headerValue="Description">
                        <apex:outputField value="{!pitem.Description__c}"/>
                    </apex:column>
                    <apex:column headerValue="Price">
                        <apex:outputField value="{!pitem.Price__c}"/>
                    </apex:column>
                </apex:pageBlockTable>
    
            </apex:pageBlockSection>
    
        </apex:pageBlock>
    
    </apex:page>
    And there you have your product catalog!

Tell Me More...

  • The pageBlockTable component produces a table with rows, and each row is found by iterating over a list. The standard controller you used for this page was set to Merchandise__c, and the recordSetVar to products. As a result, the controller automatically populated the products list variable with merchandise records retrieved from the database. It’s this list that the pageBlockTablecomponent uses.
  • You need a way to reference the current record as you iterate over the list. The statement var="pitem" assigns a variable called pitemthat holds the record for the current row.

Creating a Simple Visualforce Page - Apex


In this lesson you’ll create a new, very simple Visualforce page, the equivalent of “Hello World.”
  1. In your browser, add the text /apex/Catalog to the URL for your Salesforce instance. For example, if your Salesforce instance ishttps://na1.salesforce.com, the new URL would be https://na1.salesforce.com/apex/Catalog.You’ll get an error message: Page Catalog does not exist.
    Visualforce 'Quick Fix' screen: Create page Catalog
  2. Click the Create Page Catalog link to create the new page. The Catalog page will be created with some default code.
  3. The Page Editor displays a preview of the new page above and the code below. It will look like this:
    Visualforce: New page with default code
    If the Page Editor is collapsed, click the Expand (Visualforce Page Editor expand button) button at the bottom right of your browser window.
  4. You don’t really want the heading of the page to say “Congratulations,” so change the contents of the <h1> tag to Product Catalog, and remove the comments and other plain text. The code for the page will now look something like this.
    <apex:page>
    
      <h1>Product Catalog</h1>
    
    </apex:page>
    You can add additional text and HTML between the tags, but Visualforce pages must begin with <apex:page> and end with</apex:page>.
  5. Click the Save button (Visualforce Page Editor save button) at the top of the Page Editor. The page reloads to reflect your changes.
Notice that the code for the page looks a lot like standard HTML. That’s because Visualforce pages combine HTML tags, such as <h1>, withVisualforce-specific tags, which start with <apex:>.

Enabling Visualforce Development Mode - Apex


The simplest way to get started with Visualforce is to enable development mode. Development mode embeds a Visualforce page editor in your browser. It allows you to see and edit your code, and preview the page at the same time. Development mode also adds an Apex editor for editing controllers and extensions.
  1. Click Your Name | Setup | My Personal Information | Personal Information.
  2. Click Edit.
  3. Select the Development Mode checkbox.
  4. Click Save.
After enabling development mode, all Visualforce pages display with the development mode footer at the bottom of the browser window.

Visualforce Pages with Apex Controllers


Visualforce is a component-based user interface framework for the Force.com platform. Visualforce allows you to build sophisticated user interfaces by providing a view framework that includes a tag-based markup language similar to HTML, a library of reusable components that can be extended, and an Apex-based controller model. Visualforce supports the Model-View-Controller (MVC) style of user interface design, and is highly flexible.
Visualforce includes standard controllers for every sObject available in your organization, which lets you create Visualforce pages that handle common features without writing any code beyond the Visualforce itself. For highly customized applications, Visualforce allows you to extend or replace the standard controller with your own Apex code. You can make Visualforce applications available only within your company, or publish them on the Web.
In this tutorial, you will use Visualforce to create a simple store front page. You’ll start with a simple product listing page that does not use Apex as a quick introduction to Visualforce. Then you’ll add a few features, like a simple shopping cart, to see how Visualforce connects to a controller written in Apex.

Retrieving a Record Using the Apex REST GET Method

In this lesson, you’ll use Workbench to send a REST client request to retrieve the new merchandise record you’ve just created in the previous lesson. This request invokes one of the Apex REST methods you’ve just implemented.
  1. In the REST Explorer, Click GET.
  2. In the relative URL box, append the ID of the record you copied from Lesson 2 of this tutorial to the end of the URL:/services/apexrest/Merchandise/.
  3. Click Execute. This causes the getMerchandiseById method to be called. The response returned contains the fields of the new merchandise record.

    Response returned by the REST GET method.
  4. Optionally, click Show Raw Response to view the entire response, including the HTTP headers and the response body in JSON format.

    Raw response returned by the REST GET request. 

Creating a Record Using the Apex REST POST Method

In this lesson, you’ll use REST Explorer in Workbench to send a REST client request to create a new merchandise record. This request invokes one of the Apex REST methods you’ve just implemented.
Workbench’s REST Explorer simulates a REST client. It uses the session of the logged-in user as an authentication mechanism for callingApex REST methods.
You might be able to skip the first few steps in this procedure if you already set up sample data with Workbench in a previous tutorial.
  1. Navigate to: workbench.developerforce.com.
  2. If prompted for your credentials, enter your login information and click Login.
  3. For Environment, select Production.
  4. Accept the terms of service and click Login with Salesforce.
  5. Click Allow to allow Workbench to access your information.
  6. After logging in, click utilities | REST Explorer.
  7. Click POST.
  8. The URL path that REST explorer accepts is relative to the instance URL of your org, so you only have to provide the path that is appended to the instance URL. In the relative URL box, replace the default URL with /services/apexrest/Merchandise/
  9. For the request body, insert the following JSON string representation of the object to insert:
    {
      "name" : "Eraser",
      "description" : "White eraser",
      "price" : 0.75,
      "inventory" : 1000
    }
    Note that the field names for the object to create must match and must have the same case as the names of the parameters of the method that will be called.
  10. Click Execute. This causes the createMerchandise method to be called. The response contains the ID of the new merchandise record.
  11. To obtain the ID value from the response, click Show Raw Response, and then copy the ID value, without the quotation marks, that is displayed at the bottom of the response. For example, "a04R00000007xX1IAI", but your value will be different. You’ll use this ID in the next lesson to retrieve the record you’ve just inserted.

Adding a Class as a REST Resource - Apex

Prerequisites:
  • Tutorial #1: Creating Warehouse Custom Objects
  • Tutorial #2: Using the Developer Console
  • Tutorial #8: sObjects and the Database
Let’s add a class with two methods and expose it through Apex REST.
  1. In the Developer Console, click the Repository tab.
  2. In the Setup Entity Type section, click Classes, and then click New.
  3. For the class name, enter MerchandiseManager and click OK.
  4. Delete the auto-generated code and add the following.
    @RestResource(urlMapping='/Merchandise/*')
    global with sharing class MerchandiseManager {
      
        @HttpGet
        global static Merchandise__c getMerchandiseById() {
            RestRequest req = RestContext.request;        
            String merchId = req.requestURI.substring(
                                      req.requestURI.lastIndexOf('/')+1);
            Merchandise__c result = 
                           [SELECT Name,Description__c,Price__c,Total_Inventory__c
                            FROM Merchandise__c 
                            WHERE Id = :merchId];
            return result;
        }
      
        @HttpPost
        global static String createMerchandise(String name,
            String description, Decimal price, Double inventory) {
            Merchandise__c m = new Merchandise__c(
                Name=name,
                Description__c=description,
                Price__c=price,
                Total_Inventory__c=inventory);
            insert m;
            return m.Id;
        }
    }
  5. Click Save.

Tell Me More...

  • The class is global and defined with the @RestResource(urlMapping='/Invoice_Statement__c/*') annotation. Any Apexclass you want to expose as a REST API must be global and annotated with the @RestResource annotation. The parameter of the@RestResource annotation, urlMapping, is used to uniquely identify your resource and is relative to the base URLhttps://instance.salesforce.com/services/apexrest/. The base URL and the urlMapping value form the URI that the client sends in a REST request. In this case, the URL mapping contains the asterisk wildcard character, which means that the resource URI can contain any value after /Merchandise/. In Step 3 of this tutorial, we’ll be appending an ID value to the URI for the record to retrieve.
  • The class contains two global static methods defined with Apex REST annotations. All Apex REST methods must be global static.
  • The first class method, getMerchandiseById, is defined with the @HttpGet annotation.
    • The @HttpGet annotation exposes the method as a REST API that is called when an HTTP GET request is sent from the client.
    • This method returns the merchandise item that corresponds to the ID sent by the client in the request URI.
    • It obtains the request and request URI through the Apex static RestContext class.
    • It then parses the URI to find the value passed in after the last / character and performs a SOQL query to retrieve the merchandise record with this ID. Finally, it returns this record.
  • The second class method, createMerchandise, is defined with the @HttpPost annotation. This annotation exposes the method as a REST API and is called when an HTTP POST request is sent from the client. This method creates a merchandise record using the specified data sent by the client. It calls the insert DML operation to insert the new record in the database and returns the ID of the new merchandise record to the client.

Apex REST


You can create custom REST Web service APIs on top of the Force.com platform or Database.com by exposing your Apex classes as REST resources. Client applications can call the methods of your Apex classes using REST to run Apex code in the platform.
Apex REST supports both XML and JSON for resource formats sent in REST request and responses. By default, Apex REST uses JSON to represent resources.
For authentication, Apex REST supports OAuth 2.0 and the Salesforce session. This tutorial uses Workbench to simulate a REST client. Workbench uses the session of the logged-in user as an authentication mechanism for calling Apex REST methods.
Note
Workbench is a free, open source, community-supported tool (see the Help page in Workbench). Salesforce.com provides a hosted instance of Workbench for demonstration purposes only—salesforce.com recommends that you do not use this hosted instance of Workbench to access data in a production database. If you want to use Workbench for your production database, you can download, host, and configure it using your own resources.