๐Ÿ“˜ Exception Definition Language (EDL)

Structured exception specification with category owned code prefixes


๐ŸŽฏ 1. Key design rules

โœ… Category owns the code prefix

โœ… Error defines only a numeric suffix

โœ… Final error code is derived

โœ… Error names use camelCase

This enforces semantic ownership and prevents code drift.


๐Ÿง  2. Core concepts

ConceptDefinition
Root exceptionSingle abstract base class
CategoryAbstract base exception with semantic meaning and code prefix
ErrorConcrete exception extending one category
Code prefixCategory level identifier
Code valueFour digit numeric value on the error
Final code<prefix>-<value>
Message templateParameterised human readable message
ParametersTyped constructor arguments

๐ŸŒณ 3. Inheritance model

Rules enforced by the compiler:

  1. Exactly one root exception
  2. Categories form an acyclic inheritance tree
  3. Each category generates one abstract base class
  4. Each error extends exactly one category
  5. Only categories define code prefixes
  6. Only errors define numeric code values

๐Ÿ“„ 4. EDL structure


๐Ÿงพ 4.1 Top level document

package: com.example.errors
rootException: ApplicationException

๐Ÿ—‚๏ธ 4.2 Category definition

categories:
  NotFound:
    codePrefix: NF
    httpStatus: 404
    retryable: false

  Validation:
    codePrefix: VAL
    httpStatus: 400

Category fields

FieldRequiredMeaning
parentNoParent category, defaults to root
codePrefixYesError code prefix owned by this category
httpStatusNoHTTP status for this category
retryableNoRetryability flag
abstractNoDefaults to true

โ— 4.3 Error definition

errors:
  invalidEmail:
    category: Validation
    code: 0001
    message: "Email '{email}' is invalid."
    params:
      email: String

  userNotFound:
    category: NotFound
    code: 0004
    message: "User '{userId}' was not found."
    params:
      userId: UUID

Error fields

FieldRequiredMeaning
categoryYesOwning category
codeYesFour digit numeric value
messageYesMessage template
paramsYesNamed typed parameters

๐Ÿšซ Codes outside 0000 to 9999 are invalid.


๐Ÿ” 5. Code composition rules

The compiler MUST generate final codes as follows:

<category.codePrefix>-<error.code>

Example

Validation + 0001  ->  VAL-0001
NotFound + 0004    ->  NF-0004

๐Ÿงช 6. Semantic validation rules

๐Ÿงฑ Structural

  • Category code prefixes must be unique
  • Error numeric codes must be unique within a category
  • Error names must be camelCase
  • Category names must be PascalCase

๐Ÿ“ Message rules

  • Every placeholder must match a parameter
  • Every parameter must be used exactly once
  • Parameter names are case sensitive

โ˜• Java rules

  • Generated code must compile without warnings
  • All generated exceptions must be immutable
  • No reflection is permitted

๐Ÿงฌ 7. Java generation semantics


๐Ÿชต 7.1 Root exception

public abstract class ApplicationException extends RuntimeException {

  private final String code;
  private final String messageTemplate;
  private final Map<String, Object> parameters;

  protected ApplicationException(
      String code,
      String messageTemplate,
      Map<String, Object> parameters,
      Throwable cause) {

    super(messageTemplate, cause);
    this.code = code;
    this.messageTemplate = messageTemplate;
    this.parameters = Map.copyOf(parameters);
  }

  public final String getCode() {
    return code;
  }

  public final String getMessageTemplate() {
    return messageTemplate;
  }

  public final Map<String, Object> getParameters() {
    return parameters;
  }
}

๐Ÿ—‚๏ธ 7.2 Category exception

public abstract class ValidationException extends ApplicationException {

  protected ValidationException(
      String numericCode,
      String template,
      Map<String, Object> parameters,
      Throwable cause) {

    super(
        "VAL-" + numericCode,
        template,
        parameters,
        cause
    );
  }

  public int getHttpStatus() {
    return 400;
  }
}

๐Ÿ“Œ Category composes the final error code.


โ— 7.3 Concrete error exception

public final class InvalidEmailException extends ValidationException {

  public static final String NUMERIC_CODE = "0001";

  public InvalidEmailException(String email) {
    super(
        NUMERIC_CODE,
        "Email '{email}' is invalid.",
        Map.of("email", email),
        null
    );
  }
}

โœ” Leaf class never hardcodes the prefix
โœ” Prefix changes do not require touching leaf errors


๐Ÿ“š 8. Extended example

๐Ÿงพ YAML

categories:
  ClientError:
    abstract: true

  Validation:
    parent: ClientError
    codePrefix: VAL
    httpStatus: 400

  NotFound:
    parent: ClientError
    codePrefix: NF
    httpStatus: 404

errors:
  invalidEmail:
    category: Validation
    code: 0001
    message: "Email '{email}' is invalid."
    params:
      email: String

  userNotFound:
    category: NotFound
    code: 0001
    message: "User '{userId}' does not exist."
    params:
      userId: UUID

๐ŸŒณ Resulting hierarchy

ApplicationException
 โ””โ”€ ClientErrorException
    โ”œโ”€ ValidationException
    โ”‚  โ””โ”€ InvalidEmailException   -> VAL-0001
    โ””โ”€ NotFoundException
       โ””โ”€ UserNotFoundException   -> NF-0001

๐Ÿงฐ 9. Maven plugin impact

๐Ÿ” Additional validations

The Maven plugin MUST now enforce:

  • category codePrefix uniqueness
  • numeric error codes are exactly 4 digits
  • numeric codes are unique per category
  • camelCase error identifiers
  • PascalCase category identifiers

๐Ÿง  10. Why this refinement matters

  • ๐Ÿงญ categories fully own their error space
  • ๐Ÿ” prefixes can be renamed without touching errors
  • ๐Ÿ” numeric codes remain compact and sortable
  • ๐Ÿ“– error specs stay readable and low noise
  • ๐Ÿงฌ generated Java stays clean and stable

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.