Java 와 Kotlin
language = 'kotlin' 은 같은 모델을 src/main/kotlin 의 Kotlin 엔티티·서비스·컨트롤러로 생성하고, 고른 번들의
-kt 판(jpa-springboot-kt, ddd-springboot-kt, hexagonal-springboot-kt)을 씁니다. 규칙은 같고, 각 언어가 그것을
말하는 방식만 다릅니다.
build.gradle
elasticore {
architecture = 'hexagonal'
language = 'kotlin' // java | kotlin
}
두 언어의 같은 생명주기
Kotlin 예제의 Ticket 은 생명주기가 둘이고, cancel 명령이 둘을 함께 바꿉니다:
blueprint/shop/model/ticket.yml (elasticore-template-kt)
Ticket:
meta: entity @root @expose(20) @owner(agentId) @access(read=owner, create=user, close=owner) @event(Closed) -- 작업
- Kotlin (생성)
- Java (같은 규칙)
TicketBase.kt
open fun cancel() {
requireStatus("cancel", TicketStatus.OPEN)
requireBilling("cancel", BillingStatus.UNBILLED)
this.status = TicketStatus.CLOSED
this.billing = BillingStatus.VOID
raiseClosed()
}
/** Whether cancel may be given now: the status is OPEN and the billing is UNBILLED. */
fun canCancel(): Boolean = (this.status == TicketStatus.OPEN) && (this.billing == BillingStatus.UNBILLED)
ShipmentBase.java (DSL 가이드의 예)
public void cancel() {
requireStatus("cancel", ShipmentStatus.READY); // 1) 모든 생명주기를 먼저 확인
requireFee("cancel", FeeStatus.PAID);
this.status = ShipmentStatus.CANCELLED; // 2) 모두 통과해야 함께 이동
this.fee = FeeStatus.REFUNDED;
raiseCancelled(); // 3) 도착 상태마다 같은 이름의 @event 발행
raiseRefunded();
}
무엇이 다른가
| Java | Kotlin | |
|---|---|---|
| 이벤트 클래스 | 필드 + 생성자 + 게터 | 주 생성자의 val (data class) |
| 명세 클래스 | private 생성자 | object |
| 팩토리 | private 생성자 + static | object + fun |
| 도메인 서비스·프로세스 매니저의 포트 | XxxBase 의 @Autowired protected 필드 | @Autowired protected lateinit var |
| 조건식 | order.getItems() | order.items!! |
| 불변식 리스너 | @EntityListeners({A.class, B.class}) | @EntityListeners(A::class, B::class) |
| 값 객체 | Lombok 으로 불변 | 언어로 불변 |
| 잠긴 setter | @Setter(AccessLevel.PROTECTED) | protected set / final var ... private set |
| 시그니처 | 서비스와 널 허용까지 맞춤 (save(dto: OrderDTO): OrderDTO?) |
한 언어에만 있는 규칙은 자기 언어를 말하고(requireSyntax), 다른 언어에서 선택되면 이유와 함께 그 자리에서 멈춥니다 -
.kt 파일에 Java 가 조용히 들어가는 일은 없습니다.
Kotlin 빌드에 필요한 것
Kotlin JPA 프로젝트가 쓰는 플러그인들입니다. elasticore-template-kt 와 같습니다(이 예제는 저장소 안에서
io.elasticore 플러그인을 가져오고, 프로젝트는 릴리스 버전을 적습니다):
build.gradle
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.9.24'
id 'org.jetbrains.kotlin.plugin.allopen' version '1.9.24'
id 'org.jetbrains.kotlin.plugin.jpa' version '1.9.24'
id 'io.spring.dependency-management' version '1.1.6'
id 'io.elasticore' version '3.0.261022-rc1'
}
org.jetbrains.kotlin:kotlin-reflect- Spring 을 쓰는 Kotlin 앱에 필요합니다.- Spring Boot 4 이면 Kotlin 2.2 이상, Jackson Kotlin 모듈은
tools.jackson.module:jackson-module-kotlin. - 생성 코드는
kotlin-spring플러그인 없이도 기동합니다: 확장 서비스와 리포지터리 어댑터는open class, 엔티티 컬렉션은MutableList<X>입니다. mapping: xml(JPA 어노테이션을orm.xml로)을 쓰면io.elasticore.springboot3.entity.PersistentModel을allOpen과noArg에 등록합니다.`in`- 헥사고날 패키지adapter.in.web은 예약어를 감싸 씁니다.
언어마다 닿는 것
대부분의 규칙은 두 언어 모두에 닿습니다. @search(like) 는 모든 Kotlin 빌드(그리고 v3 Java 번들)에서 대소문자를
무시합니다. @restExclude 는 Kotlin 의 컨트롤러와 유스케이스에서 메서드를 빼고, Kotlin 서비스는 그대로 둡니다.
예제: elasticore-template-kt -
빌드마다 생성·컴파일·기동합니다(ShopApiContractTest).