How to create an Apex class using the Tooling API from within a Salesforce LWC and Apex

To create an Apex class using the Tooling API from within a Salesforce Lightning Web Component (LWC) and Apex, you need to make an HTTP callout to the Tooling API. This involves several steps, including setting up the necessary permissions, handling authentication, and constructing the API request.

Step 1: Set Up Permissions

Ensure your Salesforce user account has the appropriate permissions to use the Tooling API and to create Apex classes. You may need to enable API access and assign permissions to create and manage Apex code.

Step 2: Create Named Credential

Since the Tooling API requires authentication, you should set up a Named Credential in Salesforce to manage the authentication process securely. This will store the endpoint and handle the authentication tokens needed for API requests.

  • Go to SetupSecurityNamed Credentials.
  • Create a new Named Credential with the URL of your Salesforce instance’s Tooling API endpoint (usually https://<your-instance>.salesforce.com/services/data/vXX.0/tooling/ where XX is the API version).
  • Set the Identity Type to “Named Principal” and Authentication Protocol to “OAuth 2.0”.
  • Use “OAuth 2.0” settings appropriate for your organization.

Step 3: Apex Code to Use Tooling API

Write an Apex class that uses this Named Credential to make HTTP callouts to the Tooling API.

public with sharing class ApexCreator {
    @AuraEnabled
    public static String createApexClass(String className, String classBody) {
        HttpRequest req = new HttpRequest();
        req.setEndpoint('callout:MyNamedCredential/services/data/vXX.0/tooling/sobjects/ApexClass');
        req.setMethod('POST');
        req.setHeader('Content-Type', 'application/json');

        // Create the JSON body with the Apex class details
        Map<String, String> body = new Map<String, String>{
            'Name' => className,
            'Body' => classBody
        };
        req.setBody(JSON.serialize(body));

        Http http = new Http();
        HttpResponse res = http.send(req);
        if (res.getStatusCode() == 201) {
            return 'Apex class created successfully.';
        } else {
            return 'Error: ' + res.getBody();
        }
    }
}

Step 4: Call Apex from LWC

In your LWC, create a method to call the Apex method, passing the class name and body as parameters.

import { LightningElement, api } from 'lwc';
import createApexClass from '@salesforce/apex/ApexCreator.createApexClass';

export default class ApexClassCreator extends LightningElement {
    @api className;
    @api classBody;

    createClass() {
        createApexClass({ className: this.className, classBody: this.classBody })
            .then(result => {
                console.log(result);
            })
            .catch(error => {
                console.error(error);
            });
    }
}

HTML for LWC

Add a simple form in your LWC’s HTML to input the class name and body, and a button to trigger the class creation.

<template>
    <lightning-input label="Class Name" value={className} onchange={handleInputChange} data-id="className"></lightning-input>
    <lightning-textarea label="Class Body" value={classBody} onchange={handleInputChange} data-id="classBody"></lightning-textarea>
    <lightning-button label="Create Class" onclick={createClass}></lightning-button>
</template>

JavaScript Handling Input

Handle the input changes in your LWC JavaScript.

handleInputChange(event) {
    const field = event.target.dataset.id;
    if (field === 'className') {
        this.className = event.target.value;
    } else if (field === 'classBody') {
        this.classBody = event.target.value;
    }
}

Security and Monitoring

Remember to monitor the usage of this functionality, as dynamically creating Apex classes can lead to security issues and potentially harmful code being injected and executed within your Salesforce environment. Always validate the inputs and consider adding logs and checks to monitor the creation of Apex classes.

This setup allows your LWC to interact with Salesforce’s Tooling API to dynamically create Apex classes based on user input or other runtime conditions.

Published by Sandeep Kumar

He is a Salesforce Certified Application Architect having 11+ years of experience in Salesforce.

Leave a Reply