Zoometric Traits in Murciano-Granadina Dairy Goats and Bucks
4. Discussion
public String getT2() {
if (t2 == null) t2 = System.now();
return '' + t2;
} }
Using the with sharing or without sharing Keywords
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.
Note: The only exceptions to this rule are Apex scripts that are executed with the executeAnonymous call.
executeAnonymous always executes using the full permissions of the current user. For more information on executeAnonymous, see Anonymous Blocks on page 70.
Because these rules are not enforced, developers who use Apex must take care that they do not inadvertently expose sensitive data that would normally be hidden from users by profile-based permissions, field-level security, or organization-wide defaults.
They should be particularly careful with Web services, which can be restricted by profile, but execute in system context once they are initiated.
Most of the time, system context provides the correct behavior for system-level operations such as triggers and Web services that need access to all data in an organization. However, you can also specify that particular Apex classes should enforce the sharing rules that apply to the current user. (For more information on sharing rules, see the Salesforce.com online help.)
Note: A user's profile-based permissions and field-level security are always ignored to ensure that Apex scripts can view all fields and objects in an organization. If particular fields or objects are hidden for a user, the script would fail to compile at runtime.
Use the with sharing keywords when declaring a class to enforce the sharing rules that apply to the current user. For example:
public with sharing class sharingClass { // Code here
}
Use the without sharing keywords when declaring a class to ensure that the sharing rules for the current user are not enforced. For example:
public without sharing class noSharing { // Code here
Keywords
}
If a class is not declared as either with or without sharing, the current sharing rules remain in effect. This means that if the class is called by a class that has sharing enforced, then sharing is enforced for the called class.
Both inner classes and outer classes can be declared as with sharing. The sharing setting applies to all code contained in the class, including initialization code, constructors, and methods. Classes inherit this setting from a parent class when one class extends or implements another, but inner classes do not inherit the sharing setting from their container class.
For example:
public with sharing class CWith {
// All code in this class operates with enforced sharing rules.
Account a = [select . . . ];
public static void m() { . . . } static {
. . . } {
. . . }
public c() { . . . } }
public without sharing class CWithout {
// All code in this class ignores sharing rules and operates // as if the context user has the Modify All Data permission.
Account a = [select . . . ];
. . .
public static void m() { . . .
// This call into CWith operates with enforced sharing rules
// for the context user. When the call finishes, the code execution // returns to without sharing mode.
CWith.m();
}
public class CInner {
// All code in this class executes with the same sharing context // as the code that calls it.
// Inner classes are separate from outer classes.
. . .
// Again, this call into CWith operates with enforced sharing rules
// for the context user, regardless of the class that initially called this inner class.
// When the call finishes, the code execution returns to the sharing mode that was used to call this inner class.
CWith.m();
}
public class CInnerWithOut exends CWithout {
// All code in this class ignores sharing rules because
Keywords
} }
Caution: There is no guarantee that a class declared as with sharing does not call a script that operates as without sharing. Class-level security is always still necessary. In addition, all SOQL or SOSL queries that use PriceBook2 ignore the with sharing keyword. All PriceBook records are returned, regardless of the applied sharing rules.
Enforcing the current user's sharing rules can impact:
• SOQL and SOSL queries. A query may return fewer rows than it would operating in system context.
• DML operations. An operation may fail because the current user does not have the correct permissions. For example, if the user specifies a foreign key value that exists in the organization, but which the current user does not have access to.
Annotations
An Apex annotation modifies the way a method is executed, similar to annotations in Java.
Annotations are defined with an initial @ symbol, followed by the appropriate keyword. To add an annotation to a method, specify it immediately before the method definition:
global class MyClass {
@future
Public static void myMethod(String a) {
//long-running Apex code }
}
Apex supports the following annotations:
• future
• isTest
Future
Use the future annotation to identify methods that are executed asynchronously. When you specify future, the method executes when Salesforce has available resources.
For example, you can use the future annotation when making an asynchronous Web service callout to an external service.
Without the annotation, the Web service callout is made from the same thread that is executing the Apex script, and no additional processing can occur until the callout is complete (synchronous processing).
Methods with the future annotation must be static methods, and can only return a void type.
To make a method in a class execute asynchronously, define the method with the future annotation. For example:
global class MyFutureClass {
@future
static void myMethod(String a, Integer i) {
System.debug('Method called with: ' + a + ' and ' + i);
//do callout, other long running code
Annotations
} }
The following snippet shows how to specify that a method executes a callout:
@future (callout=true)
public static void doCalloutFromFuture() { //Add code to perform callout
}
You can specify (callout=false) to prevent a method from making callouts.
Methods with the future annotation have the following limits:
• No more than 10 method calls per Apex invocation
• No more than 200 method calls per Salesforce license per 24 hours
• The parameters specified must be primitive dataypes, arrays of primitive datatypes, or collections of primitive datatypes.
• Methods with the future annotation cannot take SObjects or objects as arguments.
Remember that any method using the future annotation requires special consideration, because the method does not necessarily execute in the same order it is called.
You cannot call a method annotated with future from a method that also has the future annotation. Nor can you call a trigger from an annotated method that calls another annotated method.
IsTest
Use the isTest annotation to define classes or individual methods that only contain code used for testing your application.
The isTest annotation is similar to creating methods declared as testMethod.
Note: Classes defined with the isTest annotation do not count against your organization limit of 1 MB for all Apex scripts. Individual methods defined with the isTest annotation do count against your organization limits. For more information, see Understanding Execution Governors and Limits on page 142.
Classes and methods defined as isTest must be declared as private. For example:
@isTest
private class MyTest { // Methods for testing }
Classes defined as isTest cannot be interfaces or enums.
A class defined as isTest can only be invoked using the Force.comrunTestsAPI call, or from the Salesforce user interface (using the Run Tests button). You cannot call it from another class or trigger.