OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
22.01k stars 6.6k forks source link

[BUG] @Valid TYPE_USE bean validation annotation on builder causes issues on JBoss EAP 7.4 #19188

Open jpraet opened 4 months ago

jpraet commented 4 months ago
Description

Similar to https://github.com/OpenAPITools/openapi-generator/issues/17875. The applied fix does not entirely solve the issue.

Related to #17874, the @Valid bean validation annotation also gets added on TYPE_USE in the builder.

  public static PartnersRestBuilder<?, ?> builder() {
    return new PartnersRestBuilderImpl();
  }

  private static class PartnersRestBuilderImpl extends PartnersRestBuilder<PartnersRest, PartnersRestBuilderImpl> {

    @Override
    protected PartnersRestBuilderImpl self() {
      return this;
    }

    @Override
    public PartnersRest build() {
      return new PartnersRest(this);
    }
  }

  public static abstract class PartnersRestBuilder<C extends PartnersRest, B extends PartnersRestBuilder<C, B>>  {
    private List<@Valid PartnerRest> items = new ArrayList<>();
    private Integer total;
    protected abstract B self();

    public abstract C build();

    public B items(List<@Valid PartnerRest> items) {
      this.items = items;
      return self();
    }
    public B total(Integer total) {
      this.total = total;
      return self();
    }
  }
}
PartnersRest.java ```java package be.fgov.kszbcss.tad.admin.rest.model; import be.fgov.kszbcss.tad.admin.rest.model.PartnerRest; import com.fasterxml.jackson.annotation.JsonTypeName; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.io.Serializable; import javax.validation.constraints.*; import javax.validation.Valid; import java.util.Objects; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.annotation.JsonTypeName; @JsonTypeName("Partners") @javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaJAXRSSpecServerCodegen", date = "2024-07-17T13:55:57.807731525+02:00[Europe/Brussels]", comments = "Generator version: 7.7.0") public class PartnersRest implements Serializable { private @Valid List<@Valid PartnerRest> items = new ArrayList<>(); private Integer total; protected PartnersRest(PartnersRestBuilder b) { this.items = b.items; this.total = b.total; } public PartnersRest() { } /** **/ public PartnersRest items(List<@Valid PartnerRest> items) { this.items = items; return this; } @JsonProperty("items") @NotNull @Valid public List<@Valid PartnerRest> getItems() { return items; } @JsonProperty("items") public void setItems(List<@Valid PartnerRest> items) { this.items = items; } public PartnersRest addItemsItem(PartnerRest itemsItem) { if (this.items == null) { this.items = new ArrayList<>(); } this.items.add(itemsItem); return this; } public PartnersRest removeItemsItem(PartnerRest itemsItem) { if (itemsItem != null && this.items != null) { this.items.remove(itemsItem); } return this; } /** **/ public PartnersRest total(Integer total) { this.total = total; return this; } @JsonProperty("total") public Integer getTotal() { return total; } @JsonProperty("total") public void setTotal(Integer total) { this.total = total; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } PartnersRest partners = (PartnersRest) o; return Objects.equals(this.items, partners.items) && Objects.equals(this.total, partners.total); } @Override public int hashCode() { return Objects.hash(items, total); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class PartnersRest {\n"); sb.append(" items: ").append(toIndentedString(items)).append("\n"); sb.append(" total: ").append(toIndentedString(total)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } public static PartnersRestBuilder builder() { return new PartnersRestBuilderImpl(); } private static class PartnersRestBuilderImpl extends PartnersRestBuilder { @Override protected PartnersRestBuilderImpl self() { return this; } @Override public PartnersRest build() { return new PartnersRest(this); } } public static abstract class PartnersRestBuilder> { private List<@Valid PartnerRest> items = new ArrayList<>(); private Integer total; protected abstract B self(); public abstract C build(); public B items(List<@Valid PartnerRest> items) { this.items = items; return self(); } public B total(Integer total) { this.total = total; return self(); } } } ```

This somehow causes an issue on JBoss EAP 7.4.

I guess the presence of the @Valid annotation causes the container to treat the builder as a CDI bean?

Before https://github.com/OpenAPITools/openapi-generator/pull/18724:

org.jboss.weld.exceptions.DeploymentException: WELD-001503: Bean class which has interceptors cannot be declared final:  class be.fgov.kszbcss.tad.admin.rest.model.PartnersRest$PartnersRestBuilderImpl

After https://github.com/OpenAPITools/openapi-generator/pull/18724 (which attempted to fix the issue by making the builder class non-final):

org.jboss.weld.exceptions.DeploymentException: WELD-001436: Type be.fgov.kszbcss.tad.admin.rest.model.PartnersRest$PartnersRestBuilderImpl is not proxyable because it has a private constructor [EnhancedAnnotatedConstructorImpl] private be.fgov.kszbcss.tad.admin.rest.model.PartnersRest$PartnersRestBuilderImpl() - class be.fgov.kszbcss.tad.admin.rest.model.PartnersRest$PartnersRestBuilderImpl.""
openapi-generator version

OK in 7.1.0, broken from 7.2.0 onward.

jflabatBCSS commented 2 months ago

We are also affected by this issue with JBoss EAP 7.4 and are staying on 7.1.0 for this reason.

jpraet commented 2 months ago

What is the purpose of these bean validation annotations on the builder class? I don't think they are needed. The builder is instantiated with a static method call to the .builder() method, so there's no way for the bean validation runtime to enforce these constraints anyway?

I could try to make a PR to remove them, and revert #18724 as that didn't fix the issue.