Pages

Thursday, December 31, 2009

Flex Rich Clients and Complex Logics!

Nowadays many developers are driven or forced toward using richer UIs such as Adobe Flex by their customers. Using Adobe Flex and AIR technologies you can create fancy user interfaces with drag and drop functionality, applications that easily integrates with force.com Webservice APIs, takes the data offline and syncs it back to the source once connected to internet again.

All that is very interesting and cool, however one should bear in mind that all the operations, Web Service calls, etc are running in the user's browser (client machine) not on force.com servers.

For this very specific reason, one has to consider how to best design the applications to utilize the cloud computing power of force.com technology and leave the chunk of heavy operations (program logic) out of the client's machine.

The following example which is proven to be useless in the real world, shows you how to host your main operations (chunk of code) in the force.com platform and then share them in form of Web Service methods with your flex applications.

I first start with creating a new Apex class which is pretty much the same as any other Apex class you have seen before but with a few minor changes.

The Apex class is where I intend to do my main operation. I'd rather use my Flex application to utilize such Apex classes and merely view the data in proper form to the user (where possible).

Points:
  • Any Apex class which wants to share a method over the web needs to be marked as "global"
  • Any method of this class that must be reachable by our Flex app should be mark as "WebService"
  • Any internal variable or class that are used in the parameter or as output of the WebService methods also needs to be marked as "WebService".
Below is the implementation of a sample Apex class which shares a method as "WebService".



global class MyWebService
{
global class CompositeData
{
WebService String CompanyName;
WebService String FullName;
WebService String Id;
}

Webservice static MyWebService.CompositeData[] SearchContacts(String keywords)
{
List<CompositeData> results = new List<CompositeData>();

//search logic.
List<List<SObject>> data = [Find :keywords IN ALL FIELDS
RETURNING Contact (id, Name, Account.Name)];

List<SObject> contacts = data[0];

for(SObject contact : contacts)
{
CompositeData cd = new CompositeData();

cd.Id = contact.Id;
cd.FullName = ((Contact)contact).Name;
cd.CompanyName = ((Contact)contact).Account.Name;


results.add(cd);
}

return results;
}
}



The above example demonstrates how you can share a such class as structure other than Apex's SObject class.

This allows you to run multiple queries and aggregate data from various objects in force.com platform and then return them back to the Flex application using the new structure ("CompositeData" in this example).

Now let's see how we can use the above method in our Flex application. Let's say that we use a Flex wrapper class to call this Apex method and then expose this class (Flex class) to our Flex application.

I believe the comments in the code should guide you through the steps.



package com
{
import com.salesforce.AsyncResponder;
import com.salesforce.Connection;
import com.salesforce.objects.Parameter;
import com.salesforce.results.Fault;

import mx.collections.ArrayCollection;
import mx.controls.Alert;



public class MyFlexWebServiceClient
{

//a public property to provide access to the final results
public var results : ArrayCollection;

//force.com connection object
private var binding : Connection;

//the class constructor
public function MyFlexWebServiceClient()
{
results = new ArrayCollection();
}

// this method will be called from the Flex application script
// section once it is instantiated
public function init(Connection sfdcConnection)
{
//the class receive the SFDC connection object from the parent application
this.binding = sfdcConnection;

if (!this.binding.IsLoggedIn)
throw new Error("Connection to the server is not available.");
}

//this method is the wrapper method that calls the force.com webservice
public function execute(keywords: String): void
{
//validation
if (keywords == null || keywords.length <= 0)
{
//handle the invalid data
return;
}

//preparing the parameters of the web service method
var params : Array = new Array(1);

var param1 : com.salesforce.objects.Parameter = new Parameter("keywords", keywords);
params[0] = param1;

// using SFDC Aysync Responder to get the results in flex
var tempCallBack: AsyncResponder = new AsyncResponder(
function(result:Object):void {

if (result != null)
this.results = result as ArrayCollection;
else
Alert.show("Result is empty.", "Info");
},
function(result: Fault):void { Alert.show("Operation failed", "Error"); }
);

// call the execute method of the SFDC connection object to reach out the web service
binding.execute("MyWebService", "SearchContacts", params, tempCallBack);

}

}
}



Happy holidays and new year!

Friday, September 18, 2009

Salesforce.com Winter 10 Release...What's in it for you?

This Tuesday, Salesforce.com announced the release of Winter 10 version and explored new features that soon will be added to the mix. Right off the bat I would like to declare that this new release has a lot of more to offer compare to the previous one and I thank Salesforce for that!

The highlight of the new features is the Realtime Quotes that will be available soon to all Salesforce.com customers. In any sales environment one of the aspects of the Sales process is to be able to track what goods potential and existing customers are interested to purchase and Salesforce supports that by the means of Opportunities.

The one thing that always bugged me though was that Salesforce did not have a feature to allow communication of that information (in terms of Quotes or Invoices) to those customers as soon as the deals reached to a more solid state (proposing or closing).

I believe Salesforce is very late in the game to introduce this feature and already many customers have sought other means to fill that gap and now most will face the question whether to migrate the existing solutions to what's provided out-of-the-box or stay with their current vendors...




Also the fact that Salesforce PriceBooks are not customizable hinders the possibility of tailoring Salesforce to any specific pricing calculation model. Concepts such as automated Volume Discounts calculation that could be applied to Opportunity line items, or any other custom pricing models.


Moving on, on the Custom Cloud side, Salesforce yet again is gaining momentum by introducing "Batch Code Processor" and "Code Scheduler".
Many admins in the past, in order to process event-driven data to be able to provide custom roll-ups, Analytics and better summary-data visibility of child objects in the system, were forced to max out their workflow rules or develop triggers which most of the time would hit the Governing Limits or just fail in bulk DML operations.



With these new features many of those scenarios can be easily addressed and even more complex logic can be applied to solve problems and fulfill business requirements!
Cases such as data de-dupping, data heath checks, rebuilding account hierarchies.... Sky is the limit!

Saturday, September 12, 2009

Edit and Delete Command For Your Datatable In Visualforce


Most often that not you need to show data to the users in form of a table, such as Salesforce List Views or Related Lists.

Visualforce allows us to easily implement such page with a few lines of code. However, most often you would want to be able to add more interactivity/functionality to your page by supporting Edit or Delete command or any other custom operation that is required by design.

Today's article will show you how you can get that working for you.



Above picture depicts how the final result will look like, very much like Salesforce.com standard pages, isn't it?.

In this example I list the first twenty Account records that Apex finds and show then on the screen and then I would like to have actions such as "Edit" that forwards the user to Account edit page and brings the user back to my page again after the modifications are done and also "Delete" action that receives a confirmation from user and removes an Account record from Salesforce CRM.

So let's talk about the User Interface (UI) components required first and then we will look into the controller's code to see how it all works together.

Steps to add the page tags:
  • I first add a PageBlock component and set the title to "Accounts"
  • Then I want to put a PageBlockDataTable in the my Visualforce page.
  • In this step I simply add all the data columns I want to show to the user and leave the first column empty for the next step.
  • Now we are ready to add the action items to the first column of the dataTable.
Below is the page tags that I have used to make it all happen:


<apex:page controller="DataTableEditRemoveController">
<apex:form id="form" >
<apex:pageBlock title="Accounts">
<apex:pageMessages ></apex:pageMessages>
<apex:pageBlockTable value="{!accs}" var="row">
<apex:column >
<apex:outputLink title="" value="/{!row.id}/e?retURL=/apex/{!$CurrentPage.Name}" style="font-weight:bold">Edit</apex:outputLink>&nbsp;|&nbsp;
<a href="javascript:if (window.confirm('Are you sure?')) DeleteAccount('{!row.Id}');" style="font-weight:bold">Del</a>
</apex:column>
<apex:column value="{!row.Name}"/>
<apex:column value="{!row.BillingStreet}"/>
<apex:column value="{!row.BillingCity}"/>
<apex:column value="{!row.BillingPostalCode}"/>
<apex:column value="{!row.BillingCountry}"/>
</apex:pageBlockTable>
</apex:pageBlock>

<apex:actionFunction action="{!DeleteAccount}" name="DeleteAccount" reRender="form" >
<apex:param name="accountid" value="" assignTo="{!SelectedAccountId}"/>
</apex:actionFunction>
</apex:form>
</apex:page>



