Salesforce-Platform-Developer-II Exam Questions With Explanations

The best Salesforce-Platform-Developer-II practice exam questions with research based explanations of each question will help you Prepare & Pass the exam!

Over 15K Students have given a five star review to SalesforceKing

Why choose our Practice Test

By familiarizing yourself with the Salesforce-Platform-Developer-II exam format and question types, you can reduce test-day anxiety and improve your overall performance.

Up-to-date Content

Ensure you're studying with the latest exam objectives and content.

Unlimited Retakes

We offer unlimited retakes, ensuring you'll prepare each questions properly.

Realistic Exam Questions

Experience exam-like questions designed to mirror the actual Salesforce-Platform-Developer-II test.

Targeted Learning

Detailed explanations help you understand the reasoning behind correct and incorrect answers.

Increased Confidence

The more you practice, the more confident you will become in your knowledge to pass the exam.

Study whenever you want, from any place in the world.

Salesforce Salesforce-Platform-Developer-II Exam Sample Questions 2025

Start practicing today and take the fast track to becoming Salesforce Salesforce-Platform-Developer-II certified.

22024 already prepared
Salesforce Spring 25 Release
202 Questions
4.9/5.0

An Apex trigger and Apex class increment a counter, Edit __C, any time the Case is changed.

A. Option A

B. Option B

C. Option C

D. Option D

C.   Option C

Explanation:

To determine the correct option for incrementing the Edit_Count__c field on a Case object whenever it is changed, we need to analyze the provided Apex trigger and class implementations. The trigger is a before update trigger on the Case object, and the goal is to ensure the Edit_Count__c field increments only once per update operation, avoiding multiple increments due to recursive trigger calls. Let’s evaluate each option step-by-step.

Trigger and Requirement Analysis

The trigger is defined as:
trigger on Case (before update) {
CaseTriggerHandler.handle(Trigger.new);
}

This trigger calls a static method handle in the CaseTriggerHandler class, passing the list of new Case records (Trigger.new). The handle method is responsible for incrementing the Edit_Count__c field. Since it’s a before update trigger, the field can be modified directly on the records in Trigger.new without requiring a separate DML operation. However, a common challenge with triggers is recursion—e.g., updating the record within the trigger could cause it to fire again, leading to unintended multiple increments. We need a mechanism to prevent this, ensuring the counter increments only once per update.

Evaluating the Options

Option A:
Analysis: This implementation simply loops through the cases and increments Edit_Count__c by 1 for each record. However, it lacks any recursion control. If the trigger update causes another update (e.g., via a workflow or process), the trigger will re-execute, incrementing the counter multiple times. This does not meet the requirement of a single increment per change.
Verdict: Incorrect due to potential recursion issues.

Option B:
Analysis: This approach uses a firstRun Boolean to control execution. The trigger sets firstRun = true before calling handle, and the handle method checks this flag to perform the increment only if firstRun is true, then sets it to false. However, there are issues:

➜ firstRun is an instance variable in the class, but the handle method is static. Static methods cannot directly access instance variables unless they are also static or passed as parameters, which isn’t done here. This code would not compile due to this mismatch.
➜ Even if made static (e.g., static Boolean firstRun), the trigger and class logic would need to align properly. The current setup has redundant checks and could still fail if multiple updates occur in the same transaction context, as firstRun would reset with each trigger invocation.

Verdict: Incorrect due to compilation errors and ineffective recursion control.

Option C:
Analysis: This version declares firstRun as a static Boolean initialized to true but does not use it in the handle method to control execution. The handle method always increments Edit_Count__c for each case, with no recursion prevention. Like Option A, this risks multiple increments if the trigger fires again due to a subsequent update. The firstRun variable is unused, making this implementation incomplete.
Verdict: Incorrect due to lack of recursion control.

Option D:
Analysis: Here, the firstRun Boolean is defined within the trigger context, set to true initially. The if (firstRun) condition ensures the handle method runs only once per trigger execution, and firstRun is set to false afterward. Since it’s a local variable in the trigger, it resets with each new transaction but persists within a single trigger invocation. This prevents recursion within the same update operation—e.g., if a workflow updates the record, the trigger won’t re-execute the increment logic. The handle method then safely increments Edit_Count__c for each case. This approach effectively limits the increment to once per update.
Verdict: Correct, as it prevents recursion and ensures a single increment per change.

