Skip to content

Maintain Operations Step by Step

TL;DR

  • Configure your hashCode generator template.

  • Decide if it's a Data or Structure operation.

  • Implement all 4 operations (add, change, addOrChange, remove). Do not forget sub properties and implement ChangeOperation interface.

  • Include the operations at the properly ChangeSetDTO.

  • Generate xsd to commit.

  • Register the execution of your operations at ChangeSetStructureExecutor or ChangeSetDataExecutor.

  • Implement the executors, do not forget getEntity() and provide a EntityResolver to your Object.

  • Create tests to each executor.

  • Implement download mapping.

DTO

HashCode

Since there is a MD5 hash validation over the changeSet by Liquibase, it's necessary to have a different approach when implement hashCode, basically computes value only if the property is not null.

This prevent false positive hash validation when adding new properties to the ChangeSetDTO object. Bellow there are two examples:

Default Template

    @Override
    public final int hashCode() {
        int result = dataObject != null ? dataObject.hashCode() : 0;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + (criteriaList != null ? criteriaList.hashCode() : 0);
        return result;
    }

Custom Template

    @Override
    public int hashCode() {
        int result = dataObject != null ? dataObject.hashCode() : 0;
        result = (name != null ? 31 * result : result) + (name != null ? name.hashCode() : 0);
        result = (CollectionUtils.isNotEmpty(criteriaList) ? 31 * result : result) + (CollectionUtils.isNotEmpty(criteriaList) ? criteriaList.hashCode() : 0);
        return result;
    }

Observe the difference, at the Custom Template the result variable only receives value if the property is not null.

Configuration

1) Open the file you want to create the hashCode and equals code and press ALT + INSERT

2) Check the first option and click at ... button

3) Click at Copy button and define a name of your preference and click OK

4) Paste the code of the custom template located at meceap\extra\templates\changelog-hashCode.template at the HasCode Template input and click OK

Done, to use simple select the created template. You may need restart your IDE to work.

Operations

Structure vs Data

First of all, you need to decide if your operation is considered Structure or Data, this is easy to know, if your object depends on data from xlsx files, you are dealing with a Data operation, if not, Structure. This is important, since the JarProcessor has the following order to process files:

  • Structure
  • Import xlsx files
  • Data

A good example of data operation is every object that contains criteria.

Operations

There are 4 types of operations:

  • add: Used to create a object, by default generate a exception when the object already exists.
  • change: Used to change a object, by default generate a exception when the object doesn't exists.
  • addOrChange: Created specially to provide compatibility to apps created by AppBuilder. This operation verify if the object exists or not and redirect to the correct executor, add if not exists and change if exists.
  • remove: Used to remove a object, normally do not generate a exception if the object doesn't exists.

This all four operations have to be implemented, the exception is change, there are objects that has no need to change, for example: DocumentType Notification. But the addOrChange must be implemented and in the case of the object already exists simple do nothing.

Remember:

ChangeSet operation needs to be as granular as possible. The goal is always to provide a way to change a specific part or property without having to process the whole object.

Taking DataObject as a example, there are operations over the DataObject, but also operations related to fields, indexes and dataSources.

Another tip, you must pay attention on change operations, change operations may have many fields and you only should change fields that were informed.

Your class must implement ChangeOperation interface, this is need because all operations are stored at database, more about this later.

After create all operations list them at the properly ChangeSetDTO class, do not forget to change equals and hashCode methods to include the new properties.

XSD

After implement your DTOs and list at ChangeSetDTO execute the test testGeneratingSchema(). You'll notice some xsd files changed, do not forget to commit them.

Register the Execution

You need to register your operation at ChangeSetStructureExecutor or ChangeSetDataExecutor. Pay attention in the order you place the operation. For example, DataObject must be created before DocumentType, you'll see a bunch of examples at these classes.

Implement the Executor

After register your operation at ChangeSetExecutor create a class that implements ChangeExecutor<T> where T is your ChangeOperation / DTO. After this the ChangeSetExecutor is responsible to execute the correct ChangeExecutor for each DTO that need to be processed.

You'll need to implement two methods:

  • execute(): Execute change operation.

  • getEntity(): Return the target Entity of operation. (Only high level: DataObject, DocumentType. Never field for example.)

First, it's important to understand what is this Entity object, short description: It's a generic implementation to store information about any object that exist at CEAP.

Was created because every operation executed by the ChangeLog is persisted in a collection at MongoDB named customRootName._Change.

Fortunately there is a simple way to obtain this Entity for every BaseObject and BaseMongoObject, two steps:

1) Create your EntityResolver: Implement a EntityBaseObjectResolver or EntityBaseMongoObjectResolver, examples: EntityDataObjectResolver and EntityMacroResolver. The resolver is needed to define which properties compose the unique key of the object.

2) Use the EntityService at your ChangeExecutor simple executing the method getEntity().

This is useful to navigate from the Change to the affect Object and from the Object to Changes. Even if the object is removed and recreated we'll be able to reproduce these steps because we don't store the id, but the properties that make the object unique.

Tests

Implement tests for each executor, remember the quality gate and try to obtain at least 80% of coverage. You also can use CoffeeDispenser to write xml files and verify if your operation is executing properly.

Download

Verify if it's necessary to export and import information across CEAP instances, if yes:

  • Implement the UI and DownloadConfiguration class.
  • Create a class that implement ChangeSetMapper interface.
  • Change ChangeLog*MappingManager including your Mapper.