Skip to content

Conversation

@cmoulliard
Copy link

@cmoulliard cmoulliard commented Jan 15, 2026

What's changed?

I included part of the MavenSettings and RawRepositories java classes the missing constructors required by jackson when we bump jackson from 2.17 to >= 2.19 to avoid the deserialization issue with HttpHeader and Property

	@JsonCreator
	public MavenSettings(@JsonProperty("localRepository") @Nullable String localRepository,
			@JsonProperty("profiles") @Nullable Profiles profiles,
			@JsonProperty("activeProfiles") @Nullable ActiveProfiles activeProfiles,
			@JsonProperty("mirrors") @Nullable Mirrors mirrors,
			@JsonProperty("servers") @Nullable Servers servers) {

The MavenSettingsTest is again failing but not because there is deserialization issue using 2.17 or 2.20 but instead because we got a null HttpHeader object vs X-JFrog-Art-Api when rewrite is processing it !!

❯ gradle :rewrite-maven:test --tests "org.openrewrite.maven.MavenSettingsTest
MavenSettingsTest > serverHttpHeaders() FAILED
    org.opentest4j.AssertionFailedError: 
    expected: "X-JFrog-Art-Api"
     but was: null
        at app//org.openrewrite.maven.MavenSettingsTest.serverHttpHeaders(MavenSettingsTest.java:958)

MavenSettingsTest > canDeserializeSettingsCorrectly() FAILED
    org.assertj.core.error.AssertJMultipleFailuresError: 
    Multiple Failures (1 failure)
    -- failure 1 --
    Expecting value to be true but was false
    at MavenSettingsTest.lambda$canDeserializeSettingsCorrectly$22(MavenSettingsTest.java:998)
        at app//org.openrewrite.maven.MavenSettingsTest.canDeserializeSettingsCorrectly(MavenSettingsTest.java:998)

Hopefully, the following TestCase where we only use jackson works with 2.17 or 2.20

❯ gradle :rewrite-maven:test --tests "org.openrewrite.maven.MavenSettingsWithServerHttpHeaderParsedByJacksonTest"

Checklist

  • I've added unit tests to cover both positive and negative cases
  • I've read and applied the recipe conventions and best practices
  • I've used the IntelliJ IDEA auto-formatter on affected files

@cmoulliard
Copy link
Author

I was able to reproduce the new error.
There are no errors when the parsing of the Settings XML is done using this code

        XmlMapper m = new XmlMapper();
        MavenSettings settings = m.readValue(settingsXml, MavenSettings.class);

        Assertions.assertNotNull(settings.getServers());
        MavenSettings.Server server = settings.getServers().getServers().getFirst();

        Assertions.assertNotNull(server.getConfiguration().getHttpHeaders());
        assertThat(server.getConfiguration().getHttpHeaders().getFirst().getName()).isEqualTo("X-JFrog-Art-Api"); // OK

but well using the Rewrite XML parser config

XMLInputFactory input = new WstxInputFactory();
        input.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
        input.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, false);
        XmlFactory xmlFactory = new XmlFactory(input, new WstxOutputFactory());

        ObjectMapper m = XmlMapper.builder(xmlFactory)
          .constructorDetector(ConstructorDetector.USE_PROPERTIES_BASED)
          .enable(FromXmlParser.Feature.EMPTY_ELEMENT_AS_NULL)
          .defaultUseWrapper(false)
          .build()
          .registerModule(new ParameterNamesModule())
          .disable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)
          .disable(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)
          .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        m.setVisibility(m.getSerializationConfig().getDefaultVisibilityChecker()
            .withFieldVisibility(JsonAutoDetect.Visibility.NONE)
            .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
            .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
            .withCreatorVisibility(JsonAutoDetect.Visibility.PUBLIC_ONLY))
          .registerModule(new JavaTimeModule())
          .registerModule(new MavenXmlMapper.StringTrimModule());

        MavenSettings settings = m.readValue(settingsXml, MavenSettings.class);

        Assertions.assertNotNull(settings.getServers());
        MavenSettings.Server server = settings.getServers().getServers().getFirst();

        Assertions.assertNotNull(server.getConfiguration().getHttpHeaders());
        assertThat(server.getConfiguration().getHttpHeaders().getFirst().getName()).isEqualTo("X-JFrog-Art-Api"); // NOK as null

@cmoulliard
Copy link
Author

cmoulliard commented Jan 16, 2026

We can fix the issue reported part of this PR if we change from "false" to "true" the value of the .defaultUseWrapper(true) of the XmlMapper.Builder but by doing that we will get this jackson error:

no String-argument constructor/factory method to deserialize from String 