How It Is Done For Edit Action:
Since the standard Account edit page is good enough for me I used an outputLink component to link the record to its Standard Edit page. In Salesforce for standard objects you can follow this format to get the URL for their edit page: /{RecordId}/e

I also wanted this to work in such a way that would return the user back to my Visualforce page once the user clicks on "save" or "cancel" in the Account edit page. In order to do that I need to add the following to the URL: /{RecordId}/e?retURL={returnURL}

In the Page's source code (above) you see that for return URL I have used {!$CurrentPage.Name} merge field, where I could simply put my page name. I like writing code clean! By doing this if you later on decided to change your page name, you do not need to worry about breaking anything! You page will continue to work with no problems!

How It Is Done For Delete Action:
In order to support this action in your page you need to do a bit of coding. The key is to be able to find out which account was selected by the user to be deleted.

In this example I have used a actionFunction component that triggers a Controller's Apex method call "DeleteAccount".

Before getting more into the coding part I wanted this link to get a confirmation from the user about deleting the record before actually we remove it.
In order to do so, we need to use a little bit of Javascript "window.confirm", the javascript function returns true if the user clicks on OK and false if the user selects "Cancel".

In order to capture the user's selection as to which account should be deleted I have added a "param" tag to the actionFunction component which passes the Account ID to the controller and as soon as user clicks on the link.

Now let's take a look at the code:


public class DataTableEditRemoveController {

public List<Account> accs { get; set; }

//used to get a hold of the account record selected for deletion
public string SelectedAccountId { get; set; }

public DataTableEditRemoveController() {
//load account data into our DataTable
LoadData();
}

private void LoadData() {
accs = [Select id, name, BillingStreet, BillingCity, BillingPostalCode, BillingCountry from Account limit 20];
}

public void DeleteAccount()
{
// if for any reason we are missing the reference
if (SelectedAccountId == null) {

return;
}

// find the account record within the collection
Account tobeDeleted = null;
for(Account a : accs)
if (a.Id == SelectedAccountId) {
tobeDeleted = a;
break;
}

//if account record found delete it
if (tobeDeleted != null) {
Delete tobeDeleted;
}

//refresh the data
LoadData();
}


}




Funny thing is that in my tests if you do not set the "reRender" attribute of the "actionFunnction" component the param is not passed to the controller and the "SelectedAccountId" property is not populated. Go figure....

Also I really wanted to get it working with commandLink or commandButton components instead using actionFucntion and javascript, but was not so lucky!

Enjoy!

Monday, June 29, 2009

Triggering an Apex method with a Custom Button

Most often Salesforce.com developers want to write a custom logic such as sending a notification email, changing the status of a record (picklist), etc once a button is clicked on, in a standard layout.

The effort is minimized this way since you do not want to recreate the layout using a Visualforce page, all you need is to be able to launch a method once the button is clicked on.

In order to do so, you need to write your logic into an Apex class with following conditions:
  1. Firstly, your class should be marked as "Global"
  2. Secondly, the logic goes to a static method of this class which is marked as "WebService"
If an Apex class has the above characteristics, the method marked as web service can be called via javascript when the button is clicked on. Neat!

I think by now you have a good idea of where I am going with this, so let's dive into code and examine everything more closely.

Below I have created a Apex Class called "OutboundEmails" and added a method that has a keyword as "WebService".


global class OutboundEmails {

WebService static void SendEmailNotification(string id) {

//create a mail object to send a single email.
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();

//set the email properties
mail.setToAddresses(new string[] {'myemail@domain.com'});
mail.setSenderDisplayName('SF.com Email Agent');
mail.setSubject('A new reminder');
mail.setHtmlBody('an object with ID='+ id + ' is just clicked on.');

//send the email
Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail } );

}
}




This method receives an object Id (this is just to demo purposes, so you can identify any parameters that you need) and sends an email notification subsequently once the method is called.

Now let's concentrate on the button that will actually call our WebService method.

Firstly, I create a detail page button let's say on Account object and name it "Send Me ID".
This button's behavior will be "Execute Javascript".
If you need more information about how you can add a custom button to Account object please click here. Then I add the following code to the body of the button edit page:



{!REQUIRESCRIPT("/soap/ajax/10.0/connection.js")}
{!REQUIRESCRIPT("/soap/ajax/10.0/apex.js")}
sforce.apex.execute("OutboundEmails","SendEmailNotification", {id:"{!Account.Id}"});
window.alert("Account Id is sent." );



Now It all works together!
Once you click on the button, in case you have not forgotten to change the sample email address with your own in the code, you should receive the email.

Tuesday, April 7, 2009

How to Create Word, PDF or Excel Files with Salesforce Data

One of challenges in any software application is being able to export data into different documents using templates for various purposes.

An example of this is using such templates to create custom documents such as Fax sheets, Quotes, Invoices, Forms that are required to be filled out by a person in traditional ways.

Visualforce pages allow us to generate such documents combined with Salesfoce data. The documents can be formatted in number of types such as PDF, Excel, Word, HTML or XML.

In this example I will show how easy it is to generate PDF documents using Visualforce pages adn with adding little bit of your coding skills you can easily create other formats as well (of course with certain limitations).

In order to be able to create PDF pages in Salesforce you meed to know the following:
  • When using the Page tag, you should set the "showHeader" attribute to "false". By doing this you are telling to Visualforce to do not render any Salesforce header or even HTML tags.
    So think about a normal HTML page, which has tags such as "html", "head" and "body" none of these tags are added to your page automatically anymore. So we should add them to the page ourselves when creating PDF files.
  • Also note that HTML form elements or Apex input controls can not be included into your document.
  • The other important thing is styling, in order to make your PDF file look professional you need to apply styling skills and add CSS classes to your Visualforce page.
  • And the last point is to set your "Page" attribute called "renderAs" to "pdf".
Below is a sample PDF generate code with no content:



<apex:page showHeader="false" renderAs="pdf">
<head>
</head>
<body>
</body>
</apex:page>



The next step is to add some styling/formatting options as well as planning for your content.

By applying CSS into you can define a few CSS classes that formats your PDF document the way you need.

However, the following are important features you may want to benefit from, such as the ability to set the PDF file pages orientation (Landscape or portrait), allow page numbers or additional descriptions in PDF file's header or footer, etc.

Some of these examples are shown below:


<apex:page showHeader="false" renderAs="pdf">
<head>
<style type="text/css">
@page
{

/* Landscape orientation */
size:landscape;

/* Put page numbers in the bottom right corner of each
page in the pdf document. */
@bottom-right {
content: "Page " counter(page);
}
}

body {
font-family: Arial Unicode MS;
font-size:9pt;
}


td {
font-size:11pt;
font-family:Tahoma;
}

/* you can even define custom classes that utilize your static resources */
.checkbox
{
width: 19px;
height: 16px;
background-image:url({!URLFOR($Resource.Checkbox)});
background-repeat: no-repeat;
}
</head>
<body>
</body>
</apex:page>



If your requirement is to create Word or Excel files the process would be the same only following changes are required:
  • Remove "renderAs" attribute
  • Add a new attribute to the page tag: "ContentType":
    - For Word: contentType="application/msword"
    - For Excel: contentType="application/x-excel"
  • And finally a little bit of tweaking of your style will take care of the job

Friday, January 16, 2009

Spring 09 Release - A Whole New Force.com or Just a Few New Goodies?

After attending the Spring 09 Release the other day in hope of seeing at least some of the good ideas making way to force.com platform, features such as inline editing for Visualforce pages, more flexibility with custom of related-lists, flexibility on using the advanced Apex features to create customized reports and dashboards, etc following observations were concluded:

Well not all of them made it! in fact, we can summarized the release merely around some enhancements here and there in the platform.

Some of you would even think that in this economic downturn, one can not expect more than this from IT companies. Should this thought ever cross our minds, I would not rule this factor out as an impact on this release!

