Using the Service layer and database access

As with the Visualforce Apex controller action methods you've seen in the earlier chapters, the Service layer is also designed to be called from Visualforce JavaScript Remoting methods, as follows:

public with sharing class RaceResultsController {
  @RemoteAction
  public static List<RaceService.ProvisionalResult>loadProvisionalResults(Id raceId) {
    return RaceService.calculateProvisionResults(
      new Set<Id>{ raceId }).get(raceId);
  }
}

To make Lightning Component controller server-side calls to Apex use the @AuraEnabled annotation method:

public with sharing class RaceResultsController {
  @AuraEnabled
  public static List<RaceService.ProvisionalResult>loadProvisionalResults(Id raceId) {
    return RaceService.calculateProvisionResults(
      new Set<Id>{ raceId }).get(raceId);
  }

You will also need to apply the @AuraEnabled method to accessors for Apex types referenced by the Controller methods:

public class ProvisionalResult {
   @AuraEnabled
   public Integer racePosition {get; set;}
   @AuraEnabled
   public Id contestantId {get; set;}
   @AuraEnabled
   public String contestantName {get; set;}
}

In both these cases, however, there is no try/catch block, as error handling is done by the client code to render the messages. When exceptions are thrown, the platform takes care of catching the exception and passing it back to the calling JavaScript code for it to display accordingly. In short, there is no need to invent your own error message handling system; just let the platform handle pass it back to the client JavaScript code for you. Remember though that you still need to handle the error message in your client side JavaScript logic; this will not be done by Visualforce for you.

Considerations for client-side logic and Service layer logic

With the addition of more complex logic in the client via JavaScript, more attention needs to be given to Separation of Concerns. The following points provide some guidelines for this:

  • Single service method per remoting method: A single Service layer method invocation rule should still be observed when developing remoting methods on the controller. If multiple Service layer methods are being called, this becomes a sign that a new aggregate Service layer method should be created and called instead.
  • Avoid remoting client bias: Do not be tempted to design your Service layer solely around your JavaScript Remoting controller method needs (the needs of your JavaScript client). Always consider the Service layer as client-agnostic; this becomes particularly important if you also want to also later expose your Service layer as an API to your application.
  • Apex enum types: If you utilize Enum types in your Service layer design (to be honest, why would you not?), they are very expressive and self-documenting! However, they unfortunately at this time are not supported by the JavaScript Remoting JSON de-serializer, which means that you can return Apex data structures containing them, but cannot receive them from the client (a platform exception occurs).

    The workarounds are to either not use enum's and drop back to using string data types or create Apex class data types within the controller class and perform your own marshaling between these types and service types (leveraging the Enum.name() method to map Enum's to string values). The choice is between your desire to protect your Service layer's use of Enum's (especially if it is your public-facing API) and the effort involved. Hopefully, at some point, Salesforce will fix this issue.

When should I use JavaScript for database access?

JavaScript Remote Objects and the Lightning Data Service are designed to expose a "SOQL- and DML-like API" for use by the JavaScript code embedded within a Visualforce page or Lightning Component. Providing a way to query and update the database without having to go through the traditional AJAX Toolkit or Salesforce REST API's that incur charges to the daily API limit.

Visualforce Developer's Guide has an excellent topic that describes the best practices around using this feature, entitled Best Practices for Using Remote Objects, which I highly recommend that you read and digest fully. The Lighting Component developer Guide also has samples describing the Lightning Data Service. The main aspect from this section which I would like to highlight is the one that relates to transactional boundaries in close conjunction with maintaining a good Separation of Concerns.

Resist the temptation to invoke multiple database operations within a single JavaScript code block as each will be executed in its own Salesforce execution context and thus transaction. This means that, if an error occurs in your JavaScript code, previous operations will not be rolled back.

If you find yourself in this situation, it is also likely that you should be positioning such code in your application's Service layer and thus using JavaScript Remoting to call that Service layer method, which will then occur within a single transactional scope.

That said, if you have use cases that result in a single database operation then you can of course consider using this feature, safely assured that your Apex Trigger and Domain layer code will continue to enforce your data validation and integrity.

Finally, note that querying records from JavaScript does not invoke your Selector code. So the fields queried and populated in the resulting SObject records on the client will not always be the same in all cases throughout your JavaScript code.

..................Content has been hidden....................

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