// LEARNINGCOLLECTIONAPI — ENGINEERING REPORT

Kotlin 2.3.20 · Spring Boot 4.0.4 · Spring Data JPA + Spring Data REST · MySQL · QueryDSL 5.1.0 · SpringDoc OpenAPI 1.8.0 · Gradle 9.4.1 · JDK 17 · backing service for the zsh-learn plugin

Docs

>_EXECUTIVE SUMMARY

LearningCollectionAPI is a Kotlin / Spring Boot REST service that persists “learnings” — short notes / vocabulary cards — into MySQL, and serves them back for search and quiz. It is the HTTP backing store for the zsh-learn shell plugin. The data model is a single JPA entity (LearningCollection: id, learning, category, dateAdded). The interface is split across one hand-written controller (ten GET endpoints tuned for shell calls) and the Spring Data REST auto-generated CRUD surface under /learning.

The codebase is deliberately small — 6 main Kotlin files totalling 147 LOC — but carries a disproportionately large test suite: 23 test files, 6,155 LOC, 128 test methods (118 @Test + 10 @ParameterizedTest). The test-to-main LOC ratio is roughly 42:1, covering controller routes, the entity schema, repository contracts, CORS config, serialization, edge cases, idempotency, stress, and property-based fuzzing.

1
REST controller
10
GET endpoints
1
JPA entity
1
Repository
6
Main .kt files
147
Main LOC
23
Test .kt files
6,155
Test LOC
128
Test methods
4
Entity fields
2
Derived queries
8080
Default port

~REST SURFACE

Ten @GetMapping handlers on a single @RestController. Every operation is a GET — query param (/add, /filter) or path variable ({count}) — so the zsh-learn plugin can call them with a bare curl. “Text only” responses return just the learning strings; “full” responses return complete records.

MethodPathHandlerBehavior
GET/addaddPersists a new learning (category "programming", dateAdded now); returns the saved entity.
GET/filterfilterLearnSubstring search (findAllByLearningContaining); returns matching text.
GET/recentslearningItemRecentShortDefaultLast 20 (SHORT_CNT) learnings, text only.
GET/recents/{count}getLearningItemRecentShortLast {count} learnings, text only.
GET/recent/{count}getLearningItemRecentLast {count} learnings, full records.
GET/randomlearningItemOne random learning, full record.
GET/randomslearningItemCountShortOne random learning, text only.
GET/randoms/{count}getLearningItemCountShort{count} random learnings, text only.
GET/random/{count}getLearningItemCount{count} random learnings, full records.
GET/dumpgetDumpStreams mysqldump --extended-insert=FALSE root to the response writer.

Recency = findAll().reversed() (newest-inserted first); randomness = findAll().shuffled(). Both load the full table into memory before slicing — acceptable at the personal-collection scale this serves.


$DATA MODEL

A single entity, LearningCollection (@Table(name = "LearningCollection")), implementing Serializable. Four columns, IDENTITY-generated primary key.

FieldKotlin typeJPA annotationPurpose
idLong@Id @GeneratedValue(strategy = IDENTITY)Auto-increment PK.
learningString@ColumnThe learning content.
categoryString@ColumnDefaults to "programming" on create.
dateAddedjava.util.Date@ColumnCreation timestamp (Date()).

LCRepo extends CrudRepository<LearningCollection, Long> and declares two derived query methods: findAllByLearningContaining (used by /filter) and findAllByCategoryContaining (exposed via Spring Data REST search, not wired to a controller route). The @RepositoryRestResource(path = "learning") annotation auto-publishes full CRUD under /learning.


%SOURCE INVENTORY

Six main Kotlin files under src/main/kotlin/com/menketechnologies/learningcollection/, totalling 147 LOC.

