skip to content

Precisely, which problem does all-open solve and which does no-arg solve? Map kotlin-spring and kotlin-jpa onto them.

level: middleimportance: must knowfreq 65%

answer

  1. all-open = subclassability (remove final)
  2. no-arg = instantiability (synthesize ctor)
  3. kotlin-spring → all-open for stereotypes
  4. kotlin-jpa → no-arg AND all-open for entities
  5. Entities need both effects

basics

~20 s

all-open removes 'final' so classes can be subclassed. no-arg adds an empty constructor so frameworks can create the object. kotlin-spring is an all-open preset for Spring; kotlin-jpa is a no-arg preset (plus all-open) for JPA entities.

solid answer

~40 s

Two orthogonal needs: **subclassability** and **instantiability**. `all-open` (kotlin-allopen) addresses subclassability — it makes annotated classes and their members `open` so Spring's CGLIB proxy subclasses and Hibernate's lazy-loading entity proxies can extend them. `no-arg` (kotlin-noarg) addresses instantiability — it synthesizes a non-public, synthetic zero-arg constructor so reflective frameworks (JPA/Hibernate, some serializers) can instantiate without you supplying default values. `kotlin-spring` = all-open preconfigured for Spring stereotypes (`@Component`, `@Configuration`, `@Transactional`, `@Async`, `@Cacheable`, `@SpringBootTest`). `kotlin-jpa` = no-arg preconfigured for `@Entity`/`@Embeddable`/`@MappedSuperclass`, **and** it also configures all-open for those same JPA annotations (Hibernate proxies entities for lazy loading). So entities typically need BOTH effects; kotlin-jpa delivers both for JPA annotations.

code

kotlin · 10 lines
kotlin
plugins {
    kotlin("plugin.spring")  // all-open: @Component/@Transactional/@Configuration -> open
    kotlin("plugin.jpa")     // no-arg + all-open for @Entity/@Embeddable/@MappedSuperclass
}

@Service               // -> open (kotlin-spring)
class PaymentService

@Entity                // -> open + synthetic Invoice() (kotlin-jpa)
class Invoice(@Id val id: Long, var amount: Long)

go deeper

for a junior

Can state all-open removes final and no-arg adds a constructor at a high level.

for a middle

Cleanly maps each plugin to subclassability vs. instantiability and names the presets and their trigger annotations.

for a senior

Explains why entities need both effects and that kotlin-jpa bundles all-open + no-arg for JPA annotations.

for a principal

Discusses minimizing plugin surface (only apply what a module needs) and the trade-offs of synthetic constructors leaking uninitialized state.

## Two independent axes Frameworks need two distinct things from your classes, and the two plugins map one-to-one onto them: | Need | Meaning | Plugin | Preset | |------|---------|--------|--------| | **Subclassability** | The class isn't `final`, so a subclass/proxy can be generated | `all-open` | `kotlin-spring`, and JPA part of `kotlin-jpa` | | **Instantiability** | A no-args constructor exists for reflective `newInstance` | `no-arg` | `kotlin-jpa` | ## all-open in detail The `all-open` plugin (Gradle id `org.jetbrains.kotlin.plugin.allopen`) takes a list of **trigger annotations**. Any class carrying one — directly or via **meta-annotation** (an annotation annotated by a trigger) — is compiled as `open`, along with its members. It does **not** add constructors and does **not** touch unannotated classes. `kotlin-spring` (`org.jetbrains.kotlin.plugin.spring`) is all-open with Spring's annotation set baked in. Because Spring stereotypes are meta-annotated (`@Service` is itself `@Component`), your custom `@Service` classes are covered transitively. ## no-arg in detail The `no-arg` plugin (`org.jetbrains.kotlin.plugin.noarg`) **synthesizes a zero-argument constructor**. Properties of that instance are uninitialized until the framework populates them via field access/reflection. The constructor is **synthetic** (invisible to normal code) so it can't be misused as a public API; an optional `invokeInitializers` flag can run `init {}` blocks. `kotlin-jpa` (`org.jetbrains.kotlin.plugin.jpa`) wires no-arg to JPA annotations **and** also makes those entity classes `open` (the JPA preset includes the all-open behavior for `@Entity`/`@Embeddable`/`@MappedSuperclass`). That's why applying just `kotlin-jpa` is usually enough for entities — they become both open and instantiable. ## Why entities need both ```kotlin @Entity class Order(@Id val id: Long, var total: BigDecimal) ``` - Hibernate **instantiates** `Order` reflectively → needs `no-arg`. - Hibernate returns a **lazy proxy subclass** of `Order` → needs the class `open` (all-open). ## Common confusion to avoid - all-open ≠ adds a constructor. - no-arg ≠ removes final. - They are separate plugins solving separate problems; the JPA preset just happens to bundle both effects for JPA annotations.

  • If a project uses Spring but NOT JPA, do you still need kotlin-jpa?
    No. kotlin-spring (all-open) suffices for beans. kotlin-jpa is only needed for JPA entities that require a synthesized no-args constructor.
  • Does kotlin-jpa also remove final from entities, or just add the constructor?
    Both — the JPA preset configures all-open for the JPA annotations in addition to no-arg, so entities become open AND get a no-args constructor.

saying these in an interview costs you the question

  • Saying all-open generates a constructor
  • Saying no-arg removes final
  • Claiming kotlin-jpa only adds a constructor and you still must apply all-open separately
  • Not realizing entities need both subclassability and instantiability
  • Treating the presets and the base plugins as unrelated

context