Conclusion:
The requirement is to increment Edit_Count__c once per Case update, avoiding multiple increments due to recursion. Option D uses a local firstRun Boolean in the trigger to control execution, ensuring the handle method runs only once per update. Options A and C lack recursion control, while Option B has a compilation error due to the instance variable mismatch. Thus, the correct answer is:
D. Option D

Which three approaches should a developer implement to obtain the best performance for data retrieval when building a Lightning web component? (Choose 3 answers)

A. Use lazy load for occasionally accessed data.

B. Use layoutTypes: 9'Full') to display a set of fields.

C. Use the Lightning Data Service.

D. Use getRecordUi to obtain metadata.

E. Use {Cacheable=true} whenever possible

A.   Use lazy load for occasionally accessed data.
C.   Use the Lightning Data Service.
E.   Use {Cacheable=true} whenever possible

Explanation:

✅ A. Use lazy load for occasionally accessed data

➡️ Why it helps: Lazy loading defers loading data until it’s actually needed, which improves initial load time and reduces unnecessary server calls.
➡️ Use case: When data is only needed upon user interaction (e.g., expanding a section or switching tabs), lazy loading improves performance.
➡️ Result: Faster initial render and optimized use of resources.

✅ C. Use the Lightning Data Service

➡️ Why it helps: Lightning Data Service (LDS) loads, caches, and shares record data without requiring Apex.
➡️ It avoids server round trips and handles field-level security and sharing automatically.
➡️ Result: High-performance, low-maintenance data access aligned with platform standards.

✅ E. Use {cacheable=true} whenever possible

➡️ Why it helps: When an Apex method is annotated with @AuraEnabled(cacheable=true), results are cached on the client side.
➡️ This reduces unnecessary Apex calls for data that doesn’t change frequently.
➡️ Result: Faster response time and reduced server load.

❌ Why the other options are incorrect:

❌ B. Use layoutTypes: 'Full' to display a set of fields

➜ This option refers to a metadata-driven UI feature, but using layoutTypes like 'Full' can return more fields than necessary, leading to over-fetching.
➜ It’s not performance optimized compared to fetching only specific fields using getRecord.

❌ D. Use getRecordUi to obtain metadata

➜ getRecordUi is useful for fetching layout and metadata, but it returns a lot of data, which can impact performance if used frequently or for high-volume pages.
➜ Not optimal for regular data retrieval—it’s better for dynamic form generation, not bulk performance.

📚 Reference:
Lightning Web Components Performance Best Practices
LDS vs Apex Data Access
@AuraEnabled(cacheable=true) – Apex Documentation

🧠 Key Takeaway:
Use lazy loading, Lightning Data Service, and cacheable Apex methods to get the best performance in Lightning Web Components. Avoid over-fetching metadata or fields you don't need.

A developer writes a Lightning web component that displays a dropdown list of all custom objects in the org from which a user will select. An Apex method prepares and returns data to the component. What should the developer do to determine which objects to include in the response?

A. Check the isCustom() value on the sObject describe result.

B. Import the list of all custom objects from @salesforce/schema.

C. Check the getobiectType [) value for ‘Custom’ or "Standard’ on the sObject describe result.

D. Use the getcustomobjects() method from the Schema class.

A.   Check the isCustom() value on the sObject describe result.

Explanation:

✅ Correct Answer: A. Check the isCustom() value on the sObject describe result
The correct approach for identifying custom objects in Salesforce is by using the isCustom() method on the results obtained from the sObject Describe API. This method is part of the DescribeSObjectResult class in the Apex Schema namespace and returns a Boolean value that tells whether a particular object is custom (true) or standard (false). When a developer writes an Apex method to support a Lightning Web Component (LWC) that displays a dropdown list of only custom objects, the Apex code would typically use the Schema.getGlobalDescribe() method to retrieve a map of all sObjects in the org.

Then, for each object, the developer would call describe() to get its metadata and invoke isCustom() to filter only those with a true result. This method is both reliable and native to Salesforce's metadata introspection tools, making it the most appropriate way to dynamically identify and return only custom objects. This enables the LWC to display only the relevant options without hardcoding any object names or relying on schema imports, which could become outdated or inflexible.

