A service form is an inflated form for a specific business service configuration. It is for that business service configuration and only that business service configuration.
Put another way, a service form is a runtime object containing the details of the form structure that applies to a specific business service configuration and its related form configuration. In other words, service forms manage the form configuration that can be applied to any service instance of a specific business service configuration.
It’s worth highlighting that whilst Verne uses service forms at runtime, they are analogous to static configuration in that they are used as the constant structure on which instances of a business service are based. You can’t update a service form for only one service instance of a business service.
If a service form relating to a business service was changed (say by the underlying XML configuration changing) then all service instances based on that business service configuration would be impacted by the change. This is why it is important that a service form has a one-to-one mapping to a business service configuration, so any customisations that are applied to the service form are always applicable – this wouldn’t always be the case if service forms served more than one master (i.e. could relate more than one business service configuration).
Service forms are a powerful concept in Verne, as they provide a way to customise business service form configuration, and in an optimised way.
Importantly, service forms are used to build the service transaction view tree so it’s the service form XML which is the best representation of the configuration on which the view tree is built, not the form configuration.
Note: Whilst service forms are used at runtime in a Verne application, service forms are resolved by Cheetah, so they don’t need a runtime application to be generated, allowing them be referenced and used in non-runtime tools such as Magellan.
Building a service form from static XML
Form configuration starts as static XML in module and/or application increments. When an application is started Cheetah parses these static resources and creates runtime objects to reflect the static configuration. When something occurs that requires a service form (i.e. initialising a service transaction domain tree or building the view tree) Verne retrieves the service form relating to the specific business service code from a cache, or builds one if it doesn’t already exist. The process of building a service form is outlined below:
- Retrieve the business service object relating to the business service configuration XML using the business service code
- Retrieve the form object relating to the form configuration XML using the form code from the business service’s form item value
- Build the service form object based on the form configuration XML (along with any form fragments, components, etc. that are included/referenced) and adds the business service details. See the service form XML section below for more details
- Apply any custom modifications relating to this business service. See the customised forms section below for more details
The result of this is a service form which, again, is a runtime instance of the resolved form configuration for a specific business service configuration including any customisations that apply. In this way service forms provide quick (cached) access to details relating to a business service’s form configuration.
At this point it’s worth noting that whilst used by Verne at runtime, service forms reflect static configuration. See the service form XML section below for more details.
Shared configuration
The same form configuration can be referenced by more than one business service configuration. But even if there is a one-to-one mapping of business services to forms, forms usually include components, which can also be shared across multiple forms. This means there’s usually a high chance there is at least some XML configuration somewhere within a form that is shared across multiple business services.
Configuration reuse vs. complexity
Common components are usually defined (from a business perspective) and are implemented via configuration components or form fragments and re-used in multiple places. When business components have slightly different rules depending on certain conditions, what invariably happens is you either:
- keep to a few components or form fragments but add complexity in terms of rules and/or parameters to them to support the variations (added complexity)
- inflate the number of components or form fragments by configuring separate, slightly different ones for each of the variations (added volume)
- injecting configuration into the components or form fragments to support the variations (potentially less visible, although tools such as Magellan can help with this)
Each of the approaches has their merits and pitfalls – at the end of the day registers have complex requirements that need to be considered so there is no silver bullet and it’s up to the project team to decide when to favour one approach over another.
Neither option – fewer forms and/or components that have rules to support multiple use cases, or more forms and/or components to be used for a specific use case – is in itself a pitfall, it’s more about whether one method is used across the board blindly or not.
Also consider ongoing maintenance when considering which option works. For example, whilst component A and component B may appear to have more in common than not in the first instance, indicating perhaps using the same component for both, keeping things separate allows for greater flexibility if things change in the future. Then again, if everything’s kept separate and there’s a lot of repetition then making one update to one common area of functionality may mean making the same change a number of times, and requiring more testing to be satisfied everything’s working as expected. Again, it’s just something to recognise and consider for each project or even business service.
Customised forms
When considering shared configuration and the reuse vs. complexity dilemma (above) service forms are a crucial ingredient in providing a way for some shared configuration to be altered for only a specific business service or group of business services. Or more specifically, a way for this to be achieved efficiently and in a way where tooling such as Magellan can make the changes more visible, even if defined away from the configuration they impact.
See cascading configuration for more details regarding customising configuration relating to service forms.
It’s worth noting that these customisations result in changes to what can be thought of as the configuration. Whether they are applicable and how they will be applied is still determined at runtime.
Remember service form customisations result in changes to the configuration. Whether and how they are applied is still determined at runtime.
What this means is that you can change the configuration but it doesn’t mean you’ll definitely get what you expect at runtime. For example, if you have the following:
<businessService code="myService1" mode="Create" formItem="myForm1" displayGroup="create"/>
Form configuration:
<record shortCode="myForm1" domain="MyDomain">
<stylesheet name="sheet1">
<selector selector="attribute">
<rule scope="instantiate" reference="myRule1" group="notCreate"/>
</selector>
</stylesheet>
<attribute attribute="Attr1" textKeyPrefix="attr1"/>
</record>
Resulting service form XML:
<record shortCode="myForm1" domain="MyDomain" businessServiceCode="myService1" businessServiceMode="Create" businessServiceFormCode="myForm1">
<stylesheet name="sheet1">
<selector selector="attribute">
<rule scope="instantiate" reference="myRule1" group="notCreate"/>
</selector>
</stylesheet>
<attribute attribute="Attr1" textKeyPrefix="attr1">
<rule scope="instantiate" reference="myRule1" group="notCreate"/>
</attribute>
</record>
Which all looks fine, except the rule that’s been added is associated to the group notCreate and this particular business service has a displayGroup of create which, let’s just go out on a limb and say doesn’t relate to the notCreate display group’s hierarchy. So if you expected this rule to be run on this attribute for this business service at runtime you would be disappointed to find it does not. Hopefully this highlights the nature of service form customisations, their scope and how they simply impact the configuration used at runtime.
Service form XML
A service form can be viewed as XML, which is a static view of the XML configuration that the runtime data structure uses.
Whilst the resulting XML representation of the service form configuration can be quite different from the static form configuration XML, they are often highly similar.
In addition to any customisations that might be applied, the following business service detail attributes are added to the form root element:
businessServiceCode– thecodeof the business service configurationbusinessServiceMode– themodeof the business service configurationbusinessServiceFormCode– theformItemof the business service configuration, which matches theshortCodeof the form itself
In the simplest cases where there are no business-service-based modifications applicable the service form will actually match the form configuration with the exception of including the attributes mentioned above on the root element, as per the first example below.
Remember don’t be fooled though into thinking the service form always follows a form this closely. Also remember it is the service form the view tree is based on, not the form, so the service form reigns supreme in determining what structure and form the view tree should take.
No customisations example
Below is a trivial example where there are no customisations so the service form winds up the same as the form configuration on which it’s based with the exception of the business service detail attributes added to the root element.
Business service configuration:
<businessService code="myService1" mode="Create" formItem="myForm1" displayGroup="create"/>
Form configuration:
<record shortCode="myForm1" domain="MyDomain">
<attribute attribute="Attr1" textKeyPrefix="attr1"/>
</record>
Resulting service form XML:
<record shortCode="myForm1" domain="MyDomain" businessServiceCode="myService1" businessServiceMode="Create" businessServiceFormCode="myForm1">
<attribute attribute="Attr1" textKeyPrefix="attr1"/>
</record>
Minor customisation example
Below is a similar trivial example but one that results in the service form XML differing from the form configuration on which it is initially based.
Business service configuration:
<businessService code="myService1" mode="Create" formItem="myForm1" displayGroup="create"/>
Form configuration:
<record shortCode="myForm1" domain="MyDomain">
<stylesheet name="sheet1">
<selector selector="attribute">
<readOnly value="true"/>
</selector>
</stylesheet>
<attribute attribute="Attr1" textKeyPrefix="attr1"/>
</record>
Resulting service form XML:
<record shortCode="myForm1" domain="MyDomain" businessServiceCode="myService1" businessServiceMode="Create" businessServiceFormCode="myForm1">
<stylesheet name="sheet1">
<selector selector="attribute">
<readOnly value="true"/>
</selector>
</stylesheet>
<attribute attribute="Attr1" textKeyPrefix="attr1" readOnly="true"/>
</record>
Note the readOnly="true" on the Attr1 attribute element.
See cascading configuration for more examples where the form configuration is customised, resulting in the service form XML representation differing from the form configuration (as well as how to apply such customisations).

