...
Method
...
chaining
...
is
...
a
...
convenient
...
mechanism
...
that
...
allows
...
multiple
...
method
...
invocations
...
on
...
the
...
same
...
object
...
to
...
occur
...
in
...
a
...
single
...
statement.
...
A
...
method-chaining
...
implementation
...
consists
...
of
...
a
...
series
...
of
...
methods
...
that
...
return
...
the
...
this
...
reference.
...
This
...
implementation
...
allows
...
a
...
caller
...
to
...
invoke
...
methods
...
in
...
a
...
chain
...
by
...
performing
...
the
...
next
...
method
...
invocation
...
on
...
the
...
return
...
value
...
of
...
the
...
previous
...
method
...
in
...
the
...
chain.
...
While
...
the
...
methods
...
used
...
in
...
method
...
chaining
...
can
...
be
...
atomic,
...
the
...
chain
...
they
...
comprise
...
is
...
inherently
...
nonatomic.
...
Consequently,
...
callers
...
of
...
methods
...
that
...
are
...
involved
...
in
...
method
...
chaining
...
must
...
provide
...
sufficient
...
locking
...
to
...
guarantee
...
that
...
the
...
entire
...
chain
...
of
...
invocations
...
is
...
atomic,
...
as
...
shown
...
in
...
rule
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
Noncompliant Code Example
Method chaining is a useful design pattern for building an object and setting its optional fields. A class that supports method chaining provides several setter methods that each return the this
reference. However, if accessed concurrently, a thread may observe shared fields to contain inconsistent values. This noncompliant code example shows the JavaBeans pattern, which is not thread-safe.
Code Block | ||
---|---|---|
| ||
]. h2. Noncompliant Code Example Method chaining is a useful design pattern for building an object and setting its optional fields. A class that supports method chaining provides several setter methods that each return the {{this}} reference. However, if accessed concurrently, a thread may observe shared fields to contain inconsistent values. This noncompliant code example shows the JavaBeans pattern, which is not thread-safe. {code:bgColor=#FFcccc} final class USCurrency { // Change requested, denomination (optional fields) private int quarters = 0; private int dimes = 0; private int nickels = 0; private int pennies = 0; public USCurrency() {} // Setter methods public USCurrency setQuarters(int quantity) { quarters = quantity; return this; } public USCurrency setDimes(int quantity) { dimes = quantity; return this; } public USCurrency setNickels(int quantity) { nickels = quantity; return this; } public USCurrency setPennies(int quantity) { pennies = quantity; return this; } } // Client code: class exampleClientCode { private final USCurrency currency = new USCurrency(); // ... public exampleClientCode() { Thread t1 = new Thread(new Runnable() { @Override public void run() { currency.setQuarters(1).setDimes(1); } }); t1.start(); Thread t2 = new Thread(new Runnable() { @Override public void run() { currency.setQuarters(2).setDimes(2); } }); t2.start(); //... } } {code} |
The
...
JavaBeans
...
pattern
...
uses
...
a
...
no-argument
...
constructor
...
and
...
a
...
series
...
of
...
parallel
...
setter
...
methods
...
to
...
build
...
an
...
object.
...
This
...
pattern
...
is
...
not
...
thread-safe
...
and
...
can
...
lead
...
to
...
inconsistent
...
object
...
state
...
when
...
the
...
object
...
is
...
modified
...
concurrently.
...
In
...
this
...
noncompliant
...
code
...
example,
...
the
...
client
...
constructs
...
a
...
USCurrency
...
object
...
and
...
starts
...
two
...
threads
...
that
...
use
...
method
...
chaining
...
to
...
set
...
the
...
optional
...
values
...
of
...
the
...
USCurrency
...
object.
...
This
...
example
...
code
...
might
...
result
...
in
...
the
...
USCurrency
...
instance
...
being
...
left
...
in
...
an
...
inconsistent
...
state,
...
for
...
example,
...
with
...
two
...
quarters
...
and
...
one
...
dime
...
or
...
one
...
quarter
...
and
...
two
...
dimes.
Compliant Solution
This compliant solution uses the variant of the Builder pattern [Gamma 1995], suggested by Bloch [Bloch 2008], to ensure the thread-safety and atomicity of object creation.
Code Block | ||
---|---|---|
| ||
h2. Compliant Solution This compliant solution uses the variant of the Builder pattern \[[Gamma 1995|AA. References#Gamma 95]\], suggested by Bloch \[[Bloch 2008|AA. References#Bloch 08]\], to ensure the thread-safety and atomicity of object creation. {mc} What does this mean? It can be accessible to any number of threads ~DM => The method chaining is actually constrained to the {{USCurrency.Builder}} class which is only accessible from a single thread. {mc} {code:bgColor=#ccccff} final class USCurrency { private final int quarters; private final int dimes; private final int nickels; private final int pennies; public USCurrency(Builder builder) { this.quarters = builder.quarters; this.dimes = builder.dimes; this.nickels = builder.nickels; this.pennies = builder.pennies; } // Static class member public static class Builder { private int quarters = 0; private int dimes = 0; private int nickels = 0; private int pennies = 0; public static Builder newInstance() { return new Builder(); } private Builder() {} // Setter methods public Builder setQuarters(int quantity) { this.quarters = quantity; return this; } public Builder setDimes(int quantity) { this.dimes = quantity; return this; } public Builder setNickels(int quantity) { this.nickels = quantity; return this; } public Builder setPennies(int quantity) { this.pennies = quantity; return this; } public USCurrency build() { return new USCurrency(this); } } } // Client code: class exampleClientCode { private volatile USCurrency currency; // ... public exampleClientCode() { Thread t1 = new Thread(new Runnable() { @Override public void run() { currency = USCurrency.Builder.newInstance(). setQuarters(1).setDimes(1).build(); } }); t1.start(); Thread t2 = new Thread(new Runnable() { @Override public void run() { currency = USCurrency.Builder.newInstance(). setQuarters(2).setDimes(2).build(); } }); t2.start(); //... } } {code} The {{ |
The Builder.newInstance()
...
factory
...
method
...
is
...
called
...
with
...
any
...
required
...
arguments
...
to
...
obtain
...
a
...
Builder
...
instance.
...
The
...
optional
...
parameters
...
are
...
set
...
using
...
the
...
setter
...
methods
...
of
...
the
...
builder.
...
The
...
object
...
construction
...
concludes
...
with
...
the
...
invocation
...
of
...
the
...
build()
...
method.
...
This
...
pattern
...
makes
...
the
...
USCurrency
...
class
...
immutable
...
and
...
consequently
...
thread-safe.
...
Note
...
that
...
the
...
currency
...
field
...
cannot
...
be
...
declared
...
final
...
because
...
it
...
is
...
assigned
...
a
...
new
...
immutable
...
object.
...
It
...
is,
...
however,
...
declared
...
volatile
...
in
...
compliance
...
with
...
rule
...
...
...
...
...
...
...
...
...
...
.
...
When
...
input
...
must
...
be
...
validated,
...
ensure
...
that
...
the
...
values
...
are
...
defensively
...
copied
...
prior
...
to
...
validation.
...
(See
...
rule
...
...
...
...
...
...
...
...
...
...
for
...
more
...
information.)
...
The
...
Builder
...
class
...
also
...
complies
...
with
...
rule
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
because
...
it
...
maintains
...
a
...
copy
...
of
...
the
...
variables
...
defined
...
in
...
the
...
scope
...
of
...
the
...
containing
...
class.
...
The
...
private
...
members
...
within
...
the
...
nested
...
class
...
take
...
precedence
...
and,
...
as
...
a
...
result,
...
maintain
...
encapsulation.
...
Risk Assessment
Using method chaining in multithreaded environments without performing external locking can lead to nondeterministic behavior.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
VNA04-J | low | probable | medium | P4 | L3 |
Bibliography
[API 2006] |
|
Item 2, Consider a builder when faced with many constructor parameters |
...