❌ Option B: Import the list of all custom objects from @salesforce/schema
This option is incorrect because importing objects using the @salesforce/schema directive in LWC is designed for statically referencing individual fields or objects, not dynamically listing them. In other words, @salesforce/schema requires that the object or field be explicitly named at design time, and it cannot be used to retrieve a complete or dynamic list of all custom objects.

Moreover, @salesforce/schema is a compile-time construct, which means it does not support the level of runtime introspection that is needed for a component meant to list all custom objects in a flexible and dynamic way. Using this approach would defeat the purpose of using Apex for dynamic metadata access, and it would require hardcoded imports for every potential custom object, which is both impractical and non-scalable in real-world Salesforce orgs.

❌ Option C: Check the getObjectType() value for 'Custom' or 'Standard' on the sObject describe result
This option is incorrect because the getObjectType() method in Salesforce Apex does not return a string indicating whether the object is "Custom" or "Standard." Instead, getObjectType() returns an instance of Schema.SObjectType, which refers to the type of the object but not its classification as custom or standard.

Therefore, there's no way to extract a direct textual label like "Custom" or "Standard" from getObjectType(). This makes the approach described in this option technically invalid for the purpose of distinguishing between custom and standard objects. The only correct and supported method to achieve this is isCustom(), which directly returns a boolean indicating the object type.

❌ Option D: Use the getCustomObjects() method from the Schema class
This option is incorrect because the Schema class in Apex does not have a method called getCustomObjects(). While the Schema namespace provides powerful reflection capabilities, such as getGlobalDescribe() and various describe calls on individual objects and fields, there is no method specifically designed to return only custom objects in one call.

Developers must retrieve all sObjects using Schema.getGlobalDescribe(), and then programmatically filter them using describe().isCustom() for each entry. The method described in this option simply does not exist, which makes it technically incorrect and misleading in a Salesforce Apex context.

Reference:
Apex Reference Guide
Apex Describe Information

Universal Containers (UC) has an ERP system that stores customer Information, When an Account is created in Salesforce, the ERP system's REST endpoint for creating new customers must automatically be called with the Account information. If the call to the ERP system falls, the Account should still be created. Accounts in the UC org are only created, one at a time, by users in the UC customer on-boarding department. What should a developer implement to make the call to the ERP system's REST endpoint?

A. REST call from JavaScript

B. Headless Quick Action

C. Call a Queueable from a Trigger

D. Apex Continuation

C.   Call a Queueable from a Trigger

Explanation:

✅ The most appropriate and reliable way to call an external REST API asynchronously from a trigger, without blocking the record creation, is to use a Queueable Apex class. Queueable Apex allows complex logic and callouts to run after the DML operation completes, meaning the Account will be created regardless of whether the call to the ERP system succeeds or fails. This fits the business requirement perfectly — "the Account should still be created" even if the integration call fails. Additionally, since Accounts are only created one at a time, the scale is low, so Queueable is ideal — it's simpler and cleaner than Batch Apex or Continuation.

❌ Why the other options are incorrect:

❌ A. REST call from JavaScript
Making REST calls from JavaScript (e.g., in a Lightning component or custom UI) would require user interaction and front-end context, which doesn’t align with the process — Accounts are created directly by users (likely via standard UI or API), not through custom components. Also, JavaScript calls don’t integrate well with Apex triggers or enforce secure server-side handling of sensitive data.

❌ B. Headless Quick Action
A headless Quick Action is designed to launch Lightning flows or Apex from the UI. But in this case, the requirement is for automatic integration when the Account is created — regardless of how it's created (UI, API, etc.). Quick Actions are manual and UI-bound, so they won’t cover all entry points and would not be reliable for automation.

❌ D. Apex Continuation
Apex Continuation is used to manage long-running callouts in Visualforce or Lightning components to prevent UI timeouts. But this scenario doesn’t involve user interfaces or long-running calls — it's a trigger-based, system-level integration. Continuation isn't supported in trigger context or background jobs, so it’s not a fit here.

