July 30, 2011

XCollections - Using UDT with Map & Set in Apex !

Update Nov : 2011

XCollections is no more an independent project/API, its part of apex-commons now. XCollections is added to sub repository called  “collections” under apex-commons, all development and latest updates about it can be found here : https://github.com/abhinavguptas/collections. This post is also updated for hyperlinks and other details as per this recent change

What XCollections ?

Apex comes with a rich and continuously maturing library of native APIs. One of my favorite is Collections since my Java days. I always enjoyed presence of all 4 basic collections in Apex i.e.

  • Array & List : A list is an ordered collection of typed primitives, sObjects, user-defined objects, Apex objects or collections that are distinguished by their indices.
  • Set : A list is an ordered collection of typed primitives, sObjects, user-defined objects, Apex objects or collections that are distinguished by their indices.
  • Map : A map is a collection of key-value pairs where each unique key maps to a single value. Keys can be any primitive data type, while values can be a primitive, sObject, collection type or an Apex object.

We all know these collections do a good job as per their role and use cases.

What I’m missing Apex Collections !

Apex collections need to improve on a couple of areas for ex.

  1. Support for advanced sorting, not just sorting of primitives in List.

    We are lucky here, Richard Vanhook created an awesome library called apex-lang, now moved to git and known as apex-commons. That filled this advanced sorting gap and provided ability to do complex sorting using Java style Comparator/Comparable support. Please check ArrayUtils on Google Code project for more details.

  2. Support for Apex Objects OR UDT(User Defined Type/Classes) in Set & Maps

    Other piece of functionality that I really miss in Set & Maps is they don’t support Apex Objects or UDT(User Defined Types) as items or keys. Though most of the times in simple project we don’t need to use UDT’s with Set or Map, but on some occasions if this support is available. It could be a real time saver.

XCollections to provide missing UDT support in Sets & Maps !

imageXCollections is created to overcome the second limitation, i.e. to create an Apex API that will give UDT support in Sets & Maps.

So XCollections API is kick started with these two collections

1. XSet : One can add UDTs as item to this set.

2. XMap : One can use UDTs as keys to this Map.

Good news is that,  both these xcollections will support 99% methods available in Apex Set and Maps, with user defined apex classes Smile

Is your Apex Class or UDT – XKeyable ?

Guys form Java background must be aware that Set & Maps (Hash based) depend on two key methods in Object class i.e. hashcode() and equals(). It’s a good practice in Java to override and give a nice implementation of these methods when you are planning to use UDT's in Set/Map.

As Apex Object class is not having any such provision of hashcode() or equals() method, we required something to enforce end user to let XCollections know about similarity/equality of two different UDT instances. So, XCollections came up with a brand new interface called “XKeyable”, this interface is having a single method : “String getUniqueKey()” this method is the key for XCollections to know about two custom apex class instances being similar or different.

Here is code of XKeyable interface :

/**
        Client API looking forward to use XMap and XSet with UDT's should implement this interface for 
        UDT's participating as KEY in XMap and Item for XSet.
    */
    global interface XKeyable {
      /**
         Returns the Unique Key for this object, this Unique should be based on state.
         @return A unique String composite or single key for this state of object.
      */
      String getUniqueKey ();
    }

and here is a sample implementation :

global class Employee implements XKeyable {
       String name;
       String mobile;
       String landLine;
       Integer age;
       boolean isMale;
       String postalAddress;
       
      global Employee (String n, String m, String l, Integer a, Boolean im, String pa) {
        name = n; 
        mobile = m;
        landLine = l;
        age = a;
        isMale = im;
        postalAddress = pa;
      }
      
      global String getUniqueKey() {
        // assuming no two guys from same postal will carry same mobile and name :)
        return name + mobile + postalAddress;
      }
    }

So, in above code sample of Employee class, we easily implemented the getUniqueKey() method by just doing string concatenation of all the attributes that will comprise a unique composite key.

Now, this Employee class can be used in Xset as shown below:

static testMethod void testXSet() {
        XSet setx = new XSet();
        setx.add(new Employee('Abhinav', '232 256-1223', '432 456-3233', 17, true, 'Palam Vihar, Gurgaon, India'));
        // adding another employee with same key details i.e. name, mobile and postal. 
        setx.add(new Employee('Abhinav', '232 256-1223', '123 333-4444', 30, true, 'Palam Vihar, Gurgaon, India'));
        
        // Set should be of Size 1 as per uniqueness criteria
        System.assertEquals(1, setx.size());
        
        // adding another employee with different key details i.e. mobile no changed
        setx.add(new Employee('Abhinav', '555 333-2222', '123 333-4444', 30, true, 'Palam Vihar, Gurgaon, India'));
        
        // Set should be of Size 2 as per uniqueness criteria
        System.assertEquals(2, setx.size());
    }

Limitations of XCollections

One of the major limitation you will see with immediate effect is lack of Generics support. You can declare strongly typed collections in Apex for ex.

Set<string> aset = new Set<string>();
Map<id, Account> accountMap = new Map<id, Account>();

But as Apex doesn't supports Generics or Templates for user defined classes, XSet and XMap will not be that strongly typed. Similar code in XCollections format would be as follows.

XSet aset = new XSet();
XMap  accountMap = new XMap();

I know this is not cool, but it has to be like this until apex releases support for generics or templates. Sounds like strong candidate for IdeaExchange ?

~ XCollections road map ~

My plans with XCollections is to bring all Java collections API richness to it. Though here are some high level thoughts

  1. Support for User Defined Classes in Set & Maps via XSet and XMap, as discussed above.
  2. Add new collections like LinkedMap(ordered keys), TreeSet(Sorted Set) and other Java collections that are portable to Apex.
  3. Right rich suite of Apex test cases not just for sake for coverage, but for really testing all corners of the API Smile
  4. Give rich documentation and code samples !

Goal is to first give a stable version of XMap and XSet, and later move to rest of the items in roadmap.

XCollections on GITHUB !

All code so far is committed on github here :https://github.com/abhinavguptas/collections

July 28, 2011

Preparing for Salesforce AppExchange Security Review !

This post is for guys who are planning to release their app on App Exchange and are looking forward to clear security review in one shot ! This post aggregates all the good links and information you should have in hand.

Pointers for getting started  !

Please go thru following points to better understand the security review process and expectations

  • Force.com AppExchange & OEM Security Review : This page is having all the good links and information one needs to know for implementing the security correctly. This page gives you complete idea about various steps and the security review process, so going forward in this post, I will not focus on the process.
  • Good video for those who hate reading long text Smile
    How to prepare for Your AppExchange Security Review
  • Security Review Cost as of now is 300$ for initial review and $150 for subsequent annual reviews. For up to date information please check this link.
  • Checkout FAQ page on Salesforce WIKI : http://wiki.developerforce.com/index.php/Security_Review_FAQ

How to implement security correctly ?

