Millies, Sebastian wrote:
-----Original Message-----
From: Simon Nash [mailto:[email protected]]
Sent: Thursday, December 09, 2010 8:41 PM
To: [email protected]
Subject: Re: Elementary question about Scopes
[snip
For sharing intermediate computation results between multiple methods
of
the same instance object, I would find it very cumbersome to arrange
all my method signatures to make sure the necessary data is passed
around.
Agreed, it can be cumbersome. On the other hand, I once had to make a
service COMPOSITE which was previously stateless, because for performance
reasons I needed to introduce a cache to hold results of expensive
computations from earlier requests.
This is exactly the kind of scenario for which COMPOSITE scope is intended.
Had I used instance variables in the stateless early version, this might have
caused problems or confusion once the service became stateful.
This is a valid point. It would be necessary to modify the implementation
logic to change instance variables to method local variables, which would
be a nuisance. The other option is to implement the cache as a different
COMPOSITE-scoped service with local interfaces, and have the SCA runtime
inject a reference to this local cache object into the STATELESS instance
that it creates for each request. This is probably the approach that I
would use.
Of course, I could have solved my caching problem the old-fashioned way by
keeping the service declaration as stateless, and using static variables for
the cache. Now that would have been confusing as well, wouldn't it? Or would
that seem appropriate to you?
I wouldn't recommend doing that. With COMPOSITE scope, the SCA runtime
can control the creation and lifetime of the COMPOSITE instance rather
than being at the mercy of what the JVM does. If the domain is entrely
contained within a single JVM, this distinction may not be important.
For other scenarios such as a server cluster or a distributed domain,
there will be multiple Java instances of the same SCA COMPOSITE-scoped
object, with updates coordinated by the SCA runtime. it is essential that
the SCA runtime has the ability to manage this situation and give all
the JVMs the appearance of a single shared COMPOSITE-scoped object even
though the actual physical reality might be somewhat different.
Perhaps it would be better not to have to declare the service itself as
stateless or stateful, but rather have scope annotations on each individual
instance variable.
I'm not sure how that could be implemented. Either a new instance is
created for each request, or it isn't. If at least one instance variable
is stateful, then a new instance can't be created and so we end up with
the equivalent of COMPOSITE scope and a single instance. It wouldn't
be thread-safe to use this single instance to hold the stateless-scoped
instance variables, so I'm not sure how these variables would be treated.
Also, the approach you're suggesting has the issue of introducing a
redundant
COMPOSITE scoped instance which has no apparent useful purpose. This
object
has no mutable state, because all mutable state is stored in method
local
variables that are passed around as parameters. This seems strange, as
the
purpose of COMPOSITE scope in SCA is to provide mutable state that's
shared
between requests. Using it for this other purpose means that people
who
read the code and see the scope declared as COMPOSITE are likely to
find it
harder to understand whether the service has stateful or stateless
semantics.
Simon
I understand how that might be confusing. However, such abuse of COMPOSITE scope
came to me quite naturally in one case, where my real aim was to make sure that
the @Init method was only executed once. The reason being not just computational
expense, but rather that I wanted to establish preconditions for the use of the
service (like creating certain entities in a backend etc.) These actions should
not be repeated on each service method call, although the service itself had stateless
semantics.
What would you suggest to handle this? Is there a better place to do things
like this
than the @Init method? Or would it make sense to have a new annotation for this
purpose,
something like @OnLoad ?
You could do what I suggested above: create another local object with
COMPOSITE scope and use the @Init method of that object to do the
one-time initialization. By having a reference from your service
implementation to the other object, you can be sure that the other
object will have been initialized before the first service method of
your service implementation is invoked.
Simon
-- Sebastian