Let's have a look and quickly browse through the enhancements of the Spring 09 release:

  1. Force.com Sites Improvements

    • Audit Trail:
      Now you can track all the changes made to your sites by different users.

    • Sites Robot.txt and Fav Icon:
      With this release you will be able to set a robot.txt for you force.com site which enables you to better control how search engines should index your site's pages. Fav Icon is also a useful way of personalizing the browser in showing an icon next to the title of your website (in tabs) and also in favorites/bookmarks.

    • Standard Pages:
      Allows you to bring selected standard pages and expose them to the public via your force.com site (suitable for ideas page, etc).

    • Sites Packaging:
      With this feature we can package force.com sites, apex code, etc and install them into other instances.

  2. Force.com Web Service API Improvements

    • Improvements in the timeout limits of the callouts:
      This is potentially good when the code takes a longer time to process and bring back the results. Now we can configure it in a way to have extended timeout periods resulting in more run-time stability.

    • Also Wider range of WSDL types are supported by Spring 09 release.

  3. Database and Reporting

    • Summary Report Data Snapshots:
      Previously data snapshots were available on reports, however, with this release you can use snapshots across large amounts of data, where only the summaries will be stored, as well as create historical views of metrics, KPIs and other summary data.

    • Data Grouping Functions:
      This is actually a very useful upgrade, now you can group the entries of a report to better analyze aggregate data.

    • Delegated Data Administration:
      This feature allows you to grant permission to non-admin users to report, search, modify, transfer, share, unlock, or approve any record regardless of sharing settings on an object basis.

    • Dashboard Finder:
      This enhancement allows you to search through your dashboard items (a real time-saver!).

  4. Force.com IDE

    • Apex Code Auto-Complete in Force.com IDE:
      Finally! When you are coding in Eclipse (force.com IDE) auto-complete feature will be available to assist you with writing the code.

  5. User Interface

    • Enhanced Page Layout Editor:
      This one is my favorite enhancement, using this feature now you can create much better layouts. You can drag and drop fields and items around, "save as" a layout, leave a spot empty (blank spaces), design the mini-layout, etc.

  6. Services

    • Cross-Object Workflow:
      With this feature you can update a field on a parent record within a workflow!

    • Access to Email Logs in the Application:
      This report shows you whether your outbound emails were received or bounced back and basically gives you a comprehensive log of your outbound emails.


  7. Force.com Logic


  8. Mobile

    • Mobile Web Tabs for iPhone
      You can now create mobile-ready Visualforce Tabs for the iPhone. This enhances the client with a near-limitless method of extension - enabling you create content for the iPhone using the Visualforce user interface framework. The hybrid iPhone client that supports this functionality will be released next month.

Wednesday, January 7, 2009

Allow Mass Update of your Object Records Even Without Having a Save Button!

Today we want to explore one of the beauties of the Visualforce technology.
Those who have a history of witting ASP or ASP.NET code will admit that Visualforce has made it all too simple to develop business applications.

Let's say we want to be able to update several records of a certain Object all together providing ability for users to quickly make modifications and save them.

This is particularly useful when the data in nature changes often and it's time consuming to do the updates on a record by record basis.

In this example, I will demonstrate a Visualforce page which has a search box through which user can search Accounts and view a list of records where he or she can modify the information inline and then proceed to the next record without clicking on a save button of some sort!

This is very much as easy of entering data into cells of an excel sheet! The only difference is that the Excel needs you to click on the save button at the end but our Visualforce page won't!

I will use an actionFunction tag to create a javascript function which in turn will trigger a method of my Apex controller class. This way when the value of one the input controls changed I can call that javascript function and boom the change would get posted back to the controller and will be saved.

This the how Visualforce page is like:

<apex:page tabStyle="Account" controller="massAccountUpdateCon">
<apex:sectionHeader title="Accounts Mass Update"></apex:sectionHeader>
<apex:form >
<apex:pageBlock title="" id="pageBlock">
<!-- This block will show the search textbox and the Search button -->
<apex:pageBlockButtons location="top">
<apex:inputText value="{!keywords}" style="height:15px;"></apex:inputText>
<apex:commandButton value="Search" action="{!ViewData}" id="theButton" rerender="pageBlock" status="status"></apex:commandButton>
</apex:pageBlockButtons>
<!-- To show page level messages -->
<apex:pageMessages ></apex:pageMessages>

<!-- The below tag will provide a javascript method which when is called in turn will call a controller's method -->
<apex:actionFunction action="{!UpdateRecords}" name="updateRecords" rerender="pageBlock" status="status"></apex:actionFunction>

