Powered By Blogger

Monday, 24 October 2016

Don’t ruin your Dreamforce, be prepared


As an active Dreamforce attendee, I thought to share my this year experience with you all.

The week-long experience at the Dreamforce in San Francisco is a memorable experience. Not only do you get an opportunity to meet visionary speakers and key business leaders but also it opens up a unique opportunity to interact with key industry pioneers, leaders and lay the foundation of sosme long-lasting professional connections as well as get a strong networking platform. But all of these memories might end up as rather lackluster is you don’t pay attention to some basic dos and don’ts to enhance the overall experience. So I decided to share some of the main problems I faced there to help you organize your trip better.

  • Plan In Advance: At Dreamforce, you get the opportunity to connect and grow your business, but the key to it is planning in advance. We started searching for hotel options nearly six months before the event started but realized it was too late for a mega event like Dreamforce. Only the expensive hotel options were left across San Francisco with some costing as high as $500/night. So my advice is if you plan to join the Dreamforce 2017, it is much better to start looking and booking for it right away.

  • Hostel: When we failed to book a reasonably priced hotel room, I thought perhaps a hostel would solve our problem, but alas that was the beginning of much greater problems. The rooms were too small; the location is crucial and getting in and out and spending the night in these rooms can be quite a struggle otherwise.
  • Know Your Street: As I mentioned in my previous paragraph, the location is crucial. I was not too well versed with the streets across SFO and ended up booking a hostel in Ellis Street. This is not a great location and is filled with beggars and many other trouble creators, so we had always to travel in a cab and walking was never an option. Not only was this a greater hassle but I also ended up spending more than I had budgeted. Couple of references:
    https://www.virtualtourist.com/755471-2422856/San-Francisco-Tips/eddy-and-ellis-streetsand-much-of-downtown
    https://www.tripadvisor.in/ShowTopic-g60713-i30-k5758497-Ellis_street_cova_hotel_area_safe_at_night-San_Francisco_California.html


  • Check for Weather Conditions: The last Dreamforce that I attended was rather painful. The simple fact was I did not check the weather conditions and the event being in October as against September that it was held in the previous year, SFO was much colder. I was unprepared and without sufficient warm clothes and ended up being in bed for 2 of the 4 days.

  • Uber Pickup Points: You have to remember that not all points in SFO are Uber Pickup points. So when you are booking a cab on the phone, be very careful about the location you choose to avoid any complication with regard to that.
  • Cab at Moscone: Finally, if you are at Moscone, it would never be advisable to wait for taxis. If you book an Uber, it keeps getting rerouted, and you might end up waiting close to an hour. It is much better to start walking and getting away from Moscone and improve your chances of getting a cab faster.

You might be aware with all above this if you have been to Dreamforce, but of not, please be attentive about all these points. These can definitely help you in making your Dreamforce in memorable Dreamforce.

Saturday, 9 August 2014

Handling Inline Images in Salesforce Inbound Email

One of the Salesforce powerful feature is Inbound Email Services. Using this, you can send an email to Salesforce and process the email body as you want. Inbound email handler class allows you to access email’s plain text body as well as html body.

One issue that I came across was, none of the existing method can handle your inbound email’s inline images. I searched community a lot and realized that, too many people had the same issue but they never find any solution, so I thought to pick it from there.

Issue:
You want to write email’s HTML body in a Rich Text area field and your email has inline images. Now, when you send this, inbound email will lost those images references and your body will say “Inline Image XXXXX”.

More Detail:
I have created an email service in my org. It only listens inbound email and put the email’s HTML body in a rich text area field on lead.

global class POCEmailHandler implements Messaging.InboundEmailHandler {
    
    //Method to process email 
    global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email, Messaging.InboundEnvelope envelope) {
        Messaging.InboundEmailResult result = new Messaging.InboundEmailresult();
        
        //Create a New Lead record
        Lead lead = new Lead();
        lead.LastName = 'Inbound Lead';
        lead.Email = email.fromAddress;
        lead.Company = 'N/A';
        lead.HTML_Body__c = email.htmlBody;
        
        //Insert record
        insert lead;
    }
}


Now I sent below email to this email service. Inbound handler class processed it and a new lead was created in system.



This lead was created in system. Notice the HTML Body field.












Inline image didn’t came in the HTML body.

Reason:
Salesforce process inline images as binary attachments. When you send an email having inline images, it doesn’t come as a part of body, but it comes as binary attachment. From here, you will have to put your own logic to place the inline images back in HTML Body.

