- [Chris] Hi everyone, my name's Chris Peterson
Director of Product Management here at Salesforce for Apex,
and today I'd like to talk to you
about Apex Invocable Actions.
If you're not familiar with the Invocable Action framework,
all you need to take advantage of it
is an Apex class that contains a static method
annotated with Invocable Method.
As part of the sanitation,
you're required to specify some additional parameters
like a label for showing indeclarative tooling,
a description, and, optionally, a category.
Once you've done that,
your Apex Action is automatically exposed
in the Flow and Process Builder.
This is wonderful because it means
that you can augment the power of declarative tools
with Apex code fairly seamlessly,
and on top of that, you also get a free REST API
created by the actions framework for doing this.
So if you ever built an Apex REST service
and then a separate Apex service
and then tried to build something that bridges that
into declarative tools, you've probably ended up
with a large volume of code specifically trying
to handle the unique aspects of each of those entry points.
With the Invocable framework, you don't need to do that.
Really, you get one action that can be interacted with
across all of Salesforce platform features.
So what I'd really like you to take away
from the session today is that you should design
with Invocable Actions in mind
especially if you're starting a greenfield project.
They may not always be the perfect fit for your use case,
but you should absolutely consider them,
and consider them as the default option
unless you have a reason not to.
Let's take a look.
Here, you'll see an Apex Class that I've written already
called SanitizeUpdate.
You see our InvocableMethod annotation on here
on a static method.
You see our label that it's the SObject Update Sanitizer.
We have to write in a description, as well as a category,
and then we have our static method,
which takes a list of SObjects as input
and returns a list of SObjects as output.
The real core of this method
is calling the security strip an accessible method in Apex,
which, being fairly new, if you're not familiar with it,
takes list of SObjects as the input
and returns a stripped down clone of those
that has had field and object level security
automatically enforced.
So if you pass doing something like a list of cases
that were generated in the system mode feature
that contained fields the running user
didn't have access to,
stripInaccessible would handle that for you.
It would then return a stripped down version
of those cases that only has the information
the user should be able to,
in the case of this action, update.
So that's exactly what this does,
and, really, we're looking at one, two lines of logic
beyond the boiler plate here and some additional logging
we've added for debugability.
So let's see how useful two Apex statements are
in the context of Flow,
how much value they can actually bring to the table.
As we jump over to our Flow Builder,
you'll see the name of our Flow, Self Close Case,
gives you a hint at what we're doing today.
Our business problem is that we'd like to allow
End Users through our communities to close their own cases.
We don't want them to be able to update the status
in any other way.
We don't want them to be able
to set the status to escalated.
We don't want them to be able to close somebody else's case.
We only want it to be their own case
and only if a custom field can self-close is sent to True,
and you notice one interesting thing about this Flow
if I dive in to the Flow properties,
which is that much like Apex code,
this is running in system context
specifically with sharing enforced.
So this Flow, using some fairly new features
that have been added in the last couple releases,
runs in the same type of security model
as an Apex class that's defined with sharing,
which means it can do things that the End User can't,
and that's what we would like
to take advantage of here today.
So the very first thing we do is we fetch our case.
If you're not familiar with this in Flow,
the context record is always passed
in as the special record ID variable.
So the first thing we do is run a soft-field query on Case
to find our case.
We then check that field, allow self-closure,
and if the answer is no, redirect the user to an Air Screen.
If the answer's yes, then we invoke our new Apex action,
and this does something interesting,
which is if the user doesn't have access
to edit cases at all or specifically update cases
because we passed in update in our action,
it'll generate a fault,
so you'll see this fault connector pointing back
to our No Access Screen.
So this is doing a material amount of security enforcement,
so we know that the only thing that's gonna be updated
on this case when we get over to this Update Records call
is what the user can do in user mode.
So we're really enforcing all of the best practices
of the Salesforce security model
through this one action that really breaks down
to two Apex statements, glorious.
So let's continue the rest of our Flow
and then see it in action real quick.
We see our assignment,
that the case status is set to closed,
the running user couldn't do that,
but we're in system mode, so that's fine,
show the user a screen letting them know
the case has been closed
and asking them for a final comment,
and then we create that comment.
Simple, elegant, wonderful.
So let's run through it in Flow Debugger.
Here I've created a case where I've lost my phone,
I'm going to copy the record ID,
go over back to the Flow Builder, and debug it.
So here we are in the Flow Debugger,
manually specified my record ID,
which I wouldn't have to do normally,
but in the debugger, I do,
and, in just a second, we'll see that because I have access
to update cases, my case is now closed.
We passed all those access checks.
All done.
So we hop back over to our case,
look at that, our case is closed
and our case comment got posted.
Well, we learned that system mode is wonderful
for letting you do things
that the user couldn't normally do,
but you have to be really careful with that extra power.
We were reminded of things
that Apex developers should already know,
which is that with great power comes great responsibility,
and we showed you a new technique for really quite easily
making sure that you add that responsibility
into your flows when they run in system mode.
So no matter whether you come from a background
of declarative or programmatic,
what we'd really like you to remember
is mixing the two gives you something
so much greater than the sum of its parts.