Following are the points to follow

  • Make sure you read the Force.com Requirements Checklist carefully, its good to give a dose of this to developers before they start coding Smile. For better understanding of various technical items, please go thru the OWASP Top Ten Checklist also.
    • More details on how to implement security is available in Secure Coding Guidelines here. This is a good document on various security risks from force.com standpoint.
    • Use Security Coding Library in Apex to easily CRUD/FLS rules, this mostly ignored by almost all developers. More details about it available in this post
  • At regular intervals (every few weeks) during development, please execute following two scanners
    • Force.com Security Source Scanner : This scanner scans Apex/Visualforce code on various critical security and code quality issues. This is a really useful & highly recommended tool (also available as Eclipse plugin if required), it runs async and gives you PDF report having issue details and solutions too. List of some of those issues is mentioned below, most of these are self explanatory and more details for ambiguous ones are available in  Security Coding Guidelines. If development team takes care of all the below issues, most of your security review hassles would be gone Smile 
      • Reflected XSS        
      • SOQL SOSL Injection
      • Stored XSS
      • Sharing
      • Hardcoding Ids
      • Queries With No Where Or Limit Clause
      • Hardcoding References To Static Resources
      • Test Methods With No Assert
    • Web Application Security Scanner : This is tool is based on a paid application called Burp Suite. That gives you an easy way to simulate variety of security attacks like SOQL Injection etc. ISV Partners can request for free licenses of this application by filling in the form available on this page : http://security.force.com/webappscanner
  • Its good to occasionally participate in Security Quiz available here : http://security.force.com/platformquiz
  • Apart from that once you submit application for security review, salesforce will confirm following items from you, not all of these items are mandatory but its really good for quality stand point if your application adheres to these standards i.e.
    • Triggers are bulkified : Trigger logic supports trigger.new collection of greater than 1 record. 
    • Remove Hardcoded IDs : Class and triggers do not reference any hardcoded ids.
    • Test Bulk Logic Support
      1. Create 100 test records in xls or csv
      2. Run data loader (for each individual trigger type: insert, update, delete)
      3. Validate logic was successfully applied to all records
    • Remove System.Debug : Removed all unnecessary system.debug() statements from code (excluding test classes/methods).
    • Access Controls : Apex scripts generally run in system context, that is, the current user's profile-based permissions, field-level security, and sharing rules are not taken into account during script execution.
      Leverage the “with sharing” keyword when declaring a class to respect sharing rules that apply to current users, unless there is a specific business case to over-ride this. Controllers retrieving user-specified objects should always use sharing.
    • XSS & SOQL injection issues in Apex & Visualforce. If you have followed the secure coding guidelines and executed the source code scanner as explained above, then no need to worry about this one.
    • Do your test cases contain adequate System.assert methods to prove that all your code behaves properly?
  • Escaping false requires care: If you are using <apex.ouputText /> tag with attribute “escape = false” then please make sure either
    • The value being printed is some fixed non user inputted text like
      <apex:outputText escape="false" value="{!"<!DOCTYPE html>"}"/>
        
    • Else, value is being escaped via Apex etc using Security Coding Library escape functions or any other equivalent. For ex.
      String usertext = ApexPages.currentPage().getParameters().get('usertext');
      // the next line encodes the usertext similar to the VisualForce HTMLENCODE function but within an Apex class.
      usertext = ESAPI.encoder().SFDC_HTMLENCODE(usertext);
  • For those who are building complex mashup’s this table below has decent details of security issues that can lead to rejection in security review process
  • Lastly, make sure your application works correctly Open-mouthed smile Salesforce team would request you to setup and org for them to play with the app !

Any other tips and tricks ?

Do you want to add anything I missed here, please let me know !

July 17, 2011

Idea - “Managed” Package Extensions to reuse Base “Managed” Package Prefix !

Recently I came across a requirement where I need to

  • Create package extensions to an existing  Salesforce application.
  • This application is already having a managed package created.
  • All the new package extensions will include that managed package as dependency and will add on their respective features.

To start prototyping for customer, we quickly did following steps. For more details on creating packages and extensions please refer developerforce.com and salesforce documentations.

image

The above steps in image are from this developerforce wiki page.

I completed all the above 5 steps and was ready with basic extension functionality for demo soon (thanks to force.com platform goodness). So I was having a cool “unmanged” package extension created for a “managed” package. This unmanaged extension was ready and installable !

Please note : I was able to create an “unmanaged” package extension, that means the extension was having no package prefix, upgrading support and all cool benefits of going “managed” !

What’s the big deal in creating managed extensions ?

One can easily create package extensions that are “managed”, but the DE Org 2 (Extension Development Org) needs to get its own namespace prefix and that will be carried over to the extension. Once we assign an org wide namespace prefix, and create extensions, they will be managed.

Pain point here is both “managed” package and “managed” extension will carry different namespace prefixes, does it sounds good ? NO, would like to have same “managed” package prefix carried over to the “managed” package extensions. Imagine an Salesforce application having 4-5 extensions each carrying its own prefix, doesn’t sounds good.

Regarding the same I had a good discussion with @shobyabdi and @cirruscg on twitter ! Many Thanks to both for helping me understand  i.e. managed package and managed package extensions carry different prefixes, I was in strong impression about some way to use the same managed package prefix in extensions too Smile

imageimage

New Idea for having this feature !

It would be nice to have this feature in salesforce i.e. Both “Managed” Package and “Managed” Package Extensions carry the same prefix !

So I have created this idea on Idea Exchange, please VOTE and PROMOTE it !

Link to idea : https://sites.secure.force.com/success/ideaView?c=09a30000000D9xtAAC&id=08730000000ZZkaAAG

Feedback & Suggesions ?

If you have some cleaner way of handling this problem, I would love to hear back. Please share your views via comments.