@Setter with chaining support?!

161 views
Skip to first unread message

Stefano IceCubeR

unread,
Nov 17, 2009, 9:08:01 AM11/17/09
to Project Lombok
Hi to all i'm Stefano From Bologna, Italy and i'd like to ask/propose
a feature..

i think is useful to have chaining support on setter, i mean:

obj.setFoo("Foo").setBar("Bar").setDummy("dummy")

is it possible right now? is in future plan? it will break the Bean
specifications?

Bye & compliments!

P.S. i'm a Groovy fan and i love to see these features in java too!!!

Reinier Zwitserloot

unread,
Nov 17, 2009, 1:04:15 PM11/17/09
to Project Lombok
So, we like chaining. In fact, your post pushed us over the edge, and
we decided we were going to add it. But, unfortunately, I have bad
news. We can't.

According to chapter 7.1 of de beanspec (first hit when you google for
that), the signature for a setter MUST include the 'void' return type
part.

To go the extra mile, we checked the source of
java.beans.Introspector. On line 560:
} else if (resultType == void.class && name.startsWith
(SET_PREFIX)) {

So, returning self will actively break beanspec. Now, beanspec is not
particularly relevant in this day and age, but:

- We want to introduce the builder pattern. This will give you
chainable object creation. The generated builder code can of course
only create new objects, it can not mutate existing ones, so for the
cases where you want to chainable-set an already existing object, this
won't help you.

- We may introduce a @Chainable annotation, which does not do
anything by itself, but will treat the method as if it returned self
by calling code. Of course, this means the CALLING code needs to be
written and compiled on a lombok-ified eclipse/javac, which is not
currently how lombok works, so we're not 100% sold on this idea. It
DOES match up nicely with varargs (which works in exactly the same
fashion; the signature contains an array and just a flag that says:
"Callers, please rewrite multiple arguments in this position into a
new array literal").

- If you have existing code that contains getters and setters, you
can then not replace them with lombok @Setter annotations, as you'll
break binary compatibility (the signatures of the set method won't
match - so you'd have to recompile everything, which is not a feasible
option if you're writing a library that is used by other parties).
Furthermore, because the fact that lombok's setters would be chainable
isn't immediately obvious, people WILL make this mistake and then
wonder why their old class files no longer work with their new library
release. That would be bad.

- It would not be written anywhere and it isn't nearly as immediately
obvious that lombok's @Setter would generate a chainable version. In
particular, some confusion could arise in that it can also be seen as
reasonable that the setter is returning the previous value. In case a
class contains a field of its own type, that would create confusion.
It would also be rather confusing for the people who DO use the
beanspec (and I hear some ORM products do use it) that @Setter creates
setters that don't actually work with it. They won't realize why until
they notice in their overviews that lombok's setters appear to be
returning self.



These 2 negatives + 2 planned future expansions means that @Setter is
better off remaining in its current unchainable form.


We'll get a proof of concept @Chainable going when we get @Delegate
(which is near the top of the future plans list!) - we need
introspection at the transformation step to write it, which lombok
currently does not have in eclipse. @Setter will of course mark all
the setters it makes as Chainable.


Sorry to disappoint all of you :( - We wish there was a nice solution
somehow. We thought of adding parameters to @Data and @Setter but that
feels like we would be heading to the path of sticking 50 parameters
on @Setter, which is not where we want to go.

Michael Lorton

unread,
Nov 17, 2009, 1:08:58 PM11/17/09
to project...@googlegroups.com
More proof of the old adage: "Programming is like sex; one little mistake and you support it for the rest of its life."

M.

On Tue, Nov 17, 2009 at 10:04 AM, Reinier Zwitserloot <rein...@gmail.com> wrote:

So, we like chaining. In fact, your post pushed us over the edge, and
we decided we were going to add it. But, unfortunately, I have bad
news. We can't.

According to chapter 7.1 of de beanspec (first hit when you google for
that), the signature for a setter MUST include the 'void' return type
part.

To go the extra mile, we checked the source of
java.beans.Introspector. On line 560:
    } else if (resultType == void.class && name.startsWith
(SET_PREFIX)) {

So, returning self will actively break beanspec.]

Nick Stolwijk

unread,
Nov 17, 2009, 6:09:26 PM11/17/09
to project...@googlegroups.com
Another option I like is chaining like new Person().name("John
Doe").age(15).favoriteDrink("Beer");

So creating methods like:

public Person name(String name) {
this.name = name;
return this;
}

This won't break the bean spec and gives nicer code imho.

With regards,

Nick Stolwijk
~Java Developer~

IPROFS BV.
Claus Sluterweg 125
2012 WS Haarlem
http://www.iprofs.nl
> --~--~---------~--~----~------------~-------~--~----~
> You received this message because you are subscribed to the Google
> Groups group for http://projectlombok.org/
>
> To post to this group, send email to project...@googlegroups.com
> To unsubscribe from this group, send email to
> project-lombo...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/project-lombok?hl=en
> -~----------~----~----~----~------~----~------~--~---
>
>

Reinier Zwitserloot

unread,
Nov 18, 2009, 2:29:19 AM11/18/09
to Project Lombok
Yes, absolutely, and the getters should probably also be named just
'name()', that seems to be the more prevalent "fluent" style. We won't
at all mind doing this, but what are the annotations going to be
called? It can't be @Setter, and it can't be @Data, because we want to
keep the parameter lists on each low.

@FluentData, @FluentSetter and @FluentGetter?

On Nov 18, 12:09 am, Nick Stolwijk <nick.stolw...@gmail.com> wrote:
> Another option I like is chaining like new Person().name("John
> Doe").age(15).favoriteDrink("Beer");
>
> So creating methods like:
>
> public Person name(String name) {
>   this.name = name;
>   return this;
>
> }
>
> This won't break the bean spec and gives nicer code imho.
>
> With regards,
>
> Nick Stolwijk
> ~Java Developer~
>
> IPROFS BV.
> Claus Sluterweg 125
> 2012 WS Haarlemhttp://www.iprofs.nl
>
>
>
> On Tue, Nov 17, 2009 at 7:08 PM, Michael Lorton <mich...@circuspop.com> wrote:
> > More proof of the old adage: "Programming is like sex; one little mistake
> > and you support it for the rest of its life."
>
> > M.
>
> > On Tue, Nov 17, 2009 at 10:04 AM, Reinier Zwitserloot <reini...@gmail.com>
> > wrote:
>
> >> So, we like chaining. In fact, your post pushed us over the edge, and
> >> we decided we were going to add it. But, unfortunately, I have bad
> >> news. We can't.
>
> >> According to chapter 7.1 of de beanspec (first hit when you google for
> >> that), the signature for a setter MUST include the 'void' return type
> >> part.
>
> >> To go the extra mile, we checked the source of
> >> java.beans.Introspector. On line 560:
> >>     } else if (resultType == void.class && name.startsWith
> >> (SET_PREFIX)) {
>
> >> So, returning self will actively break beanspec.]
>
> > --~--~---------~--~----~------------~-------~--~----~
> > You received this message because you are subscribed to the Google
> > Groups group forhttp://projectlombok.org/

Michael Lorton

unread,
Nov 18, 2009, 12:04:33 PM11/18/09
to project...@googlegroups.com
Wow, I've been programming in Java since it was called Oak and I never noticed that this would work:

class jj {
 private int x;
 public jj x(int x) { this.x = x; return this; }
 public int x() {  return this.x; }
 public static void main(String ... args) {
    jj jj = new jj();
    jj.x(3);
    System.out.println(jj.x());
 }
}

Saves three letters, looks cool, let's go for it.

M.

--
Reply all
Reply to author
Forward
0 new messages