Chapter 10. Providing Integration and Extensibility

Enterprise businesses have complex needs involving many human, device, and increasingly machine interactions, often distributed across the globe. Allowing them to work together in an efficient and secure manner is no easy task, and as such, it is no great surprise that utilizing cloud-based software over the Internet has become so popular. High-grade security, scalability, and availability is high on checklists when choosing a new application, often followed by API needs and the ability to customize.

By developing on the Force.com platform, your application already has a good start. The http://trust.salesforce.com/ site provides a wide selection of industry strength, compliance, and encryption standards that are equally applicable to your applications. With this comes a selection of standard APIs offered in the SOAP and REST forms as well as the ability to create your own application APIs. In my view, there is not a more integration-ready cloud platform available today than Force.com.

In this chapter, we will review the integration and extensibility options provided as standard on the platform and how your application can get the most from them, in addition to developing custom application APIs. Once again the Application Enterprise Patterns will come into play, supporting the need for APIs and UIs to have a strong functionality parity, through the use of the Domain and Service layers described in earlier chapters.

This chapter will cover the following topics:

  • Reviewing integration and extensibility needs
  • Force.com platform APIs for integration
  • Application-specific APIs
  • Alignment with Force.com extensibility features
  • Extending the application logic with Apex Interfaces

Reviewing your integration and extensibility needs

Before diving into the different ways in which you can provide APIs to those integrating or extending your application, let's review these needs through the eyes of Developer X. This is the name I give to a persona representing a consumer of your APIs and general integration and extensibility requirements. Much like its use in designing a user interface, we can use the persona concept to sense check the design and interpretation of an API.

Defining the Developer X persona

Asking a few people (internal and external to the project) to represent this persona is well worth doing, allowing them to provide use cases and feedback to the features and functions of your application's API strategy, as it is all too easy to design an API you think makes sense, but others with less knowledge of the application do not easily understand. A good way to develop a developer community around your API is to publish designs for feedback. Keep in mind the following when designing your API for Developer X:

  • Developer X is skilled in many platforms and programming languages these days, which might not always be Force.com. Increasingly Developer X is also creating Mobile, JavaScript, and Heroku applications around your API.
  • As the Internet of Things (IoT) continues to expand, there is also a shift towards device integration from consumer devices such as watches, fridges, cars, and jet engines. So, APIs that work well on-platform and off-platform are a must.
  • Developer X might not have an in-depth knowledge of the application domain (its functional concepts), thus it's important for them to be able to communicate with those that do, meaning that your API design and application functionality terminology has to be well-aligned.

The upcoming sections outline general considerations and needs around providing both an integration API and general extensibility of your application's functionality.

Versioning

As your product functionality grows, it is important to manage the impact this has on developers and partners who have already adopted your APIs in earlier releases of your application and not force them to make code changes unless needed. Where possible, maintain backwards compatibility such that even after your application has been upgraded in a subscriber org, existing integrations and extensions continue to work without modification (multiple versions of your application code are not stored in a subscriber org).

Without backwards compatibility you can inhibit upgrades to your application within your customer base, as the time spent by Developer X addressing API issues can delay upgrades and be expensive. Some subscribers might have utilized consulting services to affect the original work or be dependent on one of your partners for add-on solutions using your API.

Versioning falls into two categories: versioning the definition (or contract determined input and output of data) and the functionality (or behavior) each API represents.

Versioning the API definition

Once you have published a specific version of an API, do not change its definition, for example the Custom Objects, fields, Apex classes, methods, or members, or equivalent REST or SOAP constructs. Even though the platform will help avoid certain changes, additions can be considered a breaking change, especially new required fields. Anything that changes the definition or signature of the API can be considered a potential breaking change.

Developer X should be able to modify and redeploy their existing integrations or extensions without having to recode or adjust their code using your API and without forcing them to upgrade to the latest version of your API, unless, of course, they want to access new functionality only accessible by completing new fields. Note that this is different from upgrading the package itself within the subscriber org, which must be allowed to happen.

