Apex FFLib Generator
Generate FFLIB-pattern Domain, Selector, and Service classes from any Salesforce Apex trigger handler — directly from VS Code.
Works with any Salesforce project. No org-specific dependencies, no hardcoded prefixes. Fully configurable for your team's naming conventions and architecture.
Features
- Batch Mode — scans your entire triggers folder and generates all three FFLIB layers at once
- Single Object Mode — target one Salesforce object by name
- Controller Migration Mode — full migration with CSV reports
- Folder Picker UI — browse for folders instead of typing paths
- Configurable class prefix — e.g.
ACME_ → ACME_ContactsDomain, or leave blank for no prefix
- Configurable base classes — default
fflib_SObjectDomain / fflib_SObjectSelector, override for any framework
- Configurable trigger dispatch — use any dispatch pattern via
{domainClass} and {objectName} tokens
- Modification log injection — auto-inserts your name, company, and date into every generated file header
- Output Channel logging — see full generator output inside VS Code
Requirements
- Java 8 or higher must be installed and available in your system
PATH
- A Salesforce project with existing trigger handler classes
Setup
Run the command:
Ctrl+Shift+P → FFLIB: Configure Folder Paths
The wizard walks you through selecting:
| Step |
What to set |
| Triggers Folder |
Path to your .trigger files |
| Classes Folder |
Path to your handler .cls files |
| Output Folder |
Where generated files land |
| Backup Folder |
Where originals are backed up |
| Your Name |
Appears in modification log header |
| Company Name |
Optional — appended to your name |
| Class Prefix |
e.g. ACME_ or leave blank |
| API Version |
Salesforce API version (default 59.0) |
Step 2 — Run the generator
Ctrl+Shift+P → FFLIB: Run Apex Generator
Pick your mode and the generator does the rest.
Generated Files
For each object (e.g. Contact), the generator produces:
| File |
Description |
ContactsDomain.cls |
FFLIB Domain class with virtual override trigger event methods |
ContactsDomain.cls-meta.xml |
Metadata XML |
ContactsSelector.cls |
FFLIB Selector class with SOQL query methods |
ContactsSelector.cls-meta.xml |
Metadata XML |
ContactsService.cls |
FFLIB Service class with business logic |
ContactsService.cls-meta.xml |
Metadata XML |
conversion_report_*.csv |
Full conversion report |
If you set a class prefix (e.g. ACME_), files will be named ACME_ContactsDomain.cls etc.
Commands
| Command |
Description |
FFLIB: Run Apex Generator |
Open mode picker and run the generator |
FFLIB: Configure Folder Paths |
Step-by-step folder setup wizard |
FFLIB: Open Generator Settings |
Jump to all extension settings |
Advanced Configuration
Open Settings (Ctrl+,) and search apexFFlibGenerator to configure:
| Setting |
Default |
Description |
classPrefix |
(blank) |
Prefix for generated class names |
domainBaseClass |
fflib_SObjectDomain |
Base class for Domain classes |
selectorBaseClass |
fflib_SObjectSelector |
Base class for Selector classes |
triggerHandlerInterface |
(blank) |
Interface handler classes implement |
triggerDispatchPattern |
fflib_SObjectDomain.triggerHandler({domainClass}.class); |
Line written into trigger files |
apiVersion |
59.0 |
Salesforce API version in metadata XML |
Example configs
No prefix (clean):
classPrefix =
→ Produces ContactsDomain, ContactsSelector, ContactsService
Custom prefix:
classPrefix = ACME_
→ Produces ACME_ContactsDomain, ACME_ContactsSelector, ACME_ContactsService
Custom trigger dispatch:
triggerDispatchPattern = MyApp.TriggerDispatcher.run({domainClass}.class, '{objectName}');
Generated Domain Class Example
/*
* Name : ContactsDomain
* Date : 03/31/2026
* Description : Auto-generated from trigger handler
*
* Modification History:
* Date: Developer/Company Description
* ---------------------------------------------------------- *
* 03/31/2026 Jane Smith Auto-generated from trigger handler
*/
public with sharing class ContactsDomain extends fflib_SObjectDomain {
public class Constructor implements fflib_SObjectDomain.IConstructable {
public fflib_SObjectDomain construct(List<SObject> sObjectList) {
return new ContactsDomain(sObjectList);
}
}
public ContactsDomain(List<Contact> records) { super(records); }
public virtual override void onBeforeInsert() {
// copied logic from handler
}
public virtual override void onAfterInsert() {
// copied logic from handler
}
public virtual override void onBeforeUpdate(Map<Id, SObject> existingRecords) {
// copied logic from handler
}
public virtual override void onAfterUpdate(Map<Id, SObject> existingRecords) {
// copied logic from handler
}
public virtual override void onBeforeDelete() { }
public virtual override void onAfterDelete() { }
public virtual override void onAfterUndelete() { }
}
Known Limitations
- Java must be on
PATH — the extension calls java -jar internally
- Aggregate SOQL inside trigger handlers is not fully parsed (manual review recommended)
- The
.jar file is bundled with the extension — no separate install needed
Release Notes
1.1.0
- Fully generic — no org-specific dependencies
- Configurable class prefix, base classes, trigger dispatch pattern
- Folder picker UI — browse for folders instead of typing paths
- Modification log injection with configurable name and company
- All 3 modes: Batch, Single Object, Controller Migration
- Domain methods generated as
virtual override (test-class compatible)
- Constructor generates
super(records) call
1.0.0
License
MIT