Skip to content

CAMEL-24620: Add support to enable/disable features from DatatypeFeature enums - #26103

Open
graben wants to merge 1 commit into
apache:mainfrom
graben:CAMEL-24620
Open

CAMEL-24620: Add support to enable/disable features from DatatypeFeature enums#26103
graben wants to merge 1 commit into
apache:mainfrom
graben:CAMEL-24620

Conversation

@graben

@graben graben commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

data formats are special and options must be defined in the model so its confirgurable via the DSLs

@graben

graben commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

@davsclaus : I can't see a corresponding model class that would be affected?

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seconding the existing CHANGES_REQUESTED review — the core issue is that every data format option must be configured via the model, and this PR bypasses that contract.

Specifically:

  1. enableFeature(Enum<? extends DatatypeFeature>) / disableFeature(Enum<? extends DatatypeFeature>) are Java-only convenience methods. They are not exposed in JsonDataFormat (in core/camel-core-model), so there is no way to configure DateTimeFeature, EnumFeature, or JsonNodeFeature through the YAML/XML DSLs or from the component endpoint URI. Data formats in Camel must be configurable solely through the model — if it isn't in the model, it effectively doesn't exist for most users.

  2. The generic Enum<? extends DatatypeFeature> parameter type is also inconsistent with the existing overloads (enableFeature(SerializationFeature), enableFeature(DeserializationFeature), enableFeature(MapperFeature)) which all use concrete enum types.

Required changes:

  • Update JsonDataFormat in core/camel-core-model to expose the new feature types (ideally as dedicated enableDateTimeFeatures, enableEnumFeatures, enableJsonNodeFeatures String properties — similar to how enableFeatures handles SerializationFeature/DeserializationFeature/MapperFeature)
  • Wire those model properties through the configurer so they reach AbstractJacksonDataFormat at runtime
  • The doEnableFeatures() / doDisableFeatures() extension to resolve the new enum names (the bulk of the diff) is a good foundation — just needs to be driven from model-level properties

Also a minor test issue:


template.send("direct:unformat", exchange -> exchange.getIn().setBody(new Date(123)));

mock.expectedMessageCount(1);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expectedMessageCount should be set before template.send(), not after. As written, the message can arrive and be recorded before the latch is initialised, making the assertion non-deterministic.

Suggested change
mock.expectedMessageCount(1);
mock.expectedMessageCount(1);
mock.message(0).body().isEqualTo("123");
template.send("direct:unformat", exchange -> exchange.getIn().setBody(new Date(123)));

@davsclaus

Copy link
Copy Markdown
Contributor

To clarify the model requirement from the previous review:

The new feature types (DateTimeFeature, EnumFeature, JsonNodeFeature) need their own dedicated @Metadata-annotated properties in the data format model (e.g. enableDateTimeFeatures, enableEnumFeatures, enableJsonNodeFeatures as String fields in AbstractJacksonDataFormat following the same pattern as enableFeatures/disableFeatures).

Since these are Jackson 3 specific (these DatatypeFeature subtypes don't exist in Jackson 2 or other JSON libraries), any shared model that also covers other JSON data formats would need excludeProperties entries to suppress these new options there.

The doEnableFeatures()/doDisableFeatures() extension is the right runtime wiring — it just needs to be driven from model properties, not only from the Java convenience methods.

Claude Code on behalf of davsclaus

@graben

graben commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Well, I see those new methods as convient methods for Jackson only. They are implemented like the three original methods which aren't reflected by model class, too, because they are not generic.

The test method might be problematic, like all test cases in that class! But I can fix them all. :-)

I think the most common way to configure this json dataformat is using the String method disable/enableFeatures which is only enhanced by this PR. So no need for a model change.

It's up to you if I should change also legacy code to make it complete.

@davsclaus

Copy link
Copy Markdown
Contributor

You're right — no model change is needed. The existing enableFeatures/disableFeatures String properties already do the job, since doEnableFeaures() and doDisableFeatures() resolve feature names by string. The new typed Java overloads are pure compile-time convenience that ultimately write into those same fields.

Here is what I'd like to see added to the test to demonstrate that the model path works end-to-end (this is the style that YAML/XML DSL users will rely on):

@Test
public void testEnableDatatypeFeatureViaModelString() throws Exception {
    MockEndpoint mock = getMockEndpoint("mock:result-model");
    mock.expectedMessageCount(1);
    mock.message(0).body().isEqualTo("123");

    template.send("direct:unformat-model", exchange -> exchange.getIn().setBody(new Date(123)));

    mock.assertIsSatisfied();
}

With a corresponding route using setEnableFeatures (the DSL/YAML-friendly model property):

JacksonDataFormat formatModel = new JacksonDataFormat();
formatModel.setEnableFeatures("WRITE_DATES_AS_TIMESTAMPS");

from("direct:unformat-model").marshal(formatModel).to("mock:result-model");

Also please fix the mock ordering in the existing and new tests — expectedMessageCount must be set before template.send(), not after:

// Correct ordering:
MockEndpoint mock = getMockEndpoint("mock:result");
mock.expectedMessageCount(1);
mock.message(0).body().isEqualTo("123");

template.send(...);

mock.assertIsSatisfied();

Also please update the Javadoc on setEnableFeatures and setDisableFeatures to mention the newly supported types (DateTimeFeature, EnumFeature, JsonNodeFeature) so users know they can pass these names as strings in YAML/XML DSL too.

Claude Code on behalf of davsclaus

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants