Goal
Configure buttons to allow cancelling, saving and applying the "Register a Super Hero" service including introducing configuration components and the workflow engine used, amongst other things, to manage a service instance through its life cycle.
Starting code
Start tag: lesson/04
Requirements
We want the user to be able to cancel out of a "Register a Super Hero" service without saving changes. We should double check they didn’t accidentally click this button via a confirmation dialog before actually cancelling.
They should also be able to ‘save & exit’ so they can come back to their saved service later on and pick up where they left off.
We also need to be able to submit the service so it becomes active on the register using a "Submit" button. No fee payment or internal task review are required at this stage, but the page should refresh and have a title "Success" and the text "Your super hero is now registered and ready to save the world!" with the details you’d entered displayed as read-only values beneath it.
Steps
So far we’ve added a new business service and form and added some attributes to the form. But we still haven’t got any action buttons on the form, so you can’t save it or apply it or anything like that. So let’s go ahead and add those in now.
Buttons
First let’s handle the cancel option. New user actions are usually triggered by selecting a menu item or a button or hyperlink in the UI. In truth hyperlinks are still configured as a menu item or a button, just with a different UI treatment. And menu items usually come with some sort of hierarchical structure requirement, so since this button is a single button all by its lonesome, it will be configured using a button element.
Configuration Components
Configuration components are a way of providing non-trivial configuration grouped into a single logical unit or piece of functionality and made available for easy reuse.
But what action would you call when the cancel button is clicked and how do you configure the confirmation dialog? It still seems there will be a fair amount of configuration decisions and rules required. But fear not, because Verne predicted just such questions (it’s good like that ;)) and has answered your call in the form of a configuration component. Ta-da!
You’ll have to ensure the “component” namespace is defined in the opening root catcfg:Configuration element of the form, form fragment or component file you’re in if it isn’t already to unlock the power of component configuration tags
xmlns:component=”http://www.fostermoore.com/schema/catcfg-ng”
Adding a button element using a configuration component couldn’t be easier, just make sure there is a component namespace such as in the opening tag of the form, then go to the bottom of the form (but still inside the root record element) and type an opening tag character (<), then a "c" for components and press Ctrl+Space to see your available options.
Hopefully you noticed the component:ExitButton option. If not, take another look and select this option. Once selected you can use Ctrl+Space again to see what other options are available, or Ctrl+Space+Space to check out the related documentation as shown in Fig 4.1 below.

<component:ExitButton/>
As you can see from the documentation, this is a useful little button for "exiting" a service, providing options relevant to the state of the current service transaction. This means it appears as a "cancel" button for services in an editable state, such as our new "Register a Super Hero" one. Perfect! 🙂
Service Transaction Viewer
In Lesson 3 we used the service transaction viewer links to view the details of the current service transaction. This time we’re going to use the "Service Txns" (plural) link in the "[Dev]" menu to look at data relating to multiple service transactions. This is particularly useful if you’re no longer on the service transaction you want to see the details for.
The “[Dev] – Service Txns” menu item can be used for querying service transactions, which is particularly useful if you’re no longer have the service transaction you’re interested in currently loaded or want to inspect a number of service transactions.
Right-click the "[Dev] – Service Txns" menu item and select to open it in a new tab. Once done you should see something similar to Fig 4.2 below.

Use this viewer to see the result of your cancelling the "Register a Super Hero" services. Make sure you’re looking at the heroes application (by ensuring "/heroes" is in the URL) then select "heroes" from the drop-down which is the first on the left highlighted in Fig 4.2, and select "Any Status" from the status drop-down next to it.
Then click the "Search" button. The "heroRegister" service you just cancelled should be listed at the top and you can select the "Json" or "Xml" link in that first entry to see its data. Now you’re relatively familiar with service transaction data you should be able to confirm it is in fact the correct service transaction, and notice how it has a ghost property value of "true" and a ghostReason property value of "discarded" (in the JSON version). Rest assured that means it has been cancelled – a logical removal from the system.
Save and Exit Button
Next we want to provide a ‘save & exit‘ button so you can save your registration and come back later. Just like with the cancel button above, a configuration component makes this a trivial exercise. See if you can find the relevant component yourself by starting to add a new component tag above the component:ExitButton one and the Ctrl+Space shortcut. You guessed it, the SaveAndExitButton one looks remarkably like what we’re after 🙂 So go ahead and add that one in and start a new service in the application to see what it looks like.
Allowing drafts
Hmm, why didn’t the save & exit button appear? It’s actually because the component has some built in smarts so even if it’s included in a form it only appears if the underlying business service has been configured to allow save & exit i.e. allows drafts to be saved. As outlined in the business service documentation we can do this in one of two ways. Explicitly via the allowDraft attribute, or implicitly via the startDueDays attribute. We’ll go for the most straight forward option of adding allowDraft="true" to the heroRegister business service. Once done, start a new service in the application again and you should now see the shiny new save & exit button. Ahhh, lovely ?
Dashboard Items
Now that we have a "Save and Exit" button, give your super hero a name the click it. You’ll exit the service as you’d expect (the "exit" part) and end up back on your dashboard in the master application (you can tell it’s the master application because of the presence of "/master" in the URL).
Use the “Service Txns” viewer again to check the service transaction you selected save & exit on. You’ll see the data looks OK, a “pending” status property and not a “ghost” in sight like with the cancelled ones 🙂 You’ll also notice a committedDate property showing the date you selected to save it via the save & exit action.
But you’d be forgiven for expecting to see some sign of your saved service there, but it isn’t… why is that? It comes back to the root domain we looked at in Lesson 3. The dashboard only looks for service transactions with certain root domains when querying for items to show.
There’s a property called "dashboard.external.dashboard.domains" that says what these root domains should be. Because the dashboard is in the master application, you’ll want to add this property to the master, so right-click the "master" directory and select Create Resource, and select the "Additional Config" Type and use the "dashboard.external.dashboard.domains" value as the Unique Key as per Fig 4.3 below.

