[ https://issues.apache.org/jira/browse/GROOVY-10955?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Paul King closed GROOVY-10955. ------------------------------ > @Builder doesn't work on records > -------------------------------- > > Key: GROOVY-10955 > URL: https://issues.apache.org/jira/browse/GROOVY-10955 > Project: Groovy > Issue Type: Bug > Reporter: Paul King > Assignee: Paul King > Priority: Major > Fix For: 4.0.10 > > > For this code: > {code} > import groovy.transform.builder.* > @Builder > record Developer(Integer id, String first, String last, String email, > List<String> skills) { } > Developer.builder().id(2).build() > {code} > The code fails in the {{build}} method. It is meant to create a new Developer > but instead creates a DeveloperBuilder instance and then throws a cast > exception: > {noformat} > org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast > object 'Developer$DeveloperBuilder@5ef26266' with class > 'Developer$DeveloperBuilder' to class 'Developer' > ... > at Developer$DeveloperBuilder.build(ConsoleScript25) > {noformat} > I wasn't necessarily expecting it to work. It could be made to work or we > could explicitly disable it for records. > Similarly, this code fails: > {code} > @Builder(builderStrategy=InitializerStrategy) > record Developer(Integer id, String first, String last, String email, > List<String> skills) { } > Developer.createInitializer().id(2).build() > {code} > with this more obscure error: > {noformat} > java.lang.ArrayIndexOutOfBoundsException: Internal compiler error while > compiling ConsoleScript26 > Method: > org.codehaus.groovy.ast.MethodNode@7cd420f9[Developer$DeveloperInitializer > id(java.lang.Integer) from Developer$DeveloperInitializer] > Line -1, expecting casting to > Developer$DeveloperInitializer<groovy.transform.builder.InitializerStrategy$SET, > T1, T2, T3, T4> but operand stack is empty > ... > at > org.codehaus.groovy.classgen.asm.OperandStack.doConvertAndCast(OperandStack.java:340) > at > org.codehaus.groovy.classgen.asm.StatementWriter.writeReturn(StatementWriter.java:593) > at > org.codehaus.groovy.classgen.AsmClassGenerator.visitReturnStatement(AsmClassGenerator.java:822) > ... > {noformat} > I would probably just used the named args style rather than a builder, e.g.: > {code} > var dev1 = new Developer(id: 1, first: 'Dan', last: 'Vega', email: > 'danv...@gmail.com', skills: ['Java', 'Spring']) > assert dev1.with{ [id, first, last, email, skills] } == > // [1, 'Dan', 'Vega', 'danv...@gmail.com', ['Java', 'Spring']] > {code} > But we should either support or disable one or more of the @Builder > strategies. > Builder can also be written on constructors. That does work for the default > strategy but again not for the InitializerStrategy. Here is a working example: > {code} > import groovy.transform.builder.* > record Developer(Integer id, String first, String last, String email, > List<String> skills) { > @Builder > Developer(Integer id, String full, String email, List<String> skills) { > this(id, full.split(' ')[0], full.split(' ')[1], email, skills) > } > } > var dev1 = new Developer(id: 1, first: 'Dan', last: 'Vega', email: > 'danv...@gmail.com', skills: ['Java', 'Spring']) > assert dev1.with{ [id, first, last, email, skills] } == > [1, 'Dan', 'Vega', 'danv...@gmail.com', ['Java', 'Spring']] > var dev2 = Developer.builder().id(2).full('Paul > King').email('pa...@apache.org').skills(['Java', 'Groovy']).build() > assert dev2.with{ [id, first, last, email, skills] } == > [2, 'Paul', 'King', 'pa...@apache.org', ['Java', 'Groovy']] > {code} -- This message was sent by Atlassian Jira (v8.20.10#820010)