In the “Leveraging Salesforce Using Spring Boot” article, I navigated the course for introducing a Spring Boot service that would leverage the well-established Salesforce RESTful API. The goal of this service is to act as a middleware layer to allow clients not written in Salesforce to retrieve and update contact data stored in Salesforce. This backend service implemented its own caching layer to provide a faster response time and also cut down on the number of times Salesforce needed to be called.
In this article, I will introduce a client application using the Svelte framework to interact with the Spring Boot service.
Why Svelte?
When I planned this series, I knew I was going to utilize Spring Boot as the middleware tier in my design. I also knew that I wanted to provide sample client applications using Angular, React, and Vue.js, because they represent the majority of JavaScript-based clients currently in use.
At the same time, I wanted to push myself and use a JavaScript-based framework that was 100% new to me. In fact, I wanted to use one that I had never even heard of before. This wasn’t that huge of a task, since I am primarily a service-tier developer.
I reached out to my good friend, Michael Bogan, who pitched the idea of using Svelte. Of course, I said “yes” to the idea before I even did a “svelte” Google search.
As soon as I performed that “svelte” search in Google, I was excited to try a JavaScript framework that provides the following advantages:
Svelte builds upon the API of the internet. It doesn’t introduce anything new (like JSX) and is designed to run with basic JavaScript, CSS, and HTML. Because of this, most developers are ready to start building applications in a few minutes and are comfortable after only an hour.
Svelte is extremely fast (proven to outperform Angular, React, and Vue.js) and production-ready. Current users of the framework include GoDaddy, IBM, Square, and The New York Times.
There are zero (yes, zero) client dependencies.
If you would like to read more, check out this wonderful article by Robert Hall.
An Example Use Case
Consider the following use case, which will be the basis for business logic we need to accomplish in Svelte:
The Business Call Center is about to launch a major marketing campaign. However, they recently discovered that the title noted for the list of contacts was incorrect approximately 90% of the time. This appears to be the result of a system conversion.
A group of interns has been tasked with making title updates to contact information stored in Salesforce. Internally, an architectural decision was made to introduce a small application using the Svelte framework—which is a newly adopted standard.
The Svelte client application will provide the following functionality:
- Retrieve a list of all contacts in Salesforce.
- Allow the title column to be edited inline (no form or modal should be introduced).
- Upon accepting the title change, the updates will be persisted into the Salesforce domain.
The expectation is that the Spring Boot RESTful API from the “Leveraging Salesforce Without Using Salesforce” article will be utilized, which has simplified the Contact object as shown below:
public class Contact {
private String id;
private String name;
private String title;
private String department;
private SalesforceAttributes attributes;
}
public class SalesforceAttributes {
private String type;
private String url;
}
If you want to see the Spring Boot service, you can access the Spring Boot Service source code here:
https://gitlab.com/johnjvester/salesforce-integration-service
Getting Svelte Up and Running
Getting a new client created and running in Svelte is quite simple. In fact, the following terminal commands were executed on my MacBook Pro to create a new instance called “salesforce-integration-svelte”:
npx degit sveltejs/template salesforce-integration-svelte
cd salesforce-integration-svelte
npm install
npm run dev
These commands resulted in the following output:
╭─john.vester@john ~/projects/salesforce-integration-svelte
╰─$ npm run dev
> svelte-app@1.0.0 dev /projects/salesforce-integration-svelte
> rollup -c -w
rollup v2.52.7
bundles src/main.js → public/build/bundle.js...
LiveReload enabled on port 35730
created public/build/bundle.js in 466ms
[2021-07-04 17:09:15] waiting for changes...
> svelte-app@1.0.0 start /projects/salesforce-integration-svelte
> sirv public --no-clear "--dev"
Your application is ready~!
- Local: http://localhost:5000
- Network: Add `--host` to expose
────────────────── LOGS ──────────────────
Navigating my browser to localhost:5000 presented the “hello world” message:
Adding Some Dependencies
As a next step, I wanted to see if it was possible to leverage Bootstrap for my new application. After all, I am not the best at UI/UX and feel like Bootstrap provides something quick and easy to use which doesn’t look like Web 1.0.
Within a few minutes, I located the sveltestrap dependency, then added it to my project using the following command:
npm install --save svelte sveltestrap
Next, I simply added the following <link>
in the public/index.html
file:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css">
Now, Bootstrap classes can be used in my new Svelte application.
Next, I randomly picked the svelte-inline-edit inline editor out of a list of Google search results. I have no idea if this is the best one to use, but it appeared to meet my basic needs. I added my second custom dependency using the following command:
npm install svelte-inline-edit --save-dev
At this point, I was ready to focus on handling the Contacts object that lives in Salesforce.
Creating the Contacts Component
The remainder of my work centered around a single file in the project’s /src folder, called Contacts.svelte. Having everything in a single file is often viewed as another benefit to adopting the Svelte framework.
Adding the View
Knowing the payload of the Contact object, I added the following view logic in the Contacts.svelte file:
{#if contacts}
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">Name</th>
<th scope="col">Department</th>
<th scope="col">Title</th>
</tr>
</thead>
<tbody>
{#each contacts as contact }
<tr>
<td>{contact.Name}</td>
<td>{contact.Department ? contact.Department : "(not set)"}</td>
<td><InlineInput length="2" bind:value={contact.Title} on:save={patchContact(contact)} ></InlineInput></td>
</tr>
{/each}
</tbody>
</table>
{:else}
<p class="loading">loading ...</p>
{/if}
There is really nothing high-tech here, but there is a special rule to show “(not set)” when the contact’s department is null. Additionally, we add the InlineInput tag to ensure the title column updates directly from the view.
Adding the Service
I created the service side of the component next:
<script>
import { onMount } from "svelte";
import InlineInput from 'svelte-inline-edit';
export let contacts;
onMount(async () => {
await fetch(`http://localhost:9999/contacts`)
.then(r => r.json())
.then(data => {
contacts = data;
});
});
async function patchContact(contact) {
console.log('contact', contact);
const headers = {
"Content-type": "application/json"
}
const res = await fetch('http://localhost:9999/contacts/' + contact.id, {
method: 'PATCH',
body: JSON.stringify({
"Title": contact.Title
}),
headers: headers
})
const json = await res.json()
console.log(JSON.stringify(json));
}
</script>
The onMount()
event loads the data via a GET call to the RESTful service and the patchContact()
function performs the PATCH call to the RESTful service.
Final Steps
With the Contact component ready, I needed to update the App.svelte
file to include the Contacts component and get rid of the “hello world” sample code.
<svelte:head>
<title>`salesforce-integration-svelte` App</title>
</svelte:head>
<h1>Contact List (from Salesforce)</h1>
<main>
<Contacts {contacts} ></Contacts>
</main>
Finally, I cleaned up the main.js
file to remove the last of the “hello world” code:
import App from './App.svelte';
const app = new App({
target: document.body,
props: { }
});
export default app;
Using the Svelte Client
With the changes in place, I executed the npm run dev
command again. After making sure the Spring Boot RESTful service was running and connected to Salesforce, navigating to localhost:5000
presented the following information:
Single-clicking on the Title for Sean Forbes (second row) places the cell into edit mode:
The title for Sean Forbes was updated from “CFO” to “CEO”:
When I click the checkmark, the client sends the new value in a PATCH request to the Spring Boot RESTful service, which is then passed on to Salesforce. Reloading the page displays the updated information:
As a result, we're able to meet the business needs and update Salesforce data without actually using a Salesforce client to do so.
Conclusion
Starting in 2021, I have been trying to live the following mission statement, which I feel can apply to any IT professional:
“Focus your time on delivering features/functionality which extends the value of your intellectual property. Leverage frameworks, products, and services for everything else.”
- J. Vester
In this example, I used Svelte for the very first time. In fact, within a short period of time (less than two hours for me), I went from an empty folder to a functional application that reads and updates contact information in Salesforce … without actually using a Salesforce client.
Of course, a production-ready scenario would require some additional work to prepare this application for “prime time” use. However, the Svelte framework certainly allowed me to focus my time on meeting the business needs stated in the example use case.
If you are interested in the source code used for the Svelte client, simply navigate to the following repository on GitLab:
https://gitlab.com/johnjvester/salesforce-integration-svelte
Future articles are also planned for the following other JavaScript-based clients:
- Vue.js
- React (React Native)
- Angular
- Lightning Web Components (outside the Salesforce ecosystem)
Have a really great day!