Idea for @Builder extension

361 views
Skip to first unread message

PeterL

unread,
Mar 16, 2015, 6:14:46 PM3/16/15
to project...@googlegroups.com
It would be nice to have a version of a builder that accepts an instance of the object of a same class and acts as a copy constructor first, then builder methods can be used to customize the final instance.

E.g.

typical builder:

MyObject obj = MyObjectBuilder.builder().name("N").age(123).build();

and a copy constructor style one:

MyObject sourceObj = ...//constructed in some way with name="N1" and age=123

MyObject modifiedCopy = MyObjectBuilder.builder(sourceObj).name("N2").build(); // copy has name="N2" and age=123

This is useful when you have the objects with a long list of properties and need to create a copy that just differs in one field value.

Martin Treurnicht

unread,
Mar 18, 2015, 10:48:33 AM3/18/15
to project...@googlegroups.com
I think a fundamental part of using builders is to have default values for properties on the builder. This is almost a must in my mind. I found this ticket because i actually wanted to log the exact same issue.

The information in this message may be proprietary and/or confidential, and protected from disclosure. If the reader of this message is not the intended recipient, or an employee or agent responsible for delivering this message to the intended recipient, you are hereby notified that any dissemination, distribution or copying of this communication is strictly prohibited. If you have received this communication in error, please notify Gyft immediately by replying to this message and deleting it from your computer.
Message has been deleted

Francis Lalonde

unread,
Mar 19, 2015, 11:04:15 AM3/19/15
to project...@googlegroups.com
There are various ways someone might want to customize builders and I dont think it is lombok's purpose to define them all.

The mechanism I read somewhere and now use for default properties is to define my own builder method. I change the name of the lombok generated builder to something like "unsafeBuilder" using the @Builder annotation parameters, and define my own static builder() method which call the unsafe one and sets the default values before returning the builder object.

@Builder(builderMethodName = "unsafeBuilder")
public class Blah {
...
    public static BlahBuilder builder() {
        return unsafeBuilder().prop1("
safeDefaultValue").prop2("safeDefaultValue");
    }

I've found this to be clean and very workable. I would use the same pattern for a copy builder, which I would name seomthing like buildFrom(Object source), and copy the original values to the unsafe builder before returning it.

@Builder(builderMethodName = "unsafeBuilder")
public class Blah {
...
    public static BlahBuilder buildFrom(Blah source) {
        return unsafeBuilder().prop1(source.getProp1()).prop2(source.getProp2);
    }

Reinier Zwitserloot

unread,
May 15, 2015, 6:33:02 AM5/15/15
to project-lombok
@Builder is a thing you put on static methods, not on classes. For a copy constructor kind of deal to function, we need to be able to extract the value for all of the parameters of the static method annotated with @Builder from some provided instance.

This is not possible.

But we can try: we would have to state that we just call getFoo(), or possibly foo(), depending on Accessors conf, for the parameter named 'foo', and its on you to ensure that this method (A) exists, (B) has no args, and (C) has an appropriate returntype.

The nice upside is that it'll "just work out" if you @Builder @Value class Foo { justSomeFieldsHere;}. Mostly. We'll have to put in some extra effort for @Singular.




 --Reinier Zwitserloot

--
You received this message because you are subscribed to the Google Groups "Project Lombok" group.
To unsubscribe from this group and stop receiving emails from it, send an email to project-lombo...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tristan

unread,
Jul 2, 2015, 12:44:43 PM7/2/15
to project...@googlegroups.com
I would love to see this added to @Builder. I've run into this use case a couple of times and always end up having to map everything by hand (or use a mapping framework).

-Tristan

Nathan Glass

unread,
Aug 5, 2015, 10:35:03 PM8/5/15
to Project Lombok
+1 - particularly with heavy @Value use. I see the same kinds of bugs around hand-maintained Builder.copy() methods that I used to see around non-Lombok equals() and hashCode().

I'm going to take a crack at this.

...he says, foolishly, before having looked at a single line of source code.

Roel Spilker

unread,
Aug 5, 2015, 10:41:52 PM8/5/15
to project...@googlegroups.com

Well, we're about to release a solution for this. Please have a look at the builderClone branch

Nathan Glass

unread,
Aug 5, 2015, 11:30:51 PM8/5/15
to Project Lombok
Thanks for the heads up. @ObtainVia is a neat way to work with imperfect param names. I had bungled my way through a javac implementation of <Type>Builder.copy(<Type> other) (as opposed to instanceOf<Type>.toBuilder()) today, without @Singular support. Let's just say I'm glad I don't have to finish ;) Though I have to say, this was an uncommonly enjoyable sojourn in to Somebody Else's Code.

If you don't mind answering, what motivated the refactors in the @Singular code?

Also, any reason I shouldn't give this branch a try tomorrow?
Reply all
Reply to author
Forward
0 new messages