Transmission #057: Jersey items API wired from Dagger
Jersey’s default HK2 injector only knows how to build types it can resolve. ItemsApiImpl took a ItemRepository in its constructor; the repository is a Dagger @Singleton with DSLContext, not an HK2 binding, so HK2 failed with Could not find a suitable constructor.
Change: build ItemsApiImpl(itemRepository) inside AppModule.jerseyServer, pass it into JerseyResourceConfig, and register(itemsApiImpl) as an instance instead of register(ItemsApiImpl.class). JerseyServer now accepts the assembled JerseyResourceConfig.
Same pattern applies whenever a Jersey resource needs app dependencies: construct it in Dagger (or a @Provides factory) and register the instance; leave HK2 for no-arg stubs only.
Optional itemType on list items
listItems exposes itemType as an optional query parameter; when omitted, Jersey passes null. ItemTypeModelMapper.fromDTOToModel assumed a non-null DTO and NPE’d on dto.name(). ItemRepository.fetchAllItems already treats a null internal type as “no type filter,” so fromDTOToModel now returns null when the DTO is null—expected behavior for optional filters, not a silent bug to paper over only at the resource layer.
InternalItem timestamps from jOOQ
ItemModelMapper.fromEntityToModel did not set createdAt / updatedAt on InternalItem, so AutoValue’s builder failed at runtime. The jOOQ Item POJO already exposes LocalDateTime for created_at / updated_at; the mapper now fills Instant fields using atOffset(UTC) (same naive-timestamp convention as elsewhere unless we add explicit DB zone config).
List items JSON entity
listItems returned Response.ok(stream) with a Stream, so Jackson tried to bean-serialize the pipeline object (internal ReferencePipeline) instead of a JSON array of Item. Collect with Stream.toList() (or Collectors.toList()) before Response.ok so the entity is a List<Item>.
PDD: server integration tests (requirements)
Change: Extended PDD planning in .agents/planning/2026-04-29-server-integration-tests/ — idea-honing.md now records twelve requirements Q&A rounds for a future integrationTest Gradle source set: assume Compose already running; call Jersey/OpenAPI only; base URL from that source set’s application.properties, overridden by HELERION_JERSEY_BASE_URL then helerion.jersey.baseUrl; read-only Items behavior; manual runs until CI exists; full generated OpenAPI Java client from the same committed spec as the server; no auth for v1; @BeforeAll-style reachability check with an actionable failure message when the URL is down.
Why it matters: Implementation can follow a single written contract instead of re-deriving ports, surfaces, and generator scope from chat context.
PDD research: server integration tests
Change: Wrote research/existing-codebase-and-compose.md (Compose ports, JERSEY_PORT, @ApplicationPath("v1"), current jaxrs-spec Gradle flow, ItemsApiImpl read/404 behavior, OpenAPI spec resolution) and research/openapi-client-generation.md (second OpenAPI Generator task, java client vs jaxrs-spec, separate packages to avoid clashing with com.helerion.api, links to openapi-generator.tech).
Why it matters: The design step can reference concrete paths and a clear client-generation strategy instead of rediscovering Grizzly base URLs or reusing the wrong generator.
PDD design: server integration tests
Change: Added design/detailed-design.md — standalone spec for integrationTest (Gradle source set, second OpenAPI Generator java client under build/, com.helerion.integration.* packages, HelerionJerseyBaseUrl resolution HELERION_JERSEY_BASE_URL → -Dhelerion.jersey.baseUrl → application.properties, @BeforeAll connectivity messaging, Items-only read scenarios, mermaid build/runtime diagram, testing strategy and appendices).
Why it matters: Implementation can follow one document (requirements R1–R12 folded in) without re-reading the whole honing thread.
PDD implementation plan: server integration tests
Change: Added implementation/plan.md with a checklist (Steps 1–7 required, Step 8 optional doc) and numbered steps: Gradle source set + base URL resolution tests, OpenAPI java client generation under build/, reachability + message tests, then Items list / fetch / 404, optional invalid filter + README.
Why it matters: Gives an ordered, demoable sequence that matches the detailed design without orphan Gradle or generator wiring.
Server: Jersey integration tests implemented
Change: Added integrationTest source set and openApiGenerateIntegrationTestClient (OpenAPI java, library=native, output build/generated/openapi-integration-test, packages com.helerion.integration.client.*). Hand-written HelerionJerseyBaseUrl / JerseyReachability, ItemsApiIntegrationTest behind @Tag("live") (enabled with -Phelerion.integration.live so ./gradlew check / default integrationTest stay Compose-free). server/README.md documents the workflow; root README.md links to it. PDD folder gained summary.md.
Why it matters: Items contract against real Jersey is now repeatable without maintaining ad-hoc HTTP in tests, and local verification stays fast when Docker is down.
IDEA: integrationTest as test sources
Change: In server/build.gradle idea { module { ... } }, added testSources.from(.../src/integrationTest/java) and testResources.from(.../src/integrationTest/resources) so the Gradle IDEA model marks that tree as test roots (generated OpenAPI client stays on generatedSourceDirs only).
Why it matters: IntelliJ only auto-treats the built-in test source set as green test folders; custom integrationTest needs an explicit hint—after Reload All Gradle Projects (or ./gradlew idea if you use generated .iml), src/integrationTest/java shows as test sources.