Resolution:

1.       Process binary attachments and see, which attachment came as a part on inline image. Create an attachment record for each image. Below code is to create a map with the inline image name and its related attachment record.


//Create a list of attachments
        Map< String, Attachment > mapAttachments = new Map< String, Attachment >(); 
        
        //Attachments
        for(Messaging.InboundEmail.BinaryAttachment bA : email.binaryAttachments) {
            System.debug(bA);
            for(integer i = 0; i < bA.headers.size(); i++) {
                
                //Header Value
                String headerValue = bA.headers[i].value;
                if(headerValue.startsWith('ii') || headerValue.startsWith('< image')) {
                    headerValue = headerValue.replaceAll('<', '').replaceAll('>', '');
                    mapAttachments.put(headerValue, new Attachment(Name = bA.fileName, body = bA.body, 
                                                    ParentId = lead.Id, ContentType = bA.mimeTypeSubType));
                }
            }
        }



2.       Now process HTML body content and get all the places where actual Inline Image was replaced with blank space and update these instances with the attachment link.
//Process inline images and update the HTML Body
        for(String headerValue : mapAttachments.keySet()) {
    
            //Reference Link
            String refLink = '/servlet/servlet.FileDownload?file=' + mapAttachments.get(headerValue).Id;
            lead.HTML_Body__c = lead.HTML_Body__c.replaceAll('cid:' + headerValue, refLink);
        }
        update lead;
 


Updated code will look like this.
global class POCEmailHandler implements Messaging.InboundEmailHandler {
    
    
global class POCEmailHandler implements Messaging.InboundEmailHandler {
    
    //Method to process email 
    global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email, Messaging.InboundEnvelope envelope) {
        Messaging.InboundEmailResult result = new Messaging.InboundEmailresult();
        
        //Create a New Lead record
        Lead lead = new Lead();
        lead.LastName = 'Inbound Lead';
        lead.Email = email.fromAddress;
        lead.Company = 'N/A';
        lead.HTML_Body__c = email.htmlBody;
        
        //Insert record
        insert lead;
        
        //Create a list of attachments
        Map< String, Attachment > mapAttachments = new Map< String, Attachment >(); 
        
        //Attachments
        for(Messaging.InboundEmail.BinaryAttachment bA : email.binaryAttachments) {
            System.debug(bA);
            for(integer i = 0; i < bA.headers.size(); i++) {
                
                //Header Value
                String headerValue = bA.headers[i].value;
                if(headerValue.startsWith('ii') || headerValue.startsWith('< image')) {
                    headerValue = headerValue.replaceAll('<', '').replaceAll('>', '');
                    mapAttachments.put(headerValue, new Attachment(Name = bA.fileName, body = bA.body, 
                                                    ParentId = lead.Id, ContentType = bA.mimeTypeSubType));
                }
            }
        }
        
        //Insert
        insert mapAttachments.values();
        
        //Process inline images and update the HTML Body
        for(String headerValue : mapAttachments.keySet()) {
    
            //Reference Link
            String refLink = '/servlet/servlet.FileDownload?file=' + mapAttachments.get(headerValue).Id;
            lead.HTML_Body__c = lead.HTML_Body__c.replaceAll('cid:' + headerValue, refLink);
        }
        update lead;
        
        return result;
    }
}




Now send the same email to Salesforce email address and see the result.













Don't  miss DF-14. See you there.
http://bit.ly/df14infblog
Join us in the Developer Zone at Dreamforce 2014 | Training, Talks & MoreSalesforce
Join Salesforce Developers from around the world in the Developer Zone at Dreamforce 2014. Learn new skills through interactive sessions and hands-on training. Immerse yourself in the tools and knowledge you need to build better, faster, and deliver more. For a limited time developers can register for Dreamforce at a special rate of $899.

Tuesday, 29 July 2014

Approval Fields in Email Notification

Many of you have been worked with the approval processes. When you are using approval processes, you can define approval notification template. It’s too common when you need to address the approver in email notification who is going to receive this email like:

Hi BSS,

A deal has been submitted and assigned to you for your approval.
Thanks,
<<Assignee Name>>
<<Company Name>>

When you define the email template, you have choice to select the Approval fields.
Request_Approver
Request_Assignee

But unfortunately, none of the field is going to help when you want to include the Approver name in email who is going to handle this approval request.
Request_Approver is, who currently approved this request.
Request_Assignee is, who assigned this request.

