### Maven Dependency Setup for jMolecules Source: https://context7.com/xmolecules/jmolecules/llms.txt Configure your Maven project to include jMolecules modules. It's recommended to use the jmolecules-bom for centralized version management. ```xml org.jmolecules jmolecules-bom 2021.1.0 pom import org.jmolecules jmolecules-ddd org.jmolecules jmolecules-events org.jmolecules jmolecules-architecture pom org.jmolecules kmolecules-ddd ``` -------------------------------- ### Define Custom Stereotype with @Stereotype Source: https://context7.com/xmolecules/jmolecules/llms.txt Use the @Stereotype meta-annotation to define custom stereotypes for your application's architectural patterns. This example shows how to define a 'ReadModel' stereotype with specific name, ID, groups, and priority. ```java import org.jmolecules.stereotype.Stereotype; import java.lang.annotation.*; // Define a custom stereotype for your own architectural patterns @Stereotype( name = "Read Model", id = "com.acme.architecture.ReadModel", groups = { "com.acme.architecture" }, priority = 50 ) @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented public @interface ReadModel {} ``` ```java // Alternative: custom stereotype as a marker interface @Stereotype( name = "Saga", id = "com.acme.architecture.Saga", groups = { "com.acme.architecture" } ) public interface Saga {} ``` -------------------------------- ### Maven Release Perform Command Source: https://github.com/xmolecules/jmolecules/blob/main/readme.adoc Perform the release after preparation using Maven's release plugin, specifying the GPG key name for signing. ```bash mvn release:perform -Dgpg.keyname=$keyname ``` -------------------------------- ### Maven Release Prepare Command Source: https://github.com/xmolecules/jmolecules/blob/main/readme.adoc Prepare for a release using Maven's release plugin, specifying commit messages for SCM changes. ```bash mvn release:prepare -DscmReleaseCommitComment="$ticketId - Release version $version." -DscmDevelopmentCommitComment="$ticketId - Prepare next development iteration." ``` -------------------------------- ### Define Bounded Context with @BoundedContext Source: https://context7.com/xmolecules/jmolecules/llms.txt Package-level annotation to identify bounded contexts. Supports optional id, name, and description attributes for documentation generation. Requires BoundedContext import. ```java // com/acme/banking/package-info.java @BoundedContext( id = "com.acme.banking", name = "Banking", description = "Manages bank accounts, transfers, and transaction history" ) package com.acme.banking; import org.jmolecules.ddd.annotation.BoundedContext; ``` -------------------------------- ### Define Module with @Module Source: https://context7.com/xmolecules/jmolecules/llms.txt Package-level annotation to identify DDD modules. Supports optional id, name, and description attributes for documentation generation. Requires Module import. ```java // com/acme/banking/accounts/package-info.java @Module( id = "accounts", name = "Accounts Module", description = "Core account management and lifecycle" ) package com.acme.banking.accounts; import org.jmolecules.ddd.annotation.Module; ``` -------------------------------- ### Onion Architecture Annotations (Classical and Simplified) Source: https://context7.com/xmolecules/jmolecules/llms.txt Supports two variants of Onion Architecture: classical (4 rings) and simplified (3 rings). Annotate packages to define the rings of your architecture. ```java // === Classical (4-ring) Onion Architecture === import org.jmolecules.architecture.onion.classical.*; // Innermost ring — pure domain model, no outward dependencies @DomainModelRing package com.acme.banking.domain.model; ``` ```java // Domain services ring — depends only on DomainModelRing @DomainServiceRing package com.acme.banking.domain.services; ``` ```java // Application services ring — orchestrates domain services @ApplicationServiceRing package com.acme.banking.application; ``` ```java // Outermost ring — infrastructure, adapters, frameworks @InfrastructureRing package com.acme.banking.infrastructure; ``` ```java // === Simplified (3-ring) Onion Architecture === import org.jmolecules.architecture.onion.simplified.*; // Combined domain model + services ring @DomainRing package com.acme.banking.domain; ``` ```java // Application ring @ApplicationRing package com.acme.banking.app; ``` ```java // Infrastructure ring @InfrastructureRing package com.acme.banking.infra; ``` -------------------------------- ### Kotlin DDD Annotations for Aggregate Root and Value Objects Source: https://context7.com/xmolecules/jmolecules/llms.txt Demonstrates Kotlin DDD patterns using kmolecules annotations. Ensure correct data classes and value object definitions for immutability and validation. ```kotlin import org.jmolecules.ddd.annotation.AggregateRoot import org.jmolecules.ddd.annotation.Entity import org.jmolecules.ddd.annotation.Identity import org.jmolecules.ddd.annotation.ValueObject import org.jmolecules.ddd.annotation.Repository // Kotlin aggregate root using kmolecules annotations @AggregateRoot data class BankAccount( @Identity val iban: IBAN, var balance: Money ) { private val _entries: MutableList = mutableListOf() val entries: List get() = _entries.toList() fun credit(amount: Money): BankAccount { require(amount.currency == balance.currency) { "Currency mismatch" } _entries += AccountEntry(amount = amount, type = EntryType.CREDIT) return copy(balance = balance + amount) } } ``` ```kotlin @ValueObject @JvmInline value class IBAN(val value: String) { init { require(value.matches(Regex("[A-Z]{2}[0-9]{2}[A-Z0-9]{4,30}"))) } } ``` ```kotlin @ValueObject data class Money(val amount: BigDecimal, val currency: String) { operator fun plus(other: Money): Money { require(currency == other.currency) { "Currency mismatch" } return Money(amount + other.amount, currency) } } ``` ```kotlin @Entity data class AccountEntry( @Identity val id: UUID = UUID.randomUUID(), val amount: Money, val type: EntryType ) ``` ```kotlin @Repository class AccountRepository { private val store = mutableMapOf() fun save(account: BankAccount) { store[account.iban] = account } fun findByIban(iban: IBAN): BankAccount? = store[iban] } ``` -------------------------------- ### CQRS Command and Query Model Annotations in Java Source: https://context7.com/xmolecules/jmolecules/llms.txt Defines commands and query models using Jmolecules annotations for CQRS. Ensure the correct namespace and command/query names are used. ```java import org.jmolecules.architecture.cqrs.*; // Commands — imperative requests for state change @Command(namespace = "com.acme.banking", name = "TransferMoney") record TransferMoneyCommand(UUID transferId, String fromIban, String toIban, BigDecimal amount) {} @Command(namespace = "com.acme.banking", name = "OpenAccount") record OpenAccountCommand(String iban, BigDecimal initialDeposit, String currency) {} // Query model — read-optimized projection (only used in the Query side) @QueryModel class AccountSummaryView { private final String iban; private BigDecimal balance; private int transactionCount; AccountSummaryView(String iban, BigDecimal balance) { this.iban = iban; this.balance = balance; } void applyCredit(BigDecimal amount) { balance = balance.add(amount); transactionCount++; } // getters... } ``` ```java // Command handler — processes commands, may reject them class BankingCommandHandler { private final AccountRepository repository; @CommandHandler(namespace = "com.acme.banking", name = "OpenAccount") AccountId handle(OpenAccountCommand cmd) { Account account = Account.open( new AccountId(UUID.randomUUID()), cmd.iban(), new Money(cmd.initialDeposit(), cmd.currency()) ); repository.save(account); return account.getId(); } @CommandHandler(namespace = "com.acme.banking", name = "TransferMoney") void handle(TransferMoneyCommand cmd) { // business logic — may throw to reject the command Account source = repository.findByIban(cmd.fromIban()) .orElseThrow(() -> new IllegalArgumentException("Source account not found")); source.debit(new Money(cmd.amount(), "EUR")); repository.save(source); } } ``` -------------------------------- ### Annotate Domain Layer Package Source: https://github.com/xmolecules/jmolecules/blob/main/readme.adoc Annotate the package-info.java file to mark an entire package as the Domain Layer using jMolecules architecture annotations. ```java @DomainLayer package org.acmebank.domain; import org.jmolecules.architecture.layered.*; ``` -------------------------------- ### Annotate Application Layer Package Source: https://github.com/xmolecules/jmolecules/blob/main/readme.adoc Annotate the package-info.java file to mark an entire package as the Application Layer using jMolecules architecture annotations. ```java @ApplicationLayer package org.acmebank.application; import org.jmolecules.architecture.layered.*; ``` -------------------------------- ### Hexagonal Architecture Annotations Source: https://context7.com/xmolecules/jmolecules/llms.txt Annotations for Ports & Adapters / Hexagonal Architecture. Use @Application for the core, @PrimaryPort/@SecondaryPort for boundary interfaces, and @PrimaryAdapter/@SecondaryAdapter for implementations. ```java import org.jmolecules.architecture.hexagonal.*; // Core application — must only use Ports, never Adapters @Application package com.acme.banking.core; ``` ```java // Primary port — interface driven by the outside world (e.g., REST, CLI) @PrimaryPort(name = "AccountManagement", description = "Use cases for managing bank accounts") interface AccountManagementPort { AccountId openAccount(String iban, BigDecimal initialDeposit); void credit(AccountId id, BigDecimal amount); Optional findAccount(AccountId id); } ``` ```java // Primary adapter — connects HTTP to the core via the primary port @PrimaryAdapter(name = "REST API", description = "HTTP REST adapter for account management") class AccountRestAdapter { private final AccountManagementPort port; AccountRestAdapter(AccountManagementPort port) { this.port = port; } // e.g., maps HTTP request -> port call -> HTTP response AccountView handleGet(String iban) { return port.findAccount(new AccountId(UUID.fromString(iban))) .orElseThrow(() -> new NoSuchElementException("Account not found")); } } ``` ```java // Secondary port — abstraction the core defines, infrastructure implements @SecondaryPort(name = "AccountRepository", description = "Persistence abstraction for accounts") interface AccountRepository { void save(Account account); Optional findById(AccountId id); } ``` ```java // Secondary adapter — implements the secondary port using a specific technology @SecondaryAdapter(name = "JPA Account Repository", description = "JPA-based persistence") class JpaAccountRepository implements AccountRepository { // JPA EntityManager, etc. @Override public void save(Account account) { /* JPA save logic */ } @Override public Optional findById(AccountId id) { /* JPA find logic */ return Optional.empty(); } } ``` -------------------------------- ### Layered Architecture Annotations Source: https://context7.com/xmolecules/jmolecules/llms.txt Use these annotations to mark packages or types with classic architectural layers. Apply to package-info.java for package-wide inheritance or directly to classes. ```java // com/acme/banking/domain/package-info.java @DomainLayer package com.acme.banking.domain; import org.jmolecules.architecture.layered.DomainLayer; ``` ```java // com/acme/banking/application/package-info.java @ApplicationLayer package com.acme.banking.application; import org.jmolecules.architecture.layered.ApplicationLayer; ``` ```java // com/acme/banking/infrastructure/package-info.java @InfrastructureLayer package com.acme.banking.infrastructure; import org.jmolecules.architecture.layered.InfrastructureLayer; ``` ```java // com/acme/banking/interfaces/package-info.java @InterfaceLayer package com.acme.banking.interfaces; import org.jmolecules.architecture.layered.InterfaceLayer; ``` ```java // Alternatively, annotate individual classes when mixing layers in one package import org.jmolecules.architecture.layered.*; import org.jmolecules.ddd.annotation.*; @DomainLayer @AggregateRoot public class BankAccount { /* ... */ } ``` ```java @ApplicationLayer @Service public class TransferMoney { /* ... */ } ``` ```java @InfrastructureLayer @Repository public class JpaBankAccountRepository { /* ... */ } ``` ```java @InterfaceLayer public class AccountRestController { /* ... */ } ``` -------------------------------- ### DDD Type-Based Model with Interfaces Source: https://context7.com/xmolecules/jmolecules/llms.txt Leverage the Java type system with interfaces for compile-time verification of DDD structural constraints. Dedicated identifier types prevent accidental mixing. ```java import org.jmolecules.ddd.types.*; // Dedicated identifier types per aggregate prevent mixing record AccountId(UUID value) implements Identifier {} record CustomerId(UUID value) implements Identifier {} // Aggregate root — self-referential generic type T class Account implements AggregateRoot { private final AccountId id; private MonetaryAmount balance; private final List entries = new ArrayList<>(); Account(AccountId id, MonetaryAmount initialBalance) { this.id = id; this.balance = initialBalance; } @Override public AccountId getId() { return id; } void credit(MonetaryAmount amount) { balance = balance.add(amount); entries.add(new AccountEntry(this, amount, EntryType.CREDIT)); } } // Entity — belongs to Account aggregate, cannot be confused with another aggregate's entity class AccountEntry implements Entity { private final UUID id = UUID.randomUUID(); private final MonetaryAmount amount; private final EntryType type; AccountEntry(Account owner, MonetaryAmount amount, EntryType type) { this.amount = amount; this.type = type; } @Override public UUID getId() { return id; } } // Repository typed to the aggregate root and its identifier class Accounts implements Repository { private final Map store = new ConcurrentHashMap<>(); void save(Account account) { store.put(account.getId(), account); } Optional findById(AccountId id) { return Optional.ofNullable(store.get(id)); } } // Value objects implement ValueObject (marker interface) record Money(BigDecimal amount, String currency) implements ValueObject { Money add(Money other) { if (!currency.equals(other.currency)) throw new IllegalArgumentException("Currency mismatch"); return new Money(amount.add(other.amount), currency); } } ``` -------------------------------- ### Create Associations with `Association.forAggregate()` and `Association.forId()` Source: https://context7.com/xmolecules/jmolecules/llms.txt Use `Association.forAggregate()` to create a reference from an aggregate instance and `Association.forId()` to create one from a raw identifier. These factory methods ensure type-safe cross-aggregate references that hold only an identifier. ```java import org.jmolecules.ddd.types.*; record OrderId(UUID value) implements Identifier {} record ProductId(UUID value) implements Identifier {} class Order implements AggregateRoot { private final OrderId id; // Cross-aggregate reference to Product — only holds the ID private final Association product; Order(OrderId id, Product product) { this.id = id; // Create association from an aggregate instance this.product = Association.forAggregate(product); } Order(OrderId id, ProductId productId) { this.id = id; // Create association from a raw identifier this.product = Association.forId(productId); } @Override public OrderId getId() { return id; } // Check if order references a specific product boolean refersTo(Product p) { return product.pointsTo(p); // by aggregate instance } boolean refersToId(ProductId pid) { return product.pointsTo(pid); // by identifier } boolean refersSameProductAs(Order other) { return product.pointsToSameAggregateAs(other.product); // cross-instance check } } class Product implements AggregateRoot { private final ProductId id; Product(ProductId id) { this.id = id; } @Override public ProductId getId() { return id; } } // Usage ProductId pid = new ProductId(UUID.randomUUID()); Product product = new Product(pid); Order order = new Order(new OrderId(UUID.randomUUID()), product); assert order.refersTo(product); // true assert order.refersToId(pid); // true ``` -------------------------------- ### Annotate Classes with Layered Architecture Source: https://github.com/xmolecules/jmolecules/blob/main/readme.adoc Annotate classes directly to define their layer within the architecture. Supports Domain, Application, Infrastructure, and Interface layers. ```java import org.jmolecules.architecture.layered.*; @DomainLayer @Entity public class BankAccount { /* ... */ } @ApplicationLayer @Service public class TransferMoney { /* ... */ } ``` -------------------------------- ### Declare Domain Events with `@DomainEvent` annotation or `DomainEvent` interface Source: https://context7.com/xmolecules/jmolecules/llms.txt Use either the `@DomainEvent` annotation or implement the `DomainEvent` interface to declare a class as a domain event. Optional `namespace` and `name` attributes provide stable external identifiers. ```java import org.jmolecules.event.annotation.DomainEvent; import org.jmolecules.event.annotation.DomainEventPublisher; import org.jmolecules.event.annotation.DomainEventHandler; import org.jmolecules.event.annotation.Externalized; // Annotation-based domain event @DomainEvent(namespace = "com.acme.banking", name = "AccountCredited") record AccountCredited(IBAN iban, MonetaryAmount amount, Instant occurredAt) {} // Type-based domain event (implements marker interface) record AccountDebited(IBAN iban, MonetaryAmount amount, Instant occurredAt) implements org.jmolecules.event.types.DomainEvent {} // Event to be published externally (e.g., to a message broker) @DomainEvent(namespace = "com.acme.banking", name = "TransferCompleted") @Externalized(target = "banking.transfers.completed") // logical target topic/channel record TransferCompleted(UUID transferId, IBAN from, IBAN to, MonetaryAmount amount) {} // Service publishing events class AccountService { private final ApplicationEventPublisher publisher; AccountService(ApplicationEventPublisher publisher) { this.publisher = publisher; } @DomainEventPublisher( publishes = "com.acme.banking.AccountCredited", type = DomainEventPublisher.PublisherType.INTERNAL ) void credit(IBAN iban, MonetaryAmount amount) { // ... business logic ... publisher.publishEvent(new AccountCredited(iban, amount, Instant.now())); } } // Event handler with explicit namespace/name linkage class AuditService { @DomainEventHandler( namespace = "com.acme.banking", name = "AccountCredited" ) void on(AccountCredited event) { // Audit log, projections, etc. System.out.printf("Account %s credited with %s at %s%n", event.iban(), event.amount(), event.occurredAt()); } // Wildcard: handle ALL events in the namespace @DomainEventHandler(namespace = "com.acme.banking", name = "*") void onAnyBankingEvent(Object event) { System.out.println("Banking event received: " + event.getClass().getSimpleName()); } } ``` -------------------------------- ### Tooling Detection of @Stereotype Source: https://context7.com/xmolecules/jmolecules/llms.txt Any type annotated with @Stereotype, directly or transitively, will be detected by various architectural tooling. This enables automated verification and documentation of architectural rules. ```java // Tooling detection: any type annotated with @Stereotype (directly or transitively) // will be detected by ArchUnit rules, jQAssistant, Spring Modulith, etc. ``` -------------------------------- ### Express DDD Entity with Annotations Source: https://github.com/xmolecules/jmolecules/blob/main/readme.adoc Use jMolecules DDD annotations to mark classes as DDD building blocks like Entity, Identity, ValueObject, and Repository. ```java import org.jmolecules.ddd.annotation.*; @Entity class BankAccount { @Identity final IBAN iban; /* ... */ } @ValueObject class IBAN { /* ... */ } @ValueObject record Currency { /* ... */ } @Repository class Accounts { /* ... */ } ``` -------------------------------- ### Gradle Dependency for jMolecules DDD Source: https://github.com/xmolecules/jmolecules/blob/main/readme.adoc Include the jMolecules DDD artifact in your Gradle project's dependencies. Ensure mavenCentral() is configured in your repositories. ```groovy repositories { mavenCentral() } dependencies { implementation("org.jmolecules:jmolecules-ddd:1.9.0") } ``` -------------------------------- ### Define Custom Stereotype Interface Source: https://github.com/xmolecules/jmolecules/wiki/The-Stereotype-Metamodel Define a custom stereotype as an interface using the @Stereotype meta-annotation. This allows classes to implement the stereotype. ```java package com.acme.example.stereotypes; @org.jmolecules.Stereotype public interface MyCustomStereotype { … } ``` -------------------------------- ### Assign Custom Stereotype to Application Component Source: https://github.com/xmolecules/jmolecules/wiki/The-Stereotype-Metamodel Assign a custom stereotype to an application component by either annotating it with the custom stereotype annotation or having it implement the custom stereotype interface. ```java @com.acme.example.stereotypes.MyCustomStereotype // <- either or … class MyApplicationComponent implements MyCustomStereotype { … } ``` -------------------------------- ### Cross-Aggregate Reference with @Association Source: https://context7.com/xmolecules/jmolecules/llms.txt Use `@Association` to express cross-aggregate references by identifier. The `aggregateType` attribute provides explicit tooling metadata. ```java import org.jmolecules.ddd.annotation.*; @AggregateRoot class Transfer { @Identity private final UUID id = UUID.randomUUID(); // Cross-aggregate references via @Association — no direct object reference @Association(aggregateType = BankAccount.class) private final IBAN sourceIban; @Association(aggregateType = BankAccount.class) private final IBAN targetIban; private final MonetaryAmount amount; Transfer(IBAN sourceIban, IBAN targetIban, MonetaryAmount amount) { this.sourceIban = sourceIban; this.targetIban = targetIban; this.amount = amount; } } ``` -------------------------------- ### Apply Custom Stereotypes Source: https://context7.com/xmolecules/jmolecules/llms.txt Apply custom stereotypes, such as the defined '@ReadModel' and 'Saga', to your classes. These custom stereotypes can be used alongside jMolecules built-in annotations. ```java // Apply custom stereotypes — usable alongside jMolecules built-ins @ReadModel class AccountProjection { private String iban; private BigDecimal balance; // Updated by event handlers; exposes read-optimized fields } ``` ```java class PaymentSaga implements Saga { // Coordinates multi-step payment flow spanning multiple aggregates } ``` -------------------------------- ### Define Aggregate Root with @AggregateRoot Source: https://context7.com/xmolecules/jmolecules/llms.txt Marks the root entity of a DDD aggregate. Changes within one aggregate are strongly consistent; cross-aggregate references use identifiers only. Requires imports for DDD annotations. ```java import org.jmolecules.ddd.annotation.*; // package-info.java in the banking domain @BoundedContext(name = "Banking", description = "Core banking operations") package com.acme.banking; // Clean domain class — no "Entity" or "AggregateRoot" suffix needed @AggregateRoot class BankAccount { @Identity final IBAN iban; private MonetaryAmount balance; private List transactions = new ArrayList<>(); BankAccount(IBAN iban, MonetaryAmount initialBalance) { this.iban = iban; this.balance = initialBalance; } void deposit(MonetaryAmount amount) { this.balance = balance.add(amount); this.transactions.add(Transaction.credit(amount)); } IBAN getIban() { return iban; } MonetaryAmount getBalance() { return balance; } } @ValueObject record IBAN(String value) { IBAN { if (value == null || !value.matches("[A-Z]{2}[0-9]{2}[A-Z0-9]{4,30}")) throw new IllegalArgumentException("Invalid IBAN: " + value); } } @ValueObject record MonetaryAmount(BigDecimal amount, Currency currency) { MonetaryAmount add(MonetaryAmount other) { if (!currency.equals(other.currency)) throw new IllegalArgumentException("Currency mismatch"); return new MonetaryAmount(amount.add(other.amount), currency); } } @Entity class Transaction { @Identity final UUID id = UUID.randomUUID(); final MonetaryAmount amount; final TransactionType type; private Transaction(MonetaryAmount amount, TransactionType type) { this.amount = amount; this.type = type; } static Transaction credit(MonetaryAmount amount) { return new Transaction(amount, TransactionType.CREDIT); } } @Repository class Accounts { private final Map store = new ConcurrentHashMap<>(); void save(BankAccount account) { store.put(account.getIban(), account); } Optional findByIban(IBAN iban) { return Optional.ofNullable(store.get(iban)); } } @Service class MoneyTransferService { private final Accounts accounts; void transfer(IBAN from, IBAN to, MonetaryAmount amount) { BankAccount source = accounts.findByIban(from) .orElseThrow(() -> new IllegalArgumentException("Account not found: " + from)); // ... debit source, credit target accounts.save(source); } } @Factory class BankAccountFactory { BankAccount openAccount(String rawIban, BigDecimal initialDeposit) { return new BankAccount(new IBAN(rawIban), new MonetaryAmount(initialDeposit, Currency.getInstance("EUR"))); } } ``` -------------------------------- ### Maven Dependency for jMolecules DDD Source: https://github.com/xmolecules/jmolecules/blob/main/readme.adoc Add the jMolecules DDD artifact as a Maven dependency to include its core functionalities in your project. ```xml org.jmolecules jmolecules-ddd 1.9.0 ``` -------------------------------- ### Define Custom Stereotype Annotation Source: https://github.com/xmolecules/jmolecules/wiki/The-Stereotype-Metamodel Use the @Stereotype meta-annotation to define a custom stereotype as an annotation. This allows it to be applied to classes, interfaces, or methods. ```java package com.acme.example.stereotypes; @org.jmolecules.Stereotype @Retention(RUNTIME) public @interface MyCustomStereotype { … } ``` -------------------------------- ### Mark Identity with @Identity Source: https://context7.com/xmolecules/jmolecules/llms.txt Marks a field or getter as the identity of an @AggregateRoot or @Entity. Used by integration tooling to map to primary keys. Requires DDD annotation imports. ```java import org.jmolecules.ddd.annotation.*; @AggregateRoot class Order { // Field-level identity @Identity private final OrderId id; @ValueObject record OrderId(UUID value) { static OrderId generate() { return new OrderId(UUID.randomUUID()); } } Order() { this.id = OrderId.generate(); } OrderId getId() { return id; } } @Entity class OrderLine { // Method-level identity private final UUID lineId = UUID.randomUUID(); @Identity UUID getLineId() { return lineId; } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.