Using forEach to set more than one property.

101 views
Skip to first unread message

m.ugues

unread,
Sep 19, 2011, 9:46:55 AM9/19/11
to lambdaj
Hallo all.
Is it possible use the forEach to set more then one property on the
list of objects?

Imagine that I have this use case:

Collection<ContrattoRapporto> contrattiRapportiToUpdate =
select(contrattiRapporti,
having(on(ContrattoRapporto.class).getFlagRapportoBloccato(),
anyOf(equalTo(false), equalTo(null))));

forEach(contrattiRapportiToUpdate).setFlagRapportoBloccato(true);
forEach(contrattiRapportiToUpdate).setDataBlocco(Calendar.getInstance());
forEach(contrattiRapportiToUpdate).setDataAggiornamento(Calendar.getInstance());

Obviously this works great, but I think this could be a forcing.
Maybe the enhanced loop is more correct in this use case.

What do you think about?

Massimo

Mario Fusco

unread,
Sep 19, 2011, 11:11:59 AM9/19/11
to lam...@googlegroups.com
Hi Massimo,

if your beans have a fluent interface lambdaj should support it without any problem. Let me make a concrete example. If the setFlagRapportoBloccato would be implemented as it follows:

public ContrattoRapporto setFlagRapportoBloccato(boolean flag) {
    this.flag = flag;
    return this;
}

you could do for instance something like:

contratto.setFlagRapportoBloccato(true).setDataBlocco(Calendar.getInstance());

If your beans are made in this way, lambdaj allows you to manipulate collection of them in the same way:

forEach(contrattiRapportiToUpdate).setFlagRapportoBloccato(true).setDataBlocco(Calendar.getInstance());

Don't forget that at compile time what the forEach() returns is an object of the same class of the method invoked after the forEach() itself. So if your setter returns void, there is nothing you can invoke on it, but if it returns the object itself you can keep invoking other methods on it and lambdaj will propagate this invocation to each bean of the underlying collection as usual.

I hope this help, and mostly makes sense, but if you have some doubts or even better any suggestion to improve it feel free to write again.
Anyway let me know if it works.

Cheers,
Mario

m.ugues

unread,
Sep 20, 2011, 4:23:43 AM9/20/11
to lambdaj
Thank's Mario, now that my domain implements the fluent interface it
works.

A little OT.
Is a best practice to implement in every domain model the fluent
interface? What do you think about it? Should it be a convention like
the javabeans spec?
Kind regards

Massimo

Mario Fusco

unread,
Sep 20, 2011, 2:05:27 PM9/20/11
to lam...@googlegroups.com
Massimo,

Personally I like to use fluent interface APIs as much as possible, but I believe it's just a matter of tastes and many couldn't agree with me. I think there are some cases (e.g. when implementing a factory) where it's very handy and makes your code more readable.

However be aware that there is also at least one big drawback: what I suggested in my former email is NOT complaint with the Java Beans specification, so if you try to use a bean implemented in that way with some of the most common Java frameworks there's a big likelihood that it won't work.

Bye,
Mario

Mattias Jiderhamn

unread,
Sep 21, 2011, 3:02:09 AM9/21/11
to lam...@googlegroups.com
I think it should also be noted that each method call on the forEach()
collection will still cause another iteration, rather than all the
chained calls being invoked on each object in a single iteration, which
will give worse performance than a regular for loop.

An alternative syntax, that possibly clarifies this, would be
ContrattoRapporto allContrattoRapporto =
forEach(contrattiRapportiToUpdate); // Create proxy
allContrattoRapporto.setFlagRapportoBloccato(true);
allContrattoRapporto.setDataBlocco(Calendar.getInstance());
allContrattoRapporto.setDataAggiornamento(Calendar.getInstance());

An idea for LambdaJ would be to be able to put method calls in a queue
on the proxy, which is then executed on each object.
Possible syntax; fluent:

performForEach(prepareForEach(contrattiRapportiToUpdate).setFlagRapportoBloccato(true).setDataBlocco(Calendar.getInstance()).setDataAggiornamento(Calendar.getInstance()));
and bean style:
ContrattoRapporto allContrattoRapporto =
prepareForEach(contrattiRapportiToUpdate); // Create proxy
allContrattoRapporto.setFlagRapportoBloccato(true); // Put in queue
allContrattoRapporto.setDataBlocco(Calendar.getInstance()); // Put in
queue
allContrattoRapporto.setDataAggiornamento(Calendar.getInstance()); //
Put in queue
performForEach(allContrattoRapporto); // Execute queue

</Mattias>

----- Original Message -----
Subject: Re: Using forEach to set more than one property.
Date: Tue, 20 Sep 2011 20:05:27 +0200
From: Mario Fusco <mario...@gmail.com>

...

Reply all
Reply to author
Forward
0 new messages