I had promised more thoughts on top of your interface thoughts. Here they
are.
[snip]
Simon Laws wrote
Same thoughts translated into interface speak....
public abstract class SCADomainFactory
public static SCADomainFactory newInstance()
-$1 public abstract SCADomain createSCADomain(String domainURI);
public abstract SCADomain getSCADomain(String domainURI);
+$1 public class SCADomainImplFactoryImpl implements SCADomainFactory
+$1 public class SCADomainProxyFactoryImpl implements SCADomainFactory
public interface SCADomain
public void start();
public void stop();
public String getURI();
$4 void addContribution(URL url);
void removeContribution(URL url);
void addComposite(QName qname);
void removeComposite(QName qname);
void startComposite(QName qname);
void stopComposite(QName qname);
+$2 void startComponent(Qname qname);
+$2 void stopComponent(Qname qname);
public <B, R extends CallableReference<B>> R cast(B target) throws
IllegalArgumentException;
public <B> B getService(Class<B> businessInterface, String
serviceName);
public <B> ServiceReference<B> getServiceReference(Class<B>
businessInterface, String referenceName);
public abstract class SCANodeFactory
public static SCANodeFactory newInstance()
$5 public abstract SCANode createSCANode(String nodeURI, String
domainURI)
public interface SCANode
public void start();
$6 public void stop();
$3 public void configure(QName composite, URL... contributions);
public String getURI();
$7 public SCADomain getSCADomain();
void startComposite();
void stopComposite();
+$2 void startComponent(Qname qname);
+$2 void stopComponent(Qname qname);
Specific but rather random comments.
$1 Not sure about createDomain. It adds potential confusion. People
will
have
to decide when to create and when to get a domain. In out model of
having a central representation of the domain
it works quite well in that in one place you "create" and everywhere
else you "get" but doesn't work so well
in other models, e.g if there is no central manager and that each
domain object holds references to all other domain
objects and nodes. Do you "create" or do you "get". How about we
take
this out and assume there is a different SCADomainFactory
impl instantiated (via newInstance) in the case where we want to do
the
creation step?
Having the same method do different things under the covers could be
confusing. I was seeing two pretty different use cases:
a) The Tuscany runtime implements an SCA domain service. It gets an
SCADomainFactory, creates an SCAdomain, starts the domain admin service,
on request from a system adminstrator adds contributions, composites,
starts them.
Here's sample code to illustrate that use case:
http://svn.apache.org/repos/asf/incubator/tuscany/sandbox/sebastien/java/sca/domain-and-node/samples/
SampleTuscanyDomainImplementation.java
b) Application code finds a domain, asks the domain for a proxy to an
application service, invokes the service.
Sample code to illustrate that:
SampleClient.java
$2 The fundamental operation is starting/stopping components.
Starting/stopping composites is a useful shortcut
Correct, but here are a few reasons for preferring startComposite IMO:
I was imagining that startComposite would:
1. Take the composite and cut it into smaller composites that can be
distributed to different nodes
2. Distribute the composites and the contributions they require to the
selected nodes
3. Assemble (build) each composite on the node on which it's going to run
4. Start the composite
5. At that point start each component contained in the composite...
pfeewww :)
Exposing a startComponent method will force us to expose other APIs for
the 5 steps. That being said, a sample piece of code showing how to script
these steps without introducing too many other APIs may convince me.
Also as system administrator using the SCA domain, I'm deploying a
composite, so I'm not sure why I'd want to not start the composite as a
whole. Turning this around, people always claim that they want to start
components individually but never complain that they can't deploy them
individually and everybody seems to be happy with deploying composites...
I find this rather funny :) My guess is that users will put components
that belong together in the same composite, to deploy, undeploy, update,
start and stop them together.
Finally, maybe the more convincing point because it's more concrete:
Starting our current Calculator sample would require 5 calls to
startComponent, that's too much...
$3 The same effect be achieved with the familiar pattern
void addContribution(URL url);
void addComposite(QName qname);
void startComposite(QName qname);
I see that this is a useful device in our desire to differentiate the
operation of a node from that of a domain.
I actually don't mind them having very similar interfaces. The
difference in my mind is one of scope. Dealing with a node
you are just deling with that
one runtime (a common pattern we use in out samples/tests). Dealing
with a domain you don't care where the contributed
artifacts run.
With configure(composite, contributions) I was trying to provide that
"immutable" feel, and avoid the usual slippery slope:
- ah I can add
- then I should be able to remove
- and update
- can I add contributions after I've added composites?
- how about updating contributions?
- ah I see that I can start multiple composites, can I add more composites
after I start?
- what if I update when it's running?
... and when is all of this going to work? OK I stop now :)
More seriously, I'm looking for the right API pattern to express something
like:
- a node is small
- a node is loaded with artifacts, frozen, then runs
- a node is reset, then is ready to run again with new artifacts
- a node is NOT a big application server
$4 We haven't explored and magic domain to node allocation algorithms
to
date. How about we start with picking he next
node that doesn't yet have a contribution. If you run out of nodes
its
bad luck, i.e. implies no magic node provisioning so if you want more
nodes
you have to start them manually.
+1
$5 Can you pass null in here (or some special constant if you want an
association with a domain
that will only every have this one node in it? This is a special case
as
there are potentially several economies that can be made in terms of
starting or
trying to connect to domain services.
Didn't get that. Could you show a sample?
$6 Has the effect of removing all configuration.
Yes, but looking at it now we need something clearer. I added
unloadContributions() to SCANode. Let me know what you think.
$7 Wondering if this should return the domain URL so that you get the
domain object manually.
+1 I made the change.
Possibly a neater solution to $5 in that a different
domain
factory (and domain implementation) can be introduced in the case that
you
know an application is only going to have domain with a single node
Still didn't understand $5 :)
Simon
Staring at interfaces is fun but it's probably easier to look at sample
use cases.
I have put several use cases there:
http://svn.apache.org/repos/asf/incubator/tuscany/sandbox/sebastien/java/sca/domain-and-node/samples/
- SampleClient.java
Application code finds a domain, gets a proxy to a service, invokes the
service
- SampleMiniUnitTestDomainWithClient.java
For testing purposes, an application test case bootstraps its own mini
domain, installs a contribution and composite in it, starts it, gets a
proxy to a service and invokes it.
- SampleTuscanyDomainImplementation.java
A mockup of what a Tuscany domain runtime implementation could look like.
A real implementation would run as a server and provide a SOAP or JSON
Service for example to add/remove contributions, add/remove/start/stop
composites, and under the covers we'd create/find/allocate nodes and run
the composites on nodes. Here I just scripted that scenario by hand in the
main method to show how the APIs would be used.
- SampleUnitTestCalculatorNodeWithClient.java
For testing purposes, an application test case bootstraps its own node,
configures it with a contribution and composite, starts the composite,
then find the domain, gets a proxy to a service and invokes it.
- SampleTuscanyNodeImplementation.java
A mockup of what a Tuscany node runtime implementation could look like. A
real implementation would run as a server and provide a SOAP or JSON
Service for example to configure the node and start/stop its composite.
Here I just scripted that scenario by hand in the main method to show how
the APIs would be used.
--
Jean-Sebastien
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]