Then for the value child (<value>Hero</value>), which expects a CSV, just give it the value of our root domain, which of course you know because you’ve been paying close attention 😉 No? We’ll give you a hint… it’s "Hero".
Once done, reload the dashboard by clicking the "Dashboard" menu link again and you should see your saved super hero registration in all its glory, similar to that in Fig 4.4 below.

Now that you have both a ‘cancel’ and a ‘save & exit’ button as well as saved ones showing up on the dashboard, try some combinations of saves and cancels.
In particular set some field values and ‘save & exit’, then load the saved service back in, make some more field changes then ‘cancel’ – notice how your service is still saved on the dashboard but still as it was when you first saved it? Magic stuff.
For super, extra bonus credit use the "Service Txns" viewer mentioned above to see what happens to the service transactions (yes, plural) relating to your "Register a Super Hero" service when you do the above (save & exit, start, cancel, etc.). See the life cycle documentation for more details about what to look out for in the data, how the service transactions are connected and why.
Submit Button
Now we have just the one button requirement left – the ability to submit the "Register a Super Hero" service. The process is almost identical to the ‘exit’ & ‘save & exit’ buttons, but this time we’ll use the "SubmitButton" component (extra points if you already spotted that one when adding the other buttons :)).
Go ahead and add that one on your own before comparing with the (very simple) full buttons configuration shown below. Make sure you remember to refresh the application to see the changes take affect.
<component:SubmitButton/>
<component:SaveAndExitButton/>
<component:ExitButton/>
We’ve made some solid progress now – in fact the form is looking great, meeting all of our requirements for this lesson. The only thing left now is to ensure something actually happens when we click the "Submit" button to apply the service.
The Workflow Engine
So click the "Submit" button and see what happens. Warning: you’re likely to be a bit disappointed. That’s because by design the submit button simply fires validation for the entire form, then – if no validation errors stop things in their tracks – it hands off to the Workflow Engine to handle the rest.
And we don’t have any workflow configuration associated to this service. The fact that this step is required comes down to the fact that our service uses a root domain not previously in the application. So we need to associate the "Hero" root domain to a workflow, which we’ll do via the data set configuration we added during Lesson 3.
As mentioned above the submit fires validation for the entire form. You will have seen each field is validated as it’s entered, but if you miss a field entirely it’s not validated by this action, so Verne ensures validation is triggered against the current form data before moving on – be that the entire form on submit, or a portion of the form like the contents of a single tab when moving to the next tab.
See this in action by submitting a "Register a Super Hero" form that you know is incomplete yet not showing errors yet.
Open up your heroes.xml data set file (use Ctrl+n to search file names if you want to) and add a workflow child element to your "heroes" dataset element. Do that using the Ctrl+space option within the dataset element’s body.
If you then press Ctrl+space when in the empty value for the templateName attribute in the workflow element you should see two options – select the "submitServiceTransaction" one. Also be sure to specify "serviceTransaction" for the workflowType attribute. This should give you a data set configuration like that shown below.
<dataset code="heroes" rootDomainName="Hero" relatedEntity="true">
<collection name="heroes"/>
<workflow workflowType="serviceTransaction" templateName="submitServiceTransaction"/>
</dataset>
OK, now we’re ready to apply! Try it again and see if the results are a little more promising. Use the "Service Txns" viewer mentioned earlier in this lesson to view the service transaction you just submitted and check it now has a status property of "activated" (see Fig 4.5 below) – that will confirm it all went as expected. You’ll also note there’s now a workflowInstanceId property value as well, indicating the workflow configuration was picked up and associated to the service.