I created this email template in Salesforce for testing.

 

Now let’s have a case when you have a multi-step approval process. User requested for the approval and email notification was sent to first level approver. So how will you get the approver name in email?

My approval process is:



I created an account and it sent the Approval Request to Lisa Hayden. Following email was sent to User Lisa.

See both the field says Bhavi Sharma.


How you can quickly fix this:
  1. Create a user lookup field on your object and call it “Next Approver”.
  2. In the approval process’s initial submission action, populate this field with the appropriate user (If you are using a queue, better is to create a Text field and get it populated with the Queue name).
  3. Now use this field in email approval submission notification email.
  4. In the first level approval actions, get this custom field populated with the name of the second level approver.

Sunday, 1 December 2013

SOAPUI: Integration Helper for Salesforce

Recently I connected with hundred of developers. While taking to them, I felt that 75% of them were scared when it came to integration. So I thought to write this to make their life bit easier.

If you have a perfect WSDL file, which can be parsed easily in Saleforce, and you are the luckiest one. You can easily use generated wsdl classes for integrating Salesforce with other application. Picture starts when you have wsdl, but Salesforce is unable to parse it because of some constraints. 

Few common issues are:
  1. You have wsdl, but that is not in Salesforce supported format.
  2. You start modifying the wsdl to make it in Salesforce supported format, but it’s getting too hard and complex.
  3. Now you decide to go with HTTP request, but you don’t know the request body format.
  4. What you need to set in the request header?
  5. You have username and password, but you don’t know how to use that.
Please add your ones if I missed anything above.

SOAPUI: I would highly recommend downloading (http://www.soapui.org/Downloads/latest-release.html) and installing this tool. This allows you to create projects using WSDL files. When you create a project using wsdl, SOAPUI creates separate requests for each operation.

Creating a project in SOAPUI using wsdl

  1. Once you have been downloaded and installed SOAPUI, open soapui.
  2. Go to File -> New Project
  3. Choose your wsdl file and click on okay.
  4. You will see a new project is created in WSDL and it has all the operations.
  5. Select any operation and click on request1. It will show you complete request format.
  6. Now put your variables in request xml and hit the service.
  7. Click on Raw tab to see the request and response headers.
So now what you have all is:
EndPoint: As shown in screen-shot above
Method: Post
Content-Type: text/xml;charset=UTF-8
SOAP Action: As shown above
Request Body: As shown above

This is all enough to create your HTTP request in Salesforce and hit the endpoint. So how this will be implemented in Salesforce now:

You can create the requestBody string in Salesforce either by using the DOM class or you can also create a direct string like 
String requestBody = ‘<……..></…….>’;

//Request
HttpRequest request = new HttpRequest();
request.setEndpoint(endpoint);
request.setMethod(‘POST’);
request.setHeader('SOAPAction', soapAction);
request.setHeader('Content-Type', 'text/xml;charset=UTF-8');
request.setBody(requestBody);

//Response
Http http = new Http();
HttpResponse response = http.send(request);

Now if you wish the parse the response, you can use DOM class to parse that.

If you have credentials and that need to be passed for authorization, then you can use these credentials in SOAPUI as given below:


In Salesforce this will be passed as :
Blob headerValue = Blob.valueOf(username + ':' + password);
String authorizationHeader = 'Basic ' + EncodingUtil.base64Encode(headerValue);
req.setHeader('Authorization', authorizationHeader);

Please do not forget to leave your comments. It will help me to improve the quality in next.

Wednesday, 5 June 2013

Test Methods: What, Why and How?



I was thinking to write something from a long time and I came up with this today(Finally I am active again on blogger :)).
I am big fan of Salesforce developer community and I daily visit it. Not because of I am expert and can answer all the queries there, but It helps me a lot to increase my knowledge. I learn something new daily from there and implement it in real life(how easy it is).

After seeing various post on community, I realized that some people are not sure about the test methods. Each day I do see 2-3 posts like, how to increase coverage, help in writing test methods, assertion failed and many more. and this encouraged me to write this post.

Let me start now without wasting your time :P.

  1. What is test method?
    [Answer]: I hope you all know, but still I would like to share :). Test method is a way to test your functionality from developer perspective. Each time when you deploy your changes to new org, you really can't test everything from UI as it will be time consuming, so test methods are the way to test if everything is working fine without user interface.
  2. Why we write test method?
    [Answer]: Suppose you implemented a functionality today and it was successfully deployed. You have test method with all the use cases covered . A month later, new enhancement comes and you implement it. Now you can run your test method to see the impact on existing functionality. 
  3. How to write test methods?
    [Answer]: I hope you all already know answer of this, but today I would like to explain this very simple way with a simple program.