The standard Salesforce APIs and platform help provide versioning when Developer X interacts with your Custom Objects and Application APIs. Versioning is implemented as follows:

  • In an Apex code context, the platform retains the version of your package installed when the Apex code was first written by Developer X, and then only ensures that Apex classes, methods, members, Custom Objects, and fields visible in this packaged version are visible to the code. This feature is something that we will explore in further detail later in this chapter.
  • In the case of the SOAP and REST APIs, by default the latest version of your Custom Objects is visible. When using the SOAP API, header values can be passed in such calls to lock a particular package version if needed (search for PackageVersionHeader in Apex Developer's Guide). Alternatively the packaged version used by these APIs can be set at an org-configuration level.

Versioning application access through the Salesforce APIs

Under the Setup menu, search for API. You will find a setup page that allows you to download the WSDLs for one of the many Salesforce SOAP APIs. In the next section there are some versioning settings that determine which installed package version should be assumed during interactions with your packaged objects.

For example, when performing a describeSObject web service operation via the Salesforce Enterprise or Partner APIs, these APIs will return different custom fields depending on when new fields were added, as new versions of the package have been released over time. The default behavior will return all fields as the default is the current package version.

If this is important to Developer X or third-party solutions when using these Salesforce APIs, the subscriber administrator can specify an explicit previous version. If they do this, new fields available in future package versions will not be available unless this is changed. The following screenshot shows how these settings can be accessed on the API page under Setup:

Versioning application access through the Salesforce APIs

Note

Only available if you have one or more managed packages installed.

Versioning the API functionality

When offering new versions of your application to users through the UI, new features are accessed by the user—either by opting into the feature by configuration using a new page or button, or sometimes just seamlessly such as a new type of calculation, optimization, or improvement to existing behavior with added benefits.

As the API is just another way into your application's logic, you should think about enabling these new features through the API in conceptually the same way. If it is seamlessly available through the UI to users, it becomes so in the API regardless of the API version, and thus, solutions built around your application's API will also benefit automatically without changes to the integration or extension code. However, if there is a new field or button needed in the UI, then a new API parameter or operation will be needed to enable the new feature. It is reasonable for this to be exposed in a new version of your API definition. Thus, Developer X will have to modify the existing code, test it, and deploy it before the solution can leverage it.

Trying to be sophisticated in your code by providing exactly the same behavior to older callers of your API will depend on the Service and Domain layers understanding the concept of API versus UI contexts and package versioning, which will rapidly become complex for you to develop, test, support, and document.

Tip

Agree and communicate to your customers and partners clearly how many versions of your API you will support and give warning on retirements. Always be sure to test your APIs at different versions to ensure the lack of fields that arrive later in your package, which are not provided by older callers, does not cause errors or unwanted behavior in these cases. Try to avoid adding new required fields to your applications without a way to default them.

If in your regression testing of older API versions, you notice a reduction in data volume throughput due to governors, it can be acceptable to condition newer logic (such as checks for newer fields). Again, be careful with how often you implant this type of conditional logic in your code base.

Translation and localization

As with the guidelines around the Service layer, which can be used as a means to form your application API later in this chapter, you should ensure that any error or status messages are translated according to your use of Custom Labels, as described in Chapter 2, Leveraging Platform Features (the Apex runtime will ensure that the user locale determines the translation used).

Tip

It is not possible to override the default Org language used to look up the appropriate Custom Labels through Apex. However, if the API is called from a Visualforce page utilizing the language attribute as described in Chapter 8, your API code will also honor this.

Some APIs expose error codes to provide a language-neutral way to recognize a certain error use case programmatically (parsing the message text is not reliable in a translated environment). As such, one approach is to use an Apex enum and a custom Apex exception class, which captures both the translated error message and the exception code. The following enum and exception types are defined in the Application class contained within the sample code for this chapter. Note the use of the global keyword in Apex; this will be discussed later in this chapter in more detail:

global Application {
  global enum ExceptionCode {
    ComplianceFailure,
    UnableToVerifyCompliance
  } 
  global virtual class ApplicationException extends Exception {
    global ExceptionCode ExceptionCode {get; private set;}
    public ApplicationException(ExceptionCode exceptionCode, String message) {
      this(message);
      this.exceptionCode = exceptionCode;
    }
  }
}

While the preceding ApplicationException class can be used as it is, the following ComplianceService class has its own custom exception that can then extend this:

global class ComplianceException extends Application.ApplicationException {
  global List<VerifyResult> failures {get; private set;}

  public ComplianceException(Application.ExceptionCode exceptionCode, String message, List<VerifyResult> failures) {
      super(exceptionCode, message);
      this.failures = failures;
  } 
}

This code can then raise exceptions specifying the enum value related to the message as follows:

throw new ComplianceException(
  Application.ExceptionCode.ComplianceFailure, 
  Label.ComplianceFailuresFound, 
  failedCompliances);
throw new ComplianceException(
  Application.ExceptionCode.UnableToVerifyCompliance,
  Label.UnableToVerifyCompliance, 
  null);

As with the Service layer guidelines, the API should be client agnostic, and thus you cannot assume whether the data values accepted or returned should be formatted or not. Thus, it is best to use the native Apex types for date, date/time, and number and allow the caller to decide whether or not to format the values. Returning formatted values is useful for UI callers, but for headless or automated solutions, this is not ideal.

Terminology and platform alignment

If you're following the guidelines of the Service layer when defining your classes, methods, parameters, and interfaces (as discussed later in this chapter), then any API based on this layer should already mirror the functional terms used in your application. Having a good alignment with your application terms makes your API easier to map to functional concepts in your application and thus for Developer X to navigate around and understand and discuss with those that know the application in more functional depth.

In addition, like the Service layer, your API should support platform concerns such as bulkification and not inhibit Developer X from calling your API in a bulkified way to make optimum use of the platform resources. This also includes Developer X utilizing Apex DML statements and thus then raises the importance of bulkified Domain layer logic as well as bulkified Service layer logic.

What are your application's integration needs?

Typically an integration need arises from a controlling process or application that consumes the functionality of your application, effectively invoking the functionality within your application automatically on behalf of a user, or as part of an event or scheduled background process. Both, the standard Salesforce APIs and any additional application APIs that you create can support this need. The following diagram shows a controlling system driving your application through either the standard Salesforce API and/or application APIs that you have provided as part of the managed package:

What are your application's integration needs?

Although integrations are much easier when all applications are built based on the same platform, it is a good practice to have an API strategy that covers both, on-and off-platform, Developer X scenarios, ideally exposing the same functionality consistently.

Developer X calling your APIs on-platform

A Force.com Apex developer can manipulate the data stored in your application through Apex DML statements. You can think of Apex DML as your free Apex API to your application data, as this approach avoids the need for you to build your own application APIs to purely manage record data, particularly for those Custom Objects that you are already exposing through the standard Salesforce UI.

Tip

It can be a useful aid to these developers to browse your Custom Object schema through Salesforce Schema Builder, as highlighted earlier in this book. Try to avoid inconsistencies between your Field Labels and Field API names (though the Schema Builder does permit toggling of these), as this can make it harder for developers and those expressing the requirements to collaborate.

Just because Apex is being used does not mean that Developer X can bypass logic in your managed Apex Triggers. However, take note that they can also write Apex Triggers of their own, which can execute before yours (as the Apex Trigger order is nondeterministic). To avoid Developer X triggers making invalid changes to record data, ensure that you follow the best practice when you're writing the validation logic to place it in the after-phase of your application triggers. As discussed in the previous chapter, utilizing the Domain pattern will ensure this.

Later in this chapter we will discuss application APIs that expose functionality not directly related to manipulating your Custom Object records, but one that is more business logic related, for example exposing the ComplianceService.verify method. In this case, by making the Service class and methods global as opposed to public, you can make this same method available to Developer X. As an extension to your Apex API strategy, allow them to consume it in the same manner as you do within your application.

The motivation behind this approach, described further in this chapter, is to ensure that the maximum amount of your application functionality is available through your API as your application evolves. However, if you do not want to expose your full Service layer directly as your application API, you can elect to create separate Apex classes that define your API which delegate to the Service layer or selectively apply the global keyword to your Service methods.

Developer X calling your APIs off-platform

Developer X using languages such as Java, .NET, NodeJS or Ruby uses the HTTP protocol to connect between the two platforms. Salesforce provides APIs to log in and authorize access for you as well as APIs to manipulate the data in your Custom Objects much like using Apex DML. Salesforce currently chooses to expose both SOAP- and REST-based variants of its HTTP-based APIs. So again, you need not develop your own APIs for this type of data integration.

Tip

Many third-party Salesforce integration applications leverage platform APIs and as such will also work with your application data; this fact is a key platform benefit for you and Developer X.

When it comes to exposing application APIs, to support SOAP and REST, you will need to develop separate Apex classes in each case for each API that you want to expose. This is because the definition and design of these types is different, though the functionality your exposing is the same. We will discuss this further later in this chapter.

SOAP versus REST

If you have been following the debate over SOAP versus REST or just simply Google for it, you'll know that there is currently a general trend towards REST. As it's easier to code against and consume in mobile and JavaScript-based scenarios, most major cloud services such as Facebook and LinkedIn only provide REST versions of their APIs. For ease of use and the ability to be more self-describing I prefer REST also.

What are your applications extensibility needs?

So far we have been discussing providing facilities to build custom solutions around your application, which is one type of integration. Another is providing ways to make extensions to its existing business logic. In an extensibility use case, Developer X or an administrator is happy for your users to consume your application UI and functionality directly but wants to extend it in some way to add additional functionality or updates to other Custom Objects. Some examples of the type of extensions you might want to consider are as follows:

  • Adding subscriber-created Custom Fields to Visualforce Pages and Field Sets is an easy way to achieve this
  • Providing alternatives to hardcoded Email messages via Email Templates
  • Extending the application Apex code logic with the subscriber-written Apex logic; this is something I call Application Callouts

In this chapter we will explore Application Callouts further. The following diagram shows processes in your application code making use of this approach to execute code written by Developer X. Later in this chapter we will see an example of how can implement these through the use of Apex interfaces and Custom Metadata records.

What are your applications extensibility needs?
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.27.171