And the application reflects this by the service now appearing in the "Past Activity" tab as "Completed" on the dashboard instead of the "Things in Progress" tab as before, as per Fig 4.6 below.

Setting the business name
There are some key properties on the service transaction that all services should have, whose presence are relied on by various system processes and functions. Most service transaction properties are set using sensible default logic, but one that can’t really be determined without guidance is the businessName.
In short, the business name is the public facing name of the registry data – in our case the super hero. As you might suspect, this can be set quite differently depending on the type of "thing" being registered. In our case of a super hero however it’s pretty straight forward and makes sense that this should simply be the super hero’s name. So we’ll go ahead and add the configuration to copy the value of the Name attribute into our service transaction businessName property, and we’ll do this with the help of another platform tag – this time the aptly named set-business-name tag. Since this is a registration and there’s no existing business name for this data, we can have the business name to reflect whatever the current name is so we’ll use the "change" rule scope. So add the following line as a child element to the Name attribute on your form, right under the attribute length validation tag.
<platform:set-business-name scope="change"/>
And that’s it! Check the service transaction data and ensure the "businessName" property is now set as you update the super hero name.
Submit confirmation screen
The final piece of the puzzle for this lesson is the presence of a confirmation screen once the user successfully submits their super hero registration form. And then we’re done. This is also relatively straight forward to do. This time the configuration will go in the business service and in the form of a…. drum roll please… service-confirmation platform tag. Have a read of the documentation to figure out what values you might need to add.
To be honest there are a few ways to go about it. We could use an entirely different service, or use an auto-generated business-service but re-using our registration form, or using a separate form. Since the content is mainly the same as the registration form itself (except read-only) it makes sense to re-use the "heroRegister" form, so we’ll do that. Then we just need to ensure we have the extra "Your super hero is now registered and ready to save the world! " text at the top and the title to read "Success". Below is the service-confirmation element we’ll add to the "heroRegister" business service and we’ll leave it as an exercise to the reader to compare this configuration with the service-confirmation documentation to understand what does what.
<platform:service-confirmation form-item="heroRegister"><textKey type="title" key="heroRegister.service.confirmation.title"/></platform:service-confirmation>
To get the text at the top of the form we’ll add the following text element to the "heroRegister" form above the attributes.
<text shortCode="message" visible="false"><platform:set-property visible="true" when-service-mode="View"/><textValue type="label" text="Your super hero is now registered and ready to save the world!"/></text>
The configuration introduces a few things all at once, but now we’re getting a bit more famililar with the configuration it’ll hopefully not be too overwhelming. Feel free to browse the documentation in your own time, but briefly it’s single a text element which is used for standalone non-editable text. The visible attribute is used to mark the related view node as invisible by default when built, then there’s another platform tag – this time a set-property one to set the view node visible only for business service’s that have a "View" mode, which is the mode that’s always used for auto-generated confirmation services. It also has a textValue element which as you can see allows you to add the textual value inline, without the need for a localised text key entry. Not requiring separate text value configuration simplifies things but obviously doesn’t allow multilingual support so is not the official best practise. Ultimately it is a project decision though, so introduced here just to raise awareness of it as an option.
That should give you a submit confirmation something like the one in Fig 4.7 below once you submit your super hero registration. Notice the Year of Arrival on Earth value is "2,021" instead of "2021" as you’d expect? Don’t worry, we’ll get to that in the next lesson ?

And look at that, another lesson has come to an end. Sigh.
Add tests
Create new scenarios to cover error conditions, save and scenarios and other functionality. In this lessons we are going to discover
- How to test error conditions and validate error messages
- Use Invalid config
- Validate Save and Exit
- Submit the form
The lesson related can be found at test Lesson 3 Error Conditions, Submit, Save and exit , Cancel a form
Recap
Whilst this lesson has been very light on actual configuration (less than 15 lines) we’ve taken the initial "Register a Super Hero" form and made it a fully functional service that can be cancelled, saved, restarted and applied. Pretty impressive really. Here’s a summary of the configuration, concepts and tools we covered:
- Configuration components and their ability to provide non-trivial configuration in a trivial way
- Added the exit, save & exit and submit buttons, and functionality that comes with them using their respective components
- How to enable saving draft service instances
- Full form validation applied when submitting a service
- The “Service Txns” viewer developer tool to query and inspect service transactions within an application
- Highlighted certain service transaction properties relating to a service in various stages of its life cycle
- Dashboard and the related “dashboard.external.dashboard.domains” property for new root domains
- The Workflow Engine and configuring a standard workflow against a root domain via the data set
- The service transaction businessName property and how to set it
- Adding a confirmation screen to display when a service is successfully submitted
- The text and textValue elements for standalone, non-editable text and assigning text with inline textual values respectively
- set-property platform tag for controlling the properties of resulting view nodes for varying conditions

