Skip to content

Commit 574a275

Browse files
authored
refactor(templates): introduce TemplateField hierarchy (#861)
- Add **TemplateField** interface with `validate()` as base for all template field types - **TemplatePayload** extends TemplateField, adds `getInfo()` for transactional metadata - Relax SHARED_CONFIG bound from `TemplatePayload` to `TemplateField` across the template hierarchy - Config fields now need only validation, not tx semantics - Binary-compatible: existing TemplatePayload impls still satisfy the relaxed bound
1 parent 7cfd423 commit 574a275

13 files changed

Lines changed: 65 additions & 29 deletions

File tree

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ See `docs/TEMPLATES_EVOLUTION_PROPOSALS.md` for comprehensive proposals includin
515515
## Commit Message Convention
516516

517517
All commits must follow [Conventional Commits](https://www.conventionalcommits.org/) with a well-structured body suitable for changelog extraction from `git log`.
518+
Don't add co-authored by claude
518519

519520
### Format
520521

core/flamingock-core-api/src/main/java/io/flamingock/api/template/AbstractChangeTemplate.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
* @param <ROLLBACK_FIELD> rollback payload type
4040
* @see io.flamingock.api.annotations.ChangeTemplate
4141
*/
42-
public abstract class AbstractChangeTemplate<SHARED_CONFIGURATION_FIELD extends TemplatePayload, APPLY_FIELD extends TemplatePayload, ROLLBACK_FIELD extends TemplatePayload> implements ChangeTemplate<SHARED_CONFIGURATION_FIELD, APPLY_FIELD, ROLLBACK_FIELD> {
42+
public abstract class AbstractChangeTemplate<SHARED_CONFIGURATION_FIELD extends TemplateField, APPLY_FIELD extends TemplatePayload, ROLLBACK_FIELD extends TemplatePayload> implements ChangeTemplate<SHARED_CONFIGURATION_FIELD, APPLY_FIELD, ROLLBACK_FIELD> {
4343

4444
private final Class<SHARED_CONFIGURATION_FIELD> configurationClass;
4545
private final Class<APPLY_FIELD> applyPayloadClass;

core/flamingock-core-api/src/main/java/io/flamingock/api/template/ChangeTemplate.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
* @see AbstractChangeTemplate
2929
* @see io.flamingock.api.annotations.ChangeTemplate
3030
*/
31-
public interface ChangeTemplate<SHARED_CONFIG_FIELD extends TemplatePayload, APPLY_FIELD extends TemplatePayload, ROLLBACK_FIELD extends TemplatePayload> extends ReflectionMetadataProvider {
31+
public interface ChangeTemplate<SHARED_CONFIG_FIELD extends TemplateField, APPLY_FIELD extends TemplatePayload, ROLLBACK_FIELD extends TemplatePayload> extends ReflectionMetadataProvider {
3232

3333
void setChangeId(String changeId);
3434

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2026 Flamingock (https://www.flamingock.io)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.flamingock.api.template;
17+
18+
import java.util.List;
19+
20+
/**
21+
* Base contract for all template field types (configuration, apply, rollback).
22+
*
23+
* <p>Provides structural validation at pipeline load time, before any change executes.
24+
* Configuration fields extend this directly, while apply/rollback payloads extend
25+
* {@link TemplatePayload} which adds transactional metadata via {@code getInfo()}.
26+
*/
27+
public interface TemplateField {
28+
29+
/**
30+
* Validates this field using the supplied change-level context
31+
* and returns any errors found.
32+
*
33+
* @param context change-level metadata available during validation
34+
* @return list of validation errors, empty if field is valid
35+
*/
36+
List<TemplatePayloadValidationError> validate(TemplateValidationContext context);
37+
}

core/flamingock-core-api/src/main/java/io/flamingock/api/template/TemplatePayload.java

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,11 @@
2020
/**
2121
* Contract for template payload types (APPLY and ROLLBACK generics).
2222
*
23-
* <p>All template payload types must implement this interface to enable
24-
* structural validation at pipeline load time, before any change executes.
23+
* <p>Extends {@link TemplateField} to inherit structural validation, and adds
24+
* transactional metadata via {@link #getInfo()}. Configuration fields use
25+
* {@code TemplateField} directly since they have no transactional semantics.
2526
*/
26-
public interface TemplatePayload {
27-
28-
/**
29-
* Validates this payload using the supplied change-level context
30-
* and returns any errors found.
31-
*
32-
* @param context change-level metadata available during validation
33-
* @return list of validation errors, empty if payload is valid
34-
*/
35-
List<TemplatePayloadValidationError> validate(TemplateValidationContext context);
27+
public interface TemplatePayload extends TemplateField {
3628

3729
/**
3830
* Returns metadata about this payload so the framework can make

core/flamingock-core-api/src/main/java/io/flamingock/api/template/wrappers/TemplateVoid.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,11 @@
2424
import java.util.List;
2525

2626
/**
27-
* A {@link TemplatePayload} sentinel representing "no configuration needed".
27+
* A {@link TemplatePayload} sentinel representing "no value needed".
2828
*
29-
* <p>Replaces {@code Void} as the CONFIG type parameter in templates that
30-
* have no shared configuration. Unlike {@code Void}, this class implements
31-
* {@code TemplatePayload}, satisfying the {@code CONFIG extends TemplatePayload}
32-
* bound on the template system.
29+
* <p>Replaces {@code Void} as a type parameter in templates that have no shared
30+
* configuration or no rollback. Implements {@code TemplatePayload} so it can be
31+
* used in any template type parameter position (CONFIG, APPLY, or ROLLBACK).
3332
*/
3433
public class TemplateVoid implements TemplatePayload {
3534

core/flamingock-core/src/main/java/io/flamingock/internal/core/task/executable/AbstractTemplateExecutableTask.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package io.flamingock.internal.core.task.executable;
1717

1818
import io.flamingock.api.template.ChangeTemplate;
19+
import io.flamingock.api.template.TemplateField;
1920
import io.flamingock.api.template.TemplatePayload;
2021
import io.flamingock.api.template.wrappers.TemplateVoid;
2122
import io.flamingock.internal.common.core.recovery.action.ChangeAction;
@@ -36,7 +37,7 @@
3637
* @param <ROLLBACK> the rollback payload type
3738
* @param <LOADED_CHANGE> the type of template loaded change
3839
*/
39-
public abstract class AbstractTemplateExecutableTask<CONFIG extends TemplatePayload, APPLY extends TemplatePayload, ROLLBACK extends TemplatePayload,
40+
public abstract class AbstractTemplateExecutableTask<CONFIG extends TemplateField, APPLY extends TemplatePayload, ROLLBACK extends TemplatePayload,
4041
LOADED_CHANGE extends AbstractTemplateLoadedChange<CONFIG, APPLY, ROLLBACK>> extends ReflectionExecutableTask<LOADED_CHANGE> {
4142
protected final Logger logger = FlamingockLoggerFactory.getLogger("TemplateExecutableChange");
4243

core/flamingock-core/src/main/java/io/flamingock/internal/core/task/executable/SimpleTemplateExecutableTask.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package io.flamingock.internal.core.task.executable;
1717

1818
import io.flamingock.api.template.AbstractChangeTemplate;
19+
import io.flamingock.api.template.TemplateField;
1920
import io.flamingock.api.template.TemplatePayload;
2021
import io.flamingock.internal.common.core.error.ChangeExecutionException;
2122
import io.flamingock.internal.common.core.recovery.action.ChangeAction;
@@ -33,7 +34,7 @@
3334
* @param <ROLLBACK> the rollback payload type
3435
*/
3536
@SuppressWarnings({"rawtypes", "unchecked"})
36-
public class SimpleTemplateExecutableTask<CONFIG extends TemplatePayload, APPLY extends TemplatePayload, ROLLBACK extends TemplatePayload>
37+
public class SimpleTemplateExecutableTask<CONFIG extends TemplateField, APPLY extends TemplatePayload, ROLLBACK extends TemplatePayload>
3738
extends AbstractTemplateExecutableTask<CONFIG, APPLY, ROLLBACK,
3839
SimpleTemplateLoadedChange<CONFIG, APPLY, ROLLBACK>> {
3940

core/flamingock-core/src/main/java/io/flamingock/internal/core/task/executable/SteppableTemplateExecutableTask.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package io.flamingock.internal.core.task.executable;
1717

1818
import io.flamingock.api.template.AbstractChangeTemplate;
19+
import io.flamingock.api.template.TemplateField;
1920
import io.flamingock.api.template.TemplatePayload;
2021
import io.flamingock.api.template.TemplateStep;
2122
import io.flamingock.internal.common.core.error.ChangeExecutionException;
@@ -36,7 +37,7 @@
3637
* @param <ROLLBACK> the rollback payload type
3738
*/
3839
@SuppressWarnings({"rawtypes", "unchecked"})
39-
public class SteppableTemplateExecutableTask<CONFIG extends TemplatePayload, APPLY extends TemplatePayload, ROLLBACK extends TemplatePayload>
40+
public class SteppableTemplateExecutableTask<CONFIG extends TemplateField, APPLY extends TemplatePayload, ROLLBACK extends TemplatePayload>
4041
extends AbstractTemplateExecutableTask<CONFIG, APPLY, ROLLBACK,
4142
MultiStepTemplateLoadedChange<CONFIG, APPLY, ROLLBACK>> {
4243

core/flamingock-core/src/main/java/io/flamingock/internal/core/task/loaded/AbstractTemplateLoadedChange.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import io.flamingock.api.annotations.Apply;
1919
import io.flamingock.api.annotations.Rollback;
2020
import io.flamingock.api.template.ChangeTemplate;
21+
import io.flamingock.api.template.TemplateField;
2122
import io.flamingock.api.template.TemplatePayload;
2223
import io.flamingock.api.template.TemplateValidationContext;
2324
import io.flamingock.internal.common.core.error.validation.ValidationError;
@@ -43,7 +44,7 @@
4344
* @param <APPLY> the apply payload type
4445
* @param <ROLLBACK> the rollback payload type
4546
*/
46-
public abstract class AbstractTemplateLoadedChange<CONFIG extends TemplatePayload, APPLY extends TemplatePayload, ROLLBACK extends TemplatePayload> extends AbstractLoadedChange {
47+
public abstract class AbstractTemplateLoadedChange<CONFIG extends TemplateField, APPLY extends TemplatePayload, ROLLBACK extends TemplatePayload> extends AbstractLoadedChange {
4748

4849
protected static final Logger logger = FlamingockLoggerFactory.getLogger(AbstractTemplateLoadedChange.class);
4950

0 commit comments

Comments
 (0)