<!-- This table contains columns which have inputfield components -->
<apex:pageBlockTable value="{!accounts}" var="a" rendered="{!NOT(ISNULL(accounts))}">
<apex:column>
<apex:facet name="header">Name</apex:facet>
<apex:inputField value="{!a.Name}" onchange="updateRecords();"></apex:inputField>
</apex:column>
<apex:column >
<apex:facet name="header">Phone</apex:facet>
<apex:inputField value="{!a.Phone}" onchange="updateRecords();"></apex:inputField>
</apex:column>
<apex:column>
<apex:facet name="header">Billing City</apex:facet>
<apex:inputField value="{!a.BillingCity}" onchange="updateRecords();"></apex:inputField>
</apex:column>
<apex:column>
<apex:facet name="header">Billing Country</apex:facet>
<apex:inputField value="{!a.BillingCountry}" onchange="updateRecords();"></apex:inputField>
</apex:column>
<apex:column>
<apex:facet name="header">Industry</apex:facet>
<apex:inputField value="{!a.Industry}" onchange="updateRecords();"></apex:inputField>
</apex:column>
</apex:pageBlockTable>

</apex:pageBlock>

<!-- The action status to show when the AJAX postback is wroking. -->
<apex:actionStatus id="status" startText="Requesting..."/>
</apex:form>
</apex:page>





Now the Controller, this is where the simplicity of coding can be visibly seen!
As you can see in the Controller's source code, I do not need to write any code to find which column's value was changed! All I need to do is to update my List of Accounts!
Visualforce will take care of all those details!


public class massAccountUpdateCon {

private List<Account> accounts;

public List<Account> getAccounts() {
return accounts;
}

public string keywords {
get;
set;
}

public PageReference ViewData() {
//dynamically build the query to insertthe filter values
String query = 'Select id, name, type, ownership, industry, phone, BillingCity, billingCountry FROM account WHERE name LIKE \'' + keywords + '%\'';

accounts = Database.query(query);

return null;
}

public PageReference UpdateRecords() {
// this simple line of code finds out which column was changed and update the
// relevant account record accordingly!
update accounts;
return null;
}
}




Friday, January 2, 2009

Visualforce Component to show Object Record Types

Happy New Year!

Time definitely flies and I wish you wonderful times in 2009!


Part of our daily job is to make life easier for others by developing new applications in force.com platform. But sometimes it's not bad to spend some time for ourselves to make our own life a little easier, better and smoother.

In this article I will present a Visualforce Component that would list the record types of an Object in the platform.

Imagine, the Account object has two record types in the force.com platform (Record Types are created by the users based on what these objects represent on their business).

Account Record types:
  • Customer
  • Partner
In many occasions especially when developing a new wizard you need to first allow the user select what type of record they want to create and then based on that show the correct type of interface to the user.

The solution as to how you can show this to the user is rather simple, but here I actually took the time to create a re-usable component, so you and I won't need to rewrite the code next time!

Here is the Component's Tags:


<apex:component controller="RecordTypeListCon">
<apex:attribute name="sObjectType" description="" type="String" required="true" default="Account" assignTo="{!sObjectType}"></apex:attribute>
<apex:attribute name="value" description="" type="String" required="true"></apex:attribute>
<apex:selectList value="{!value}" size="1">
<apex:selectOptions value="{!items}"></apex:selectOptions>
</apex:selectList>
</apex:component>



The Component has a Controller called "RecordTypeListCon" and is named as "RecordTypeList". It declares two attributes as follow:

  • sObjectType: values such as "Account", "Contact", generally the name of your object.
  • value: you can capture the result of user's selection by using the attribute in your Vsualforce Controller.

And here goes the code of the component's Controller:


public class RecordTypeListCon {
private List<SelectOption> items;

// property that reads the value from the Component attribute
public string sObjectType
{
get;
set;
}

public List<SelectOption> getItems() {
List<SelectOption> items = new List<SelectOption>();

//default value
items.add(new SelectOption('','--Select Record Type --'));

//query force.com database to get the record type of the requested object.
for(RecordType rt: [select id,name from recordtype where sobjecttype=:sObjectType]) {
items.add(new SelectOption(rt.id,rt.name));
}

return items;
}
}




Once you create this component in your Salesforce instance all you need to do when need to the selectList of your object's record types is to:


<c:RecordTypeList value="{!lookupValue}" sObjectType="Account"></c:RecordTypeList>




Enjoy!