🔗 References:
📘 Queueable Apex – Apex Developer Guide
📘 Asynchronous Apex – Salesforce Docs
📘 Callouts from Triggers – Best Practice

A developer created and tested a Visualforce page in their developer sandbox, but now receives reports that user encounter view state errors when using it in production. What should the developer ensure to correct these errors?

A. Ensure queries do net exceed governor limits,

B. Ensure properties are marked as private,

C. Ensure variables are marked as transient.

D. Ensure profiles have access to the Visualforce page.

C.   Ensure variables are marked as transient.

Explanation:

📌 Scenario Summary:
The Visualforce page worked in a developer sandbox but is causing view state errors in production.
This points to issues with too much data being stored in the view state, which exceeds Salesforce’s view state size limit (170 KB).

✅ Why Option C Is Correct:
"Ensure variables are marked as transient."
In Visualforce controllers, non-transient instance variables are automatically included in the view state, even if they are large or not needed after the initial page load.
By using the transient keyword, the developer can prevent temporary or large variables from being serialized into the view state.

💡 Example:
public class MyController {
public String name; // Stored in view state
transient public List accList; // NOT stored in view state
}

This reduces the view state size and prevents view state errors.

❌ Why the Other Options Are Incorrect:

A. Ensure queries do not exceed governor limits
Important for Apex performance, but unrelated to view state issues.
View state errors are about data size, not SOQL execution limits.

B. Ensure properties are marked as private
Private vs. public properties affect accessibility but not view state inclusion.
Even private properties can be included in view state if they are non-transient.

D. Ensure profiles have access to the Visualforce page
This would result in authorization errors, not view state errors.
Completely unrelated to the error described.

📚 Reference:
Salesforce Developer - Introducing Visualforce
Using Transient Keyword

Prep Smart, Pass Easy Your Success Starts Here!

Transform Your Test Prep with Realistic Salesforce-Platform-Developer-II Exam Questions That Build Confidence and Drive Success!

Frequently Asked Questions

The Salesforce Platform Developer II certification validates advanced knowledge in Apex, Lightning components, integration patterns, and deployment. It’s designed for developers with hands-on experience building scalable business applications on the Salesforce Platform.
  • Experienced Salesforce developers
  • Technical consultants and architects
  • Professionals aiming to showcase mastery in Apex, Visualforce, Lightning Web Components (LWC), and integrations
You must first hold the Salesforce Platform Developer I certification. Salesforce recommends 2–3 years of development experience on the platform before attempting PDII.
  • Questions: 60 multiple-choice/multiple-select
  • Time: 120 minutes
  • Passing Score: ~70%
  • Cost: USD $200 (plus taxes)
  • Delivery: Online proctored or Pearson VUE test center
  • Advanced Apex programming (asynchronous operations, exception handling)
  • Security & sharing model considerations
  • Integration techniques (REST, SOAP, external services)
  • Testing & debugging
  • Deployment & packaging best practices
Yes. Expect scenario-based questions that test your problem-solving and coding ability, including debugging, refactoring code, and recommending the best architectural approach.
  • Retake after 1 day for the first attempt
  • Retake after 14 days for further attempts
  • Maximum of 3 attempts per release cycle
  • Platform Developer I (PDI): Focuses on core Apex, SOQL, and declarative development.
  • Platform Developer II (PDII): Tests advanced coding, performance, architecture, and integration skills.
  • REST: Lightweight, modern, mobile/web integrations.
  • SOAP: Legacy or when strict contract/WSDL is required.
  • Platform Events: Real-time, event-driven architecture.
  • Change Data Capture (CDC): Sync Salesforce data with external systems automatically.
In the exam, pick the method that balances governor limits, scalability, and reliability.
  • Writing test classes with >75% coverage that assert actual outcomes.
  • Using dependency injection, stubs, and mocks for isolation.
  • Knowing when to use Unlocked Packages, Change Sets, or SFDX CLI.
  • In practice exams, review every “deployment” question twice — they’re often scenario-based and easy to misread.
  • Update LinkedIn and resume with “Salesforce Platform Developer II Certified” — highly valued by employers.
  • Join Salesforce Developer Community Groups to network.
  • Contribute to open-source Salesforce projects or blogs — recruiters notice active contributors.