What is @api Decorator?
In the realm of Salesforce development, we often need to make our Apex code talk to other parts of the system or even external applications. This is where decorators, also known as annotations, come into play. Among these, the @api decorator holds a special place, acting as a key to unlock your Apex methods and properties for broader accessibility.
At its core, the @api decorator in Salesforce Apex is an annotation used to explicitly mark methods or properties within an Apex class, signaling that they are intended to be exposed and accessible from outside that specific Apex class. This exposure is crucial for enabling interactions with various Salesforce components and external systems.
Purpose of the @api Decorator
The @api decorator serves several vital purposes in Apex development:
- Accessibility Control: It clearly defines which parts of your Apex class are meant to be public interfaces. This makes it explicit that these members are available for use by other Apex classes, Visualforce controllers, Lightning components, and external integrations consuming your Salesforce APIs.
-
API Exposure: When you design a class intended to serve as a backend for other applications or components,
@apitells the Salesforce platform that these specific methods form the public API of your class. - Enabling Dynamic Apex: It plays a role in allowing for dynamic invocation of methods, where the method to be called might not be known until runtime.
Key Use Cases and Scenarios
The @api decorator is a cornerstone in modern Salesforce development, particularly with the rise of Lightning Web Components. Let’s explore some of its most common applications:
1. Lightning Web Components (LWC) Integration
This is arguably the most significant use case for @api today. Methods and properties decorated with @api in an Apex class are directly callable or accessible from LWCs. This is the primary mechanism by which LWCs fetch data from, or send data to, the Salesforce backend.
Example: Exposing an Apex Method to LWC
Consider an Apex class designed to retrieve account information:
public with sharing class AccountService {
/**
* Retrieves a list of accounts based on the provided industry.
* @param industry The industry to filter accounts by.
* @return A list of Account records.
*/
@api // This decorator makes the method callable from LWC
public static List<Account> getAccountsByIndustry(String industry) {
return [SELECT Id, Name, Industry FROM Account WHERE Industry = :industry LIMIT 10];
}
}
In your LWC’s JavaScript file, you would import and use this method:
import { LightningElement, wire } from 'lwc';
// Import the Apex method, using the '@salesforce/apex' namespace
import getAccountsByIndustry from '@salesforce/apex/AccountService.getAccountsByIndustry';
export default class AccountList extends LightningElement {
accounts;
error;
// Use the @wire decorator to call the Apex method reactively
@wire(getAccountsByIndustry, { industry: 'Technology' })
wiredAccounts({ error, data }) {
if (data) {
this.accounts = data;
this.error = undefined;
} else if (error) {
this.error = error;
this.accounts = undefined;
}
}
}
Notice how @salesforce/apex/AccountService.getAccountsByIndustry maps directly to the Apex method exposed by @api.
2. Visualforce Controllers
While LWCs are the modern standard, @api also facilitates interaction with Visualforce pages. Methods decorated with @api can be invoked from Visualforce pages using the familiar {! } syntax or through Apex action methods.
Example: Exposing a Property and Method to Visualforce
An Apex controller for a Visualforce page:
public with sharing class ContactController {
/**
* An API property that can be bound to from Visualforce.
*/
@api // Exposes this property to Visualforce
public String accountId { get; set; }
/**
* Retrieves contacts related to the bound account.
* @return A list of Contact records.
*/
@api // Exposes this method to Visualforce
public List<Contact> getContacts() {
if (String.isNotBlank(accountId)) {
return [SELECT Id, Name, Email FROM Contact WHERE AccountId = :accountId];
}
return new List<Contact>(); // Return empty list if no accountId
}
}
A corresponding Visualforce page:
<apex:page controller="ContactController">
<apex:pageBlock title="Contact Search">
<apex:pageBlockSection columns="2">
<apex:pageBlockSectionItem>
<apex:outputLabel value="Account ID:" for="accountIdInput"/>
<apex:inputText id="accountIdInput" value="{!accountId}"/>
</apex:pageBlockSectionItem>
</apex:pageBlockSection>
<apex:pageBlock title="Contacts">
<apex:pageBlockTable value="{!contacts}" var="c">
<apex:column value="{!c.Name}" headerValue="Contact Name"/>
<apex:column value="{!c.Email}" headerValue="Email"/>
</apex:pageBlockTable>
</apex:pageBlock>
</apex:pageBlock>
</apex:page>
Here, accountId and getContacts() are accessible because of the @api decorator.
3. Reusable Apex Libraries
When developing utility classes or libraries intended for use across multiple projects or by different developers within an organization, @api helps clearly delineate the public interface. This makes it easier for others to understand and utilize your code without needing to delve into its internal workings.
4. External API Integrations
While @api is not the primary mechanism for exposing your *own* Apex code as a public API to external systems (that’s typically handled by Salesforce APIs like REST or SOAP, or integration patterns like Platform Events), it is fundamental for the Apex methods that *interact with* external services. These methods process inbound API calls or act as intermediaries, and @api ensures they are callable within the Salesforce platform’s integration framework.
@api vs. `public` Keyword
This is a common point of confusion. In Apex, methods and properties declared with the public keyword are already accessible outside their class. So, what’s the difference with @api?
The @api decorator provides a more explicit and semantic declaration, particularly for frameworks like Lightning Web Components. For LWCs, @api is essential. It’s the decorator that the LWC framework specifically looks for to understand which Apex members are meant to be exposed to the JavaScript side. A public method without @api might not be directly discoverable or usable by an LWC in the same way.
Think of public as a general accessibility modifier, and @api as a specific directive for integration points, especially for modern UI frameworks.
Using @api on Properties
Beyond methods, @api can also be applied to properties (getters and setters) within an Apex class. This allows these properties to be directly bound to properties in LWCs, enabling data flow between the Apex controller and the component.
Example: LWC Property Binding with @api
An Apex class with an API property:
public with sharing class UserProfile {
/**
* The username of the user, exposed to the LWC.
*/
@api // This property can be set or read by an LWC
public String userName { get; set; }
// ... other methods and properties
}
In an LWC JavaScript, you can receive this value:
import { LightningElement, api } from 'lwc';
export default class UserProfileDisplay extends LightningElement {
// This @api property in LWC will receive a value from a bound Apex @api property
@api userName;
// You can also use it in the template, or set it imperatively
// Example: Assume some logic sets this.userName
}
This enables a straightforward way to pass data from Apex to your LWC.
Important Considerations
-
Access Modifiers:
@apiis typically used in conjunction with thepublicaccess modifier. It doesn’t replace the need for access control; rather, it enhances it for integration purposes. You cannot decorateprivateorprotectedmembers with@api. -
with sharingvs.without sharing: When your@apimethods are invoked from LWCs or Visualforce, thewith sharingorwithout sharingkeywords on your Apex class are critical.with sharingenforces the running user’s data access permissions, whilewithout sharingbypasses them. Choose wisely based on your security requirements. -
Metadata: The
@apidecorator is part of Apex’s metadata. When Salesforce compiles your Apex code, it registers these@apiannotated members in the metadata catalog, making them discoverable by other Salesforce features and integrations.
Troubleshooting Common Issues
-
“Method is not visible” or “Method does not exist” Errors:
- Cause: The Apex method you are trying to call is not properly exposed.
- Solution: Ensure the method is declared as
publicand, crucially for LWC integration, decorated with@api.
-
Data Not Flowing to/from LWC:
- Cause: Incorrect usage of
@wireor imperative calls, or the Apex property/method is not@apienabled. - Solution: Verify that the Apex method/property has the
@apidecorator. Double-check your LWC JavaScript for correct imports, parameter passing, and handling of the returned data. Ensure parameter names and data types match between Apex and LWC.
- Cause: Incorrect usage of
-
Sharing Rule Issues with
@apiMethods:- Cause: The Apex class might be using
without sharingwhen record-level security should be enforced, or vice-versa. - Solution: Explicitly define
with sharingorwithout sharingon your Apex class. If users report seeing incorrect data or no data when they should, check your Apex class sharing model.
- Cause: The Apex class might be using
@api Decorator in Interview Context
Understanding @api is fundamental for Salesforce developers. Here are some common interview questions related to it:
- Q: What is the primary purpose of the
@apidecorator in Apex?
A: It’s used to explicitly expose Apex methods and properties to be accessible from outside the Apex class, especially for consumption by Lightning Web Components, Visualforce controllers, and other integration scenarios. - Q: How does
@apidiffer from a standardpublicmethod in Apex?
A: Whilepublicmethods are generally accessible,@apiprovides a specific directive recognized by frameworks like LWC. It’s the definitive way to make Apex members available to LWCs. - Q: Can
@apibe used on private or protected methods?
A: No,@apiis designed for members that are intended to be part of the public API, so it’s used withpublicmethods and properties. - Q: How would you pass data from an LWC to an Apex method decorated with
@api?
A: You would typically use either the@wireservice with parameters or make imperative Apex calls from the LWC’s JavaScript, passing the data as arguments to the@apiannotated Apex method. - Q: In what scenarios would you find yourself heavily relying on the
@apidecorator?
A: When building custom Lightning Web Components that need to interact with backend Apex logic, creating reusable Apex utility classes for other developers, and integrating complex business logic into Visualforce pages.
In summary, the @api decorator is a powerful tool for controlling visibility and enabling seamless communication between your Apex code and the rest of the Salesforce ecosystem. It’s indispensable for modern Salesforce development, particularly when leveraging the capabilities of Lightning Web Components.
For more in-depth information, you can refer to the official Salesforce documentation: