Skip to content

Commit abfdd28

Browse files
drernieclaude
andauthored
Fix Jackson OffsetDateTime serialization for Nextflow 24.10+ (#321) (#322)
## Summary - Register `JavaTimeModule` and disable `WRITE_DATES_AS_TIMESTAMPS` on the `ObjectMapper` used by `writeMapToPackage`, so `java.time.OffsetDateTime` (returned by Nextflow 24.10+ `WorkflowMetadata.toMap()` for `start`/`complete`) serializes as ISO-8601 strings. - Add `jackson-datatype-jsr310:2.19.0` dependency to match the existing `jackson-databind` version. - Restore working test input package (`nf-core-gallery` was deleted; switched to `udp-spec/nf-quilt/source`). - Bump version to 0.9.2. ## Why Without the module registered, `toJson` threw `Java 8 date/time type java.time.OffsetDateTime not supported by default`. The exception was caught in `writeMapToPackage`, so the pipeline appeared to finish — but `nf-quilt/config.json`, `params.json`, and `workflow.json` were never written, producing packages with degraded metadata. Closes #321 ## Test plan - [x] Pipeline run produces all three JSONs in the published package — verified at `s3://udp-spec/nf-quilt/dest-0.9.2/nf-quilt/{config,params,workflow}.json` - [x] `start`/`complete` in `workflow.json` are ISO-8601 strings (e.g. `2026-04-29T08:09:29.334938-07:00`), not epoch decimals - [x] Existing test suite passes — all 10 CI jobs green (Linux/macOS/Windows × JDK 17/19/21) against pinned `NXF_VER=24.10.3` 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR fixes a Jackson serialization failure for `java.time.OffsetDateTime` values returned by Nextflow 24.10+ workflow metadata, which silently prevented `config.json`, `params.json`, and `workflow.json` from being written to published packages. The fix registers `JavaTimeModule` and disables `WRITE_DATES_AS_TIMESTAMPS` on the static `ObjectMapper`, adds the matching `jackson-datatype-jsr310:2.19.0` dependency, adds a targeted regression test, updates the test input package reference, and bumps the version to 0.9.2. <h3>Confidence Score: 5/5</h3> Safe to merge — the fix is correct, well-tested, and self-contained with no side effects on existing serialization behaviour. All changes are focused and correct: JavaTimeModule + disabling WRITE_DATES_AS_TIMESTAMPS is the standard Jackson pattern for ISO-8601 OffsetDateTime output; the dependency version matches jackson-databind; a regression test covers both the positive and negative cases; the previous thread's concern about WRITE_DATES_AS_TIMESTAMPS was already addressed in the current HEAD. No files require special attention. <h3>Important Files Changed</h3> | Filename | Overview | |----------|----------| | plugins/nf-quilt/src/main/nextflow/quilt/QuiltProduct.groovy | Registers JavaTimeModule and disables WRITE_DATES_AS_TIMESTAMPS on the static ObjectMapper to fix OffsetDateTime serialization; changes are correct and thread-safe. | | build.gradle | Adds jackson-datatype-jsr310:2.19.0 to match existing jackson-databind version; correct dependency for JavaTimeModule. | | plugins/nf-quilt/src/test/nextflow/quilt/QuiltProductTest.groovy | Adds a regression test for OffsetDateTime ISO-8601 serialization; checks both the positive (ISO string present) and negative (no numeric epoch for start key) cases. | | main.nf | Replaces deleted nf-core-gallery reference with udp-spec/nf-quilt/source package; removes unused params.hash variable. | | wf/main.gallery.nf | Deleted since it referenced the no-longer-available nf-core-gallery bucket. | | plugins/nf-quilt/src/resources/META-INF/MANIFEST.MF | Bumps Plugin-Version from 0.9.1 to 0.9.2; consistent with changelog and README-DEV updates. | </details> <h3>Sequence Diagram</h3> ```mermaid sequenceDiagram participant NF as Nextflow 24.10+ participant QP as QuiltProduct participant OM as ObjectMapper participant JTM as JavaTimeModule participant PKG as QuiltPackage NF->>QP: WorkflowMetadata.toMap()<br/>(start/complete as OffsetDateTime) QP->>OM: toJson(map) OM->>JTM: serialize(OffsetDateTime) JTM-->>OM: "2026-04-29T08:09:29.334938-07:00" OM-->>QP: JSON string (ISO-8601) QP->>PKG: writeMapToPackage(workflow.json) PKG-->>NF: Package published with metadata ``` <sub>Reviews (3): Last reviewed commit: ["address PR review feedback"](50c071d) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=30183248)</sub> <!-- /greptile_comment --> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 95e80d7 commit abfdd28

8 files changed

Lines changed: 31 additions & 35 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
# Changelog
22

3-
## [0.9.2] 2025-05-XX
3+
## [0.9.2] 2026-04-29
44

55
- Use "package" as default prefix
66
- Modernize main*.nf files
7+
- Fix Jackson serialization of `java.time.OffsetDateTime` from Nextflow 24.10+ workflow metadata (#321)
8+
- Restore working test input package (replace deleted `nf-core-gallery` with `udp-spec/nf-quilt/source`)
9+
- Remove `wf/main.gallery.nf` (referenced the deleted `nf-core-gallery` bucket)
710

811
## [0.9.1] 2024-12-24
912

README-DEV.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ From the command-line, do, e.g.:
1515

1616
```bash
1717
export LOG4J_DEBUG=true # for verbose logging
18-
export VERSION=0.9.1
18+
export VERSION=0.9.2
1919
export NXF_PLUGINS_TEST_REPOSITORY=https://github.com/quiltdata/nf-quilt/releases/download/$(VERSION)/nf-quilt-$(VERSION)-meta.json
2020
nextflow run main.nf -plugins nf-quilt@$(VERSION)
2121
```

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ allprojects {
101101
// see https://docs.gradle.org/4.1/userguide/dependency_management.html#sec:module_replacement
102102
implementation "org.${groovySource}.groovy:groovy-all:$groovyVersion"
103103
implementation 'com.fasterxml.jackson.core:jackson-databind:2.19.0'
104+
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.19.0'
104105
implementation 'com.upplication:s3fs:2.2.2'
105106

106107
modules {

main.nf

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
/* groovylint-disable CompileStatic */
33

44
nextflow.enable.dsl = 2
5-
params.hash = '90527238d0e2ebc9e1ba98265e5f79440b557697fed3f0d29ec95942cbb4e4e0'
6-
params.input = "quilt+s3://nf-core-gallery#package=test/observer@${params.hash}&catalog=demo.quiltdata.com"
5+
params.input = 'quilt+s3://udp-spec#package=nf-quilt/source@c4e44f6932'
76
params.outdir = '/var/tmp'
87

98
process transfer {

plugins/nf-quilt/src/main/nextflow/quilt/QuiltProduct.groovy

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ package nextflow.quilt
1717

1818
import com.fasterxml.jackson.databind.ObjectMapper
1919
import com.fasterxml.jackson.databind.ObjectWriter
20+
import com.fasterxml.jackson.databind.SerializationFeature
21+
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
2022
import nextflow.quilt.jep.QuiltPackage
2123
import nextflow.quilt.jep.QuiltParser
2224
import nextflow.quilt.nio.QuiltPath
@@ -97,6 +99,8 @@ ${nextflow}
9799
]
98100

99101
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
102+
.registerModule(new JavaTimeModule())
103+
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
100104
private static final ObjectWriter OBJECT_WRITER = OBJECT_MAPPER.writerWithDefaultPrettyPrinter()
101105
static String toJson(Object value) {
102106
String result = OBJECT_WRITER.writeValueAsString(value)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Manifest-Version: 1.0
22
Plugin-Class: nextflow.quilt.QuiltPlugin
33
Plugin-Id: nf-quilt
4-
Plugin-Version: 0.9.1
4+
Plugin-Version: 0.9.2
55
Plugin-Provider: Quilt Data
66
Plugin-Requires: >=24.10.0
77

plugins/nf-quilt/src/test/nextflow/quilt/QuiltProductTest.groovy

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import nextflow.quilt.jep.QuiltPackage
2828
import java.nio.file.Files
2929
import java.nio.file.Path
3030
import java.nio.file.Paths
31+
import java.time.OffsetDateTime
32+
import java.time.ZoneOffset
3133
import groovy.transform.CompileDynamic
3234
import spock.lang.Ignore
3335
import spock.lang.IgnoreIf
@@ -95,6 +97,23 @@ class QuiltProductTest extends QuiltSpecification {
9597
product.displayName().replace('%2f', '/') == testURI
9698
}
9799

100+
void 'toJson serializes OffsetDateTime as ISO-8601 string'() {
101+
// Regression test for #321: Nextflow 24.10+ returns OffsetDateTime
102+
// for workflow start/complete; without JavaTimeModule + disabling
103+
// WRITE_DATES_AS_TIMESTAMPS, Jackson would either throw or emit
104+
// a numeric epoch like 1.735040400E9.
105+
given:
106+
OffsetDateTime when = OffsetDateTime.of(2026, 1, 2, 3, 4, 5, 0, ZoneOffset.UTC)
107+
Map map = [start: when, complete: when]
108+
109+
when:
110+
String json = QuiltProduct.toJson(map)
111+
112+
then:
113+
json.contains('"2026-01-02T03:04:05Z"')
114+
!(json =~ /"start"\s*:\s*[0-9]/)
115+
}
116+
98117
void 'should generate solid string for timestamp from now'() {
99118
when:
100119
def now = QuiltProduct.now()

wf/main.gallery.nf

Lines changed: 0 additions & 30 deletions
This file was deleted.

0 commit comments

Comments
 (0)