graphql-java-codegen
graphql-java-codegen copied to clipboard
Make constructors private when generateBuilder is true
When safely evolving schema (adding optional fields) the constructor signatures change for model classes, which breaks binary compatibility between generated client versions since the constructors are public. If constructors could be made private when builder class generation is used, this would remove a key area of binary incompatibility between generated java model classes.
Sketch:
public class Product {
private final String brand;
private Product(String brand) {
this.brand = brand;
}
/*equals hashcode etc.*/
public static Builder builder() { return new Product.Builder(); }
public static class Builder {
private String brand;
public Builder() {}
public setBrand(String brand) {
this.brand = brand;
return this;
}
}
}
The following change produces the desired result:
diff --git a/src/main/resources/templates/java-lang/type.ftl b/src/main/resources/templates/java-lang/type.ftl
index 23a501e..a447c8f 100644
--- a/src/main/resources/templates/java-lang/type.ftl
+++ b/src/main/resources/templates/java-lang/type.ftl
@@ -50,11 +50,11 @@ public class ${className} implements java.io.Serializable<#if implements?has_con
</#list>
</#if>
- public ${className}() {
+ <#if builder>private<#else>public</#if> ${className}() {
}
<#if fields?has_content>
- public ${className}(<#list fields as field>${field.type} ${field.name}<#if field_has_next>, </#if></#list>) {
+ <#if builder>private<#else>public</#if> ${className}(<#list fields as field>${field.type} ${field.name}<#if field_has_next>, </#if></#list>) {
<#list fields as field>
this.${field.name} = ${field.name};
</#list>
To avoid breaking existing clients of this library we would need to introduce a new property, something like generatePrivateConstructor
(default: false).