StacktTrace

       Caused by:
       at org.openrewrite.maven.AddDependencyTest.addTestDependenciesAfterCompile(AddDependencyTest.java:531)
       ...
        java.io.UncheckedIOException: Failed to parse pom: Cannot construct instance of `org.openrewrite.maven.internal.RawPom$Dependency` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('commons-lang')
         at [Source: (org.openrewrite.internal.EncodingDetectingInputStream); line: 7, column: 34] (through reference chain: org.openrewrite.maven.internal.RawPom["dependencies"]->org.openrewrite.maven.internal.RawPom$Dependencies["dependency"]->java.util.ArrayList[0])
            at app//org.openrewrite.maven.internal.RawPom.parse(RawPom.java:162)
            at app//org.openrewrite.maven.MavenParser.parseInputs(MavenParser.java:75)
            ... 3 more

            Caused by:
            com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `org.openrewrite.maven.internal.RawPom$Dependency` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('commons-lang')
             at [Source: (org.openrewrite.internal.EncodingDetectingInputStream); line: 7, column: 34] (through reference chain: org.openrewrite.maven.internal.RawPom["dependencies"]->org.openrewrite.maven.internal.RawPom$Dependencies["dependency"]->java.util.ArrayList[0])
                at app//com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)

           AddDependencyTest > addScopedDependency(String) > [1] scope=provided FAILED
               org.opentest4j.AssertionFailedError: [Unexpected result in "project/pom.xml":
               diff --git a/project/pom.xml b/project/pom.xml
               index 01a8359..ae86eeb 100644
               --- a/project/pom.xml
               +++ b/project/pom.xml
               @@ -3,7 +3,9 @@
                    <artifactId>my-app</artifactId>
                    <version>1</version>
                    <dependencies>
               -        <dependency>
               +        <!--~~(Unable to download POM: com.fasterxml.jackson.core:jackson-core:2.12.0. Tried repositories:
               +https://repo.maven.apache.org/maven2: Failed to parse pom: Cannot construct instance of `org.openrewrite.maven.internal.RawPom$License` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('The Apache Software License, Version 2.0')
               + at [Source: (ByteArrayInputStream); line: 22, column: 53] (through reference chain: org.openrewrite.maven.internal.RawPom["licenses"]->org.openrewrite.maven.internal.RawPom$Licenses["license"]->java.util.ArrayList[0]))~~>--><dependency>

@cmoulliard
Copy link
Author

There is still an issue as this test fails

MavenSettingsTest
    @Test
    // Test is failing as no <property> encapsulates <name> and <value>
    void canDeserializeSettingsCorrectly() throws Exception {

as the html generated dont include <property>

We got

<settings>
            <servers>
              <server>
                <id>maven-snapshots</id>
                <configuration>
                  <httpHeaders>
                      <name>X-JFrog-Art-Api</name>
                      <value>myApiToken</value>
                  </httpHeaders>
                  <timeout>10000</timeout>
                </configuration>
              </server>
            </servers>
          </settings>

instead of

<settings>
            <servers>
              <server>
                <id>maven-snapshots</id>
                <configuration>
                  <httpHeaders>
                    <property>
                      <name>X-JFrog-Art-Api</name>
                      <value>myApiToken</value>
                    </property>
                  </httpHeaders>
                  <timeout>10000</timeout>
                </configuration>
              </server>
            </servers>
          </settings>

@cmoulliard cmoulliard removed their assignment Jan 16, 2026
@cmoulliard
Copy link
Author

I created a simple jackson project to reproduce the issue: https://github.com/ch007m/maven-settings-httpheader-issue/

public class MavenSettings {
@Nullable
String localRepository;
public String localRepository;
Copy link
Member

Choose a reason for hiding this comment

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

Is it absolutely necessary to make these fields public?
I'd prefer not to expose these fields to recipe authors directly.

Copy link
Author

Choose a reason for hiding this comment

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

Fixed with a488b96

public class MavenSettings {
@Nullable
String localRepository;
private String localRepository;
Copy link
Member

Choose a reason for hiding this comment

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

Originally we had these without a modifier, instead relying on @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)

Suggested change
private String localRepository;
String localRepository;

Copy link
Author

Choose a reason for hiding this comment

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

It is still there within the header class definition

@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@ToString(onlyExplicitlyIncluded = true)
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Data
@AllArgsConstructor
@JacksonXmlRootElement(localName = "settings")
public class MavenSettings {

cmoulliard and others added 10 commits January 20, 2026 16:05
…onfiguration./httpHeaders element. openrewrite#4803

Signed-off-by: Charles Moulliard <[email protected]>
…sWithServerHttpHeaderParsedByJacksonTest.java

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…settings.xml parsed is null using ObjectMapper code of rewrite-maven

Signed-off-by: Charles Moulliard <[email protected]>

# Conflicts:
#	rewrite-maven/src/test/java/org/openrewrite/maven/MavenSettingsWithServerHttpHeaderParsedByJacksonTest.java
…lse to true the value of the .defaultUseWrapper(true) of the XmlMapper.Builder value of the .defaultUseWrapper(true) of the XmlMapper.Builder

Signed-off-by: Charles Moulliard <[email protected]>
…rror: no String-argument constructor/factory method to deserialize from String

Signed-off-by: Charles Moulliard <[email protected]>
…Failed to read /var/temp/xxx/settings.xml

Signed-off-by: Charles Moulliard <[email protected]>
…ize or deserialize serverconfigurayion with Timeout or HttpHeaders by removing lombok and using plain java code

Signed-off-by: Charles Moulliard <[email protected]>
@timtebeek timtebeek marked this pull request as draft January 20, 2026 19:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

2 participants