Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #23508 > unrolled thread
| Started by | markspace <markspace@nospam.nospam> |
|---|---|
| First post | 2013-04-18 12:16 -0700 |
| Last post | 2013-04-24 10:28 -0300 |
| Articles | 5 — 3 participants |
Back to article view | Back to comp.lang.java.programmer
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: DI/wiring markspace <markspace@nospam.nospam> - 2013-04-18 12:16 -0700
Re: DI/wiring Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2013-04-22 09:03 +0200
Re: DI/wiring markspace <markspace@nospam.nospam> - 2013-04-22 10:59 -0700
Re: DI/wiring Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2013-04-24 06:37 +0200
Re: DI/wiring Arved Sandstrom <asandstrom2@eastlink.ca> - 2013-04-24 10:28 -0300
| From | markspace <markspace@nospam.nospam> |
|---|---|
| Date | 2013-04-18 12:16 -0700 |
| Subject | Re: DI/wiring |
| Message-ID | <kkpgls$6aq$1@dont-email.me> |
On 4/18/2013 9:03 AM, Stefan Ram wrote:
> I have »invented« myself something that also seems to be
> known as »dependency injection« or »wiring«. I am doing it
I should have a look at Joerg's answer myself, but here's another idea.
Make an app context object that holds the state of your app.
class Context {
Engine getEngine()....
Printer getPrinter()...
}
Inject that into submodules in the code. Submodules are larger than
classes and can treat the context as immutable. The context then
becomes global but only for that module. The idea is that you still get
dependency injecting, but you can still test reasonably as well.
class SomeConfig {
Context context;
public SomeConfig( Context c ) { context = c; }
public init() {
Component c0 = new Component( context );
...
}
}
class Component {
Context context;...
public printIt() {
context.getPrinter().do something...
}
}
This reduces boilerplate but doesn't eliminate it. For some projects it
might be better to get a real dependency injection framework.
[toc] | [next] | [standalone]
| From | Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> |
|---|---|
| Date | 2013-04-22 09:03 +0200 |
| Message-ID | <kl2n6i$3l5$1@dont-email.me> |
| In reply to | #23508 |
On 18/04/2013 21:16, markspace allegedly wrote:
> On 4/18/2013 9:03 AM, Stefan Ram wrote:
>> I have »invented« myself something that also seems to be
>> known as »dependency injection« or »wiring«. I am doing it
>
> I should have a look at Joerg's answer myself, but here's another idea.
>
> Make an app context object that holds the state of your app.
>
> class Context {
> Engine getEngine()....
> Printer getPrinter()...
> }
>
> Inject that into submodules in the code. Submodules are larger than
> classes and can treat the context as immutable. The context then
> becomes global but only for that module. The idea is that you still get
> dependency injecting, but you can still test reasonably as well.
>
> class SomeConfig {
> Context context;
> public SomeConfig( Context c ) { context = c; }
>
> public init() {
> Component c0 = new Component( context );
>
> ....
> }
> }
>
> class Component {
> Context context;...
> public printIt() {
> context.getPrinter().do something...
> }
> }
>
> This reduces boilerplate but doesn't eliminate it. For some projects it
> might be better to get a real dependency injection framework.
As a side note, since this approach has the drawback of requiring
additional constructor or method parameters (and hence targeted
factoring), I have in such cases often found it useful to provide the
context object via the threadlocal functionality.
In code terms, instead of:
class Actor {
void act( Context c ){ doSomethingWith( c.getXXX() ); }
}
You'd have:
class Actor {
void act(){
doSomethingWith( ContextHelper.getThreadLocalContext().getXXX() );
}
}
--
DF.
[toc] | [prev] | [next] | [standalone]
| From | markspace <markspace@nospam.nospam> |
|---|---|
| Date | 2013-04-22 10:59 -0700 |
| Message-ID | <kl3tkk$3hc$1@dont-email.me> |
| In reply to | #23565 |
On 4/22/2013 12:03 AM, Daniele Futtorovic wrote:
>
> In code terms, instead of:
> class Actor {
> void act( Context c ){ doSomethingWith( c.getXXX() ); }
> }
Just to be clear, I was advocating using constructors, not method
parameters:
public class Actor {
private Context c;
public Actor( Context c ) {this.c = c}
public void act() { doSomethingWith( c.getXXX() ); }
}
This is really really different:
> You'd have:
> class Actor {
> void act(){
> doSomethingWith( ContextHelper.getThreadLocalContext().getXXX() );
> }
> }
Now actor does something different depending on what thread is invoking
a method. My class was invariant with respect to the thread invoking its
method. No matter who calls "act()" the result will always be the same.
Since modern systems often use thread pools and the worker threads are
supposed to be generic and often randomly assigned, I can't see too many
cases where your thread local context is going to be useful. Worse, if
an generic worker thread has a context and then is assigned to another
task... the results could be random and unpredictable, and really hard
to debug as well.
I'm sure you must have some use case in mind where a thread local is
useful, but I'm having a hard time seeing it. It feels like you push
the context/initialization problem into the threading system, where it's
actually going to be harder to manage. In a system that was designed
from the ground up to support contexts attached to threads, OK it might
work, but in many existing systems it seems difficult to add.
[toc] | [prev] | [next] | [standalone]
| From | Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> |
|---|---|
| Date | 2013-04-24 06:37 +0200 |
| Message-ID | <kl7nco$25q$1@dont-email.me> |
| In reply to | #23569 |
On 22/04/2013 19:59, markspace allegedly wrote:
> On 4/22/2013 12:03 AM, Daniele Futtorovic wrote:
>>
>> In code terms, instead of:
>> class Actor {
>> void act( Context c ){ doSomethingWith( c.getXXX() ); }
>> }
>
> Just to be clear, I was advocating using constructors, not method
> parameters:
>
> public class Actor {
> private Context c;
> public Actor( Context c ) {this.c = c}
> public void act() { doSomethingWith( c.getXXX() ); }
> }
Yes; this is why I spoke of "constructor or method parameters".
See, the problem, or issue, with this approach is that you make the
context part of the actor's state. Meaning the actor is bound to the
context, rather than being context-independent. For instance, the
component wouldn't be reusable for a different context.
Now, there may be situations where that would be the right thing to do.
Yet, because of that, this approach to me is inferior to passing the
context to the main actor method (the method that encapsulates the unit
of work).
> This is really really different:
>
>> You'd have:
>> class Actor {
>> void act(){
>> doSomethingWith( ContextHelper.getThreadLocalContext().getXXX() );
>> }
>> }
>
> Now actor does something different depending on what thread is invoking
> a method. My class was invariant with respect to the thread invoking its
> method. No matter who calls "act()" the result will always be the same.
>
> Since modern systems often use thread pools and the worker threads are
> supposed to be generic and often randomly assigned, I can't see too many
> cases where your thread local context is going to be useful. Worse, if
> an generic worker thread has a context and then is assigned to another
> task... the results could be random and unpredictable, and really hard
> to debug as well.
I'll have to disagree with you here. All systems that use thread pools
will involve some sort of dispatch mechanism that consumes a queue of
work units. I do not believe it is far fetched to imagine that the
dispatch mechanism would run as exemplified in the following:
while take-from-queue
set-up-context
try {
execute-task
} finally {
clean-up-context
}
The only situation, then, where the ThreadLocal wouldn't work is when
the work units are executed on multiple threads. I may be wrong, but I
do not see this as being the majority of cases -- to the contrary.
> I'm sure you must have some use case in mind where a thread local is
> useful, but I'm having a hard time seeing it. It feels like you push
> the context/initialization problem into the threading system, where it's
> actually going to be harder to manage. In a system that was designed
> from the ground up to support contexts attached to threads, OK it might
> work, but in many existing systems it seems difficult to add.
It is true that it is more fragile, and for that reason alone may be
legitimately rejected, I'll grant you that. But it is not difficult to
add; quite the contrary, it is much easier to add to an existing system
than the one you suggested, because it does not involve any change in
the API (only to the implementation).
Now, don't get me wrong, I'm not trying to suggest this is anywhere the
be-all and end-all of programming techniques. Indeed, because it is
fragile and less explicit (and hence more difficult to grasp) than the
other way (passing a context to the actor's method), the latter is my
preferred and indeed the standard approach I opt for when designing a
piece of code that involves a dispatch mechanism (which is most of
them). I merely intended to mention that other possibility for the record.
--
DF.
[toc] | [prev] | [next] | [standalone]
| From | Arved Sandstrom <asandstrom2@eastlink.ca> |
|---|---|
| Date | 2013-04-24 10:28 -0300 |
| Message-ID | <F5Rdt.1871$FS4.989@newsfe12.iad> |
| In reply to | #23569 |
On 04/22/2013 02:59 PM, markspace wrote:
> On 4/22/2013 12:03 AM, Daniele Futtorovic wrote:
>>
>> In code terms, instead of:
>> class Actor {
>> void act( Context c ){ doSomethingWith( c.getXXX() ); }
>> }
>
> Just to be clear, I was advocating using constructors, not method
> parameters:
>
> public class Actor {
> private Context c;
> public Actor( Context c ) {this.c = c}
> public void act() { doSomethingWith( c.getXXX() ); }
> }
>
> This is really really different:
>
>> You'd have:
>> class Actor {
>> void act(){
>> doSomethingWith( ContextHelper.getThreadLocalContext().getXXX() );
>> }
>> }
>
> Now actor does something different depending on what thread is invoking
> a method. My class was invariant with respect to the thread invoking its
> method. No matter who calls "act()" the result will always be the same.
>
> Since modern systems often use thread pools and the worker threads are
> supposed to be generic and often randomly assigned, I can't see too many
> cases where your thread local context is going to be useful. Worse, if
> an generic worker thread has a context and then is assigned to another
> task... the results could be random and unpredictable, and really hard
> to debug as well.
>
> I'm sure you must have some use case in mind where a thread local is
> useful, but I'm having a hard time seeing it. It feels like you push
> the context/initialization problem into the threading system, where it's
> actually going to be harder to manage. In a system that was designed
> from the ground up to support contexts attached to threads, OK it might
> work, but in many existing systems it seems difficult to add.
>
I can think of one right now, one that is in production in a fairly
major J2EE/JEE system I am familiar with.
The idea was/is to implement a persistent conversation, and this
implementation goes back about 7 years, in the context of JSF 1.x and
JPA. Basically an application-managed entity manager needs to kept
around, one for each application user, from a defined EM-creation
checkpoint to a defined EM-commit/rollback checkpoint. This is needed
because money is involved and the real-world scenario demands it. It is
not possible to commit per-request, for much of the business state.
Between HTTP requests it's reasonable to keep a user's EM in their HTTP
session. *During* requests the specific conversational EM assigned to
that user must be made available wherever it's required in code - a very
convenient way of doing that is to place the user EM into a ThreadLocal
in the 1st JSF phase, in a helper class, and provide a getter to allow
the user's HTTP request thread to retrieve that "special" EM as needed
in any method.
I think you'll realize that something like an ApplicationScoped JSF
managed bean would not work here. It's technically possible for B.L. or
datalayer code to access a JSF managed bean, if you assume that that top
layer is there, but it's an unpleasant picture. Much better to have the
user EM's kept in a ThreadLocal in a data layer helper class, since that
makes architectural sense.
I might add, this described implementation is pre-Servlet 3 and no async
processing is involved.
AHS
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.java.programmer
csiph-web