FileRole
LearningCollectionApplication.kt@SpringBootApplication bootloader with main entrypoint.
LearningController.kt@RestController — the 10 @GetMapping endpoints; @Autowired LCRepo.
LearningCollection.kt@Entity — the 4-field schema, two constructors, serialVersionUID.
LCRepo.ktCrudRepository + @RepositoryRestResource; 2 derived query methods.
Consts.ktTop-level constants: SHORT_CNT, DB_NAME, DEFAULT_CAT, DUMP.
WebConfig.ktWebMvcConfigurer + RepositoryRestConfigurer — opens CORS on /** for both layers.

!TEST COVERAGE

23 test files, 6,155 LOC, 128 test methods (118 @Test + 10 @ParameterizedTest), run on JUnit 5 (useJUnitPlatform) with kotlin-test-junit5, spring-boot-starter-test, and mockito-kotlin. The suite is far larger than the production code it exercises — controller, entity, repository, and config each carry multiple dedicated test classes.

AreaTest files
ControllerLearningControllerTest, LearningControllerBoundaryTest, LearningControllerCombinationTest, LearningControllerDataFlowTest, LearningControllerEndpointMatrixTest, LearningControllerErrorPathTest, LearningControllerIdempotencyTest, LearningControllerRouteContractTest, LearningControllerStressTest
EntityLearningCollectionTest, LearningCollectionContractTest, LearningCollectionEdgeCaseTest, LearningCollectionInvariantTest, LearningCollectionPropertyTest, LearningCollectionSchemaContractTest, LearningCollectionSerializationTest
RepositoryLCRepoContractTest
Config / constantsConstsTest, ConstsExtendedTest, WebConfigTest, WebConfigExtendedTest
ApplicationLearningCollectionApplicationTests, LearningCollectionApplicationEntryTest

Per the README, the suite spans unit tests, integration tests, boundary analysis, stress tests, serialization checks, property-based fuzzing, repository contracts, idempotency checks, and application-entry tests. Run with ./gradlew test.


&DEPENDENCY MANIFEST

From build.gradle.kts. Spring Boot version is managed by the org.springframework.boot plugin (4.0.4) plus io.spring.dependency-management (1.1.7); unversioned starters inherit from the BOM.

DependencyVersionScope
spring-boot-starter-data-jpa(BOM) 4.0.4implementation
spring-boot-starter-data-rest(BOM) 4.0.4implementation
jackson-module-kotlin(BOM)implementation
kotlin-reflect2.3.20implementation
querydsl-jpa / querydsl-apt5.1.0implementation
springdoc-openapi-ui / springdoc-openapi-data-rest1.8.0implementation
lombok(BOM)compileOnly + annotationProcessor
mysql-connector-j(BOM)runtimeOnly
kotlin-test-junit52.3.20testImplementation
spring-boot-starter-test(BOM)testImplementation
mockito-kotlin6.3.0testImplementation
junit-platform-launcher(BOM)testRuntimeOnly

Kotlin plugins: jvm, plugin.spring, plugin.jpa (all 2.3.20). Compiler arg -Xjsr305=strict. allOpen opens @Entity / @MappedSuperclass / @Embeddable classes for JPA proxying. Java toolchain pinned to 17.


@RUNTIME & PERSISTENCE

From src/main/resources/application.properties.

SettingValue
Datasource URLjdbc:mysql://localhost:3306/root?useUnicode=true&serverTimezone=UTC&…
Usernameroot
Password(empty)
show-sqlfalse
Naming strategyPhysicalNamingStrategyStandardImpl
HTTP port8080 (Spring Boot default)

/PROJECT METADATA

ItemValue
Group / versioncom.menketechnologies / 0.0.1-SNAPSHOT
Root projectlearningcollection
Language / runtimeKotlin 2.3.20 on JVM (JDK 17 toolchain)
FrameworkSpring Boot 4.0.4 (Data JPA + Data REST)
Build systemGradle 9.4.1 (wrapper)
AuthorMenkeTechnologies
Repositorygithub.com/MenkeTechnologies/LearningCollectionAPI
Issuesgithub.com/MenkeTechnologies/LearningCollectionAPI/issues
UmbrellaMenkeTechnologiesMeta
Docs homemenketechnologies.github.io/LearningCollectionAPI