Suppose I have a method, which takes marks of Science and Maths subject and returns total.

My method would be something like this:



public class MyController {
 //This method takes science and Maths marks and return total of these
 public Integer sum(Integer m1, Integer m2) {
  
  //return sum of these 2
  return m1 + m2;
 }
}

Now you can see here is, if I pass 50 and 60 in method, results would be 50+60=110.
That is what QA people will be testing from UI.

but we are developer and do everything with code :). 

so as I said, if I pass 50 and 60 in sum method, it should return 50+60=110.

Let's start writing test method

@isTest : This anotation defines that your class is a test class


@isTest
private class Test_MyController {

 //test sum method
 static testMethod void testSUM() {
  //Instantiate controller class
  MyController controller = new MyController();

  //Call Sum method
  Integer sum = controller.sum(50, 60);

  //Expected results is 110 and actual should also be 110
  //Check result
  System.assertEquals(110, sum);
 }
}



and that's all :). Isn't it cool? 

Now anytime you make changes in your controller's SUM method, you can always run the test method to check if there is any impact on existing functionality. Also make sure to keep you test method updated as per the new changes :).

HAPPY CODING :).








Tuesday, 21 May 2013

Quick Finder for Salesforce


And here the dude is back in town. Here is my new post to make all the developer’s life so easier.

Let me ask you a question here :).
When you are working in browser and if you need to find out any class/page/trigger/component/static resource, then how will you do that?

Let me tell you, how you will do it (Even I am also a advanced developerJ):

  1. First Click -> Your Name
  2. Second Click ->  Setup
  3. Third Click -> Develop
  4. Forth Click -> Apex Classes

You are not finished yet.
Now use alphabetical sorting, view more, next page etc. links to find out the exact class. This becomes more irritating when org is very big. So on an average, you need to do at-least 6 clicks to find out a component.

It is really killing time when working on browser directly. So I started working on an application which can do all this in SINGLE CLICK:-O.
Yes, you read this correctly. You can do all this in a single click. App name is Quick Finder for Salesforce.
This application includes a home page component, which you just need to place on your sidebar.


and you are done. Now doesn’t matter on which page you are, if you can see sidebar, you can go to any component at any time.



Just click on the searched result and you will be navigated to appropriate component.
Isn’t it awesome? This app currently supports following component types:
1.       Apex Class
2.       Apex Page
3.       Apex Trigger
4.       Apex Component
5.       Static Resource
Please install this from AppExchange.  Here is the Installation link. Don’t forget to review this after installation.
https://appexchange.salesforce.com/listingDetail?listingId=a0N3000000B3a8hEAB

Wednesday, 31 August 2011

Date format while uploading data in salesforce

I am back to text my knowledge to share with world.
These days I was much involved in data loading part and here I was doing a minor mistake, but each time this minor mistake forced me to re-import .

In Apex data loader setting we have a check box  "Use European date format(dd/mm/yyyy)", true value for this checkbox allowed you to insert the date in dd/mm/yyyy format.

Now may be you are thinking that what is new here and what is the need to write a blog on this as this looks very common.

Now the picture starts from here :
As you have marked the checkbox as true and you are planning to insert the date in the same format, but by mistake date is still in MM/DD/YYYY format in your csv file.

What will happen now? any guess?
Will data loader insert these records or it's going to throw an error.
and if the record inserted, will date filed be populated ?

No more questions o/w people will leave this topic :P.

So here is the answer :
Data loader will not throw any error, it will insert the date in date field, but date field value will be distorted.

So here is the example:
Suppose I have this setting checked in my Apex Data Loader.
My csv file has a date field with value: 01/23/2011 (MM/DD/YYYY)

Now I started data load operation and date will be inserted as 01/11/2012.

Explanation: As data loader is expecting the date in dd/mm/yyyy format while we provided in 01/23/2011 (MM/DD/YYYY) and  23 cannot be a month value, so 23 considered as 1 year and 11 months.
So the result will be 01/11/2012.

Now here you can see data loader is not going to block any record because of this format so you will have to be very careful with this. It's your responsibility to check the data loader setting and date format in csv file.

Please correct me if anything I am making wrong here. comments are welcome.