Lombok: [BUG] @Jacksonized does not copy @JacksonXmlElementWrapper to @Builder

Created on 23 Nov 2020  路  9Comments  路  Source: projectlombok/lombok

The @Jacksonized annotation says it "copies Jackson-related configuration annotations from the class to the builder class"

This works with @JsonProperty and @JsonXmlProperty, but unfortunately it does not work with @JsonXmlElementWrapper

All 9 comments

JacksonXmlElementWrapper is indeed missing in the list of copyable annotations. JacksonXmlText is probably also relevant.

I noticed that lombok.copyableAnnotations has an effect but it's not mentioned in the doc of either Jacksonize nor SuperBuilder. But it puts annotations on setter parameters instead of setter methods and I'm not sure if that's always appropriate.

I noticed that lombok.copyableAnnotations has an effect but it's not mentioned in the doc of either Jacksonize nor SuperBuilder. But it puts annotations on setter parameters instead of setter methods and I'm not sure if that's always appropriate.

The copyable annotations features is global for lombok, it should presumably be documented at the lombok.config feature page, perhaps, but it isn't. We should address that :)

@janrieke So, we just add com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper and com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText? Maybe we should also toss in JacksonXmlProperty and JacksonXmlRootElement as well (the other 2 annotations in that package, as per javadoc of jackson-dataformat-xml v2.2.0).

Or is that going to lead to issues and we shuold copy this only with @(Super)Builder?

JacksonXmlProperty should already be in the list. JacksonXmlRootElement is only relevant for serialization, as far as I understand its docs and XML with jackson.

So I think it's just JacksonXmlElementWrapper and JacksonXmlText that should be added.

I seem to be having issues with custom annotations marked with @JacksonAnnotationsInside as well.
What I tried:
In dir src/main/java/lomboktest
lombok.config

lombok.copyableAnnotations +=  lomboktest.TestAnnotation

TestAnnotation.java

package lomboktest;

import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.annotation.JsonProperty;

import javax.annotation.meta.TypeQualifierDefault;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@TypeQualifierDefault({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonProperty("test")
public @interface TestAnnotation {
}

And TestPojo.class

package lomboktest;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Value;
import lombok.experimental.SuperBuilder;
import lombok.extern.jackson.Jacksonized;

@Value
@Jacksonized
@SuperBuilder
public class TestPojo {

    @TestAnnotation
    String someField;

    @JsonProperty("second_field")
    String text;

}

As described in https://github.com/rzwitserloot/lombok/issues/2042, after compilation I expected the annotation to show up in my generated builder class, but there I only found

public B someField(@TestAnnotation String someField) {
            this.someField = someField;
            return this.self();
        }

        @JsonProperty("second_field")
        public B text(String text) {
            this.text = text;
            return this.self();
        }

What am I doing wrong here?

Nothing. It's simply not supported. lombok.copyableAnnotations only configures what Lombok copies to the method parameter. Copying to the method can not be configured. It only works for well-known Jackson annotations because those are hardcoded.

Copying annotations is complex: Should it be copied to the method? To the parameter? For constructors? Setters? Getters? Builder set methods?
Allowing all this to be configured would be incredibly complex both to use and to maintain in Lombok.

Solution: Customize your builder class and manually add the annotation (via interface or by manually adding the setter method).

The @JacksonXmlElementWrapper should be in the copy list of @Jacksonized with the rest of the other XML annotations. They are necessary if one is using Jackson for XML.

Customizing the builder class and adding the annotation is a huge amount of boilerplate as the

<versions>
  <version>1.0.0</version>
  <version>1.1.0</version>
</versions>

wrapper constructs are rather common.

Wouldn't it be possible to instead of hardcoding a set of annotations, use something like org.reflections:reflections library to find every @JacksonAnnotation and @JacksonAnnotationsInside to create a list to replace the hard-coded list of supported annotations? I would be happy to attempt it and create a MR

No, because Lombok does its work only during an early phase of the compilation. There is no classpath or even knowledge about other classes at that time. Lombok decides what to copy simply by looking at the names of the annotations.

Was this page helpful?
0 / 5 - 0 ratings