On 9/27/07, Simon Laws <[EMAIL PROTECTED]> wrote:
>
> Sebastien
>
> Thank you for these thoughts. My comment in line below. I'll post
> separate, but hopfully consistent, comments on the code you made.
>
> Simon
>
> On 9/27/07, Jean-Sebastien Delfino <[EMAIL PROTECTED]> wrote:
> >
> > Comments inline.
> >
> > Simon Laws wrote:
> > > On 9/26/07, ant elder <[EMAIL PROTECTED] > wrote:
> > >
> > >> On 9/26/07, Simon Laws < [EMAIL PROTECTED]> wrote:
> > >>
> > >>> We have two SCADomain interfaces (I'm leaving
> > aside  EmbeddedSCADomain
> > >>>
> > >> for
> > >>
> > >>> now)
> > >>>
> > >>> 1) o.a.t.s.host.embedded.SCADomain (supports a domian with a single
> > >>>
> > >> node)
> > >>
> > >>>     public static SCADomain newInstance()
> > >>>     public static SCADomain newInstance(String composite)
> > >>>     *A* public static SCADomain newInstance(String domainURI, String
> > >>> contributionLocation, String... composites)
> > >>>     *A* public static void removeInstance(SCADomain domainInstance)
> > >>>     *A* public static SCADomain connect(String domainURI)
> > >>>     public void close()
> > >>>     public abstract String getURI()
> > >>>     public abstract <B, R extends CallableReference<B>> R cast(B
> > target)
> > >>>     public abstract <B> B getService(Class<B> businessInterface,
> > String
> > >>> serviceName)
> > >>>     public abstract <B> ServiceReference<B>
> > getServiceReference(Class<B>
> > >>> businessInterface, String referenceName)
> > >>>     private static String getServiceName(ClassLoader classLoader,
> > String
> > >>>
> > >>> name)
> > >>>     static SCADomain createNewInstance(String domainURI, String
> > >>> contributionLocation, String... composites)
> > >>>     *B* public ComponentManager getComponentManager()
> > >>>
> > >>> 2) o.a.t.s.domain.SCADomain (supports a domain with one or more
> > nodes)
> > >>>     public static SCADomain newInstance()
> > >>>     public static SCADomain newInstance(String composite)
> > >>>     *A* public static SCADomain newInstance(String domainURI, String
> > >>> nodeURI, String contributionLocation, String... composites)
> > >>>     public abstract void close()
> > >>>     public abstract String getURI()
> > >>>     public abstract <B, R extends CallableReference<B>> R cast(B
> > target)
> > >>>
> > >>>     public abstract <B> B getService(Class<B> businessInterface,
> > String
> > >>> serviceName)
> > >>>     public abstract <B> ServiceReference<B>
> > getServiceReference(Class<B>
> > >>> businessInterface, String referenceName);
> > >>>     private static String getServiceName(ClassLoader classLoader,
> > String
> > >>> name)
> > >>>     static SCADomain createNewInstance(String domainURI, String
> > nodeURI,
> > >>> String contributionLocation, String... composites)
> > >>>
> > >>>
> > >>> I propose we move to having one. I've marked the parts that differ
> > with
> > >>> *?*.
> > >>> There are two main points.
> > >>>
> > >>> *A* The mechanism by which this local domain representation (the
> > node)
> > >>>
> > >> is
> > >>
> > >>> associated with a wider logical domain
> > >>> *B* The mechanism by which the domain is managed (the components in
> > the
> > >>> domains single node in the case of 1 above)
> > >>>
> > >>> Before we start re-positioning interfaces though we need to agree
> > what
> > >>>
> > >> we
> > >>
> > >>> mean by the words we use here as there has been some confusion.
> > We've
> > >>> discussed these issues before [1][2][3] etc. The result was a
> > separation
> > >>> of
> > >>> node and domain so that you could operate on a node and on a
> > >>>
> > >> domain.  This
> > >>
> > >>> approach/API is currently hidden behind SCADomain as there was no
> > >>> consensus
> > >>> that this was the right approach. e.g.  I've heard people saying
> > things
> > >>> like
> > >>> "a node shouldn't provide an interface for adding contributions as
> > you
> > >>>
> > >> add
> > >>
> > >>> contributions to a domain".
> > >>>
> > >>> I want to push on the issue of how we expect users to deal with a
> > domain
> > >>> and
> > >>> the nodes in that domain before going back to look at the API. My
> > >>>
> > >> starter
> > >>
> > >>> for 10 is...
> > >>>
> > >>> - There are different types of users we must consider. Here are two
> > >>> examples,
> > >>>
> > >>>   1/ the developer who uses the Tuscany APIs to build a node
> > >>> implementation
> > >>> and makes contributions and manages components programmatically (see
> > our
> > >>> samples for an example of this approach)
> > >>>   2/ the user who manages one or more nodes as a domain, making
> > >>> contributions and managing components through a GUI.
> > >>>
> > >>> - Programmatically, to developer 1/,  a node API provides sca
> > runtime
> > >>> support and has to implement all of the management interfaces for
> > >>> accepting
> > >>> contributions, managing components etc, so that developer 1/ can
> > wire
> > >>> tuscany into whatever mechanism they have in their implementation
> > and so
> > >>> that, once the node is added to a domain, the domain can configure
> > and
> > >>> manage the node. The implication here is that the node is configured
> > and
> > >>>
> > >>> managed through contribution/component management interfaces that is
> > a
> > >>> superset of that of a domain (a superset as I would expect use of
> > other
> > >>> detailed Tuscany APIs to get the node to work)
> > >>>
> > >>> - Programmatically, to developer 1/, there should also be a domain
> > >>> representation so that they can include their node in a domain and
> > >>>
> > >> perform
> > >>
> > >>> domain level operations like locating a service (or even adding
> > >>> contributions, management components at a domain level). Developer
> > 1/
> > >>> would
> > >>> associate their node implementation with a domain (within a single
> > VM
> > >>>
> > >> this
> > >>
> > >>> would be as easy as passing the node object into the domain
> > interface).
> > >>>
> > >>> - To the user of type 2/ all of these operations may be performed
> > >>>
> > >> through
> > >>
> > >>> a
> > >>> GUI using some slick drag and drop management interface. However,
> > they
> > >>>
> > >> are
> > >>
> > >>> the same operations. We don't have a slick GUI interface currently
> > so
> > >>> contributions find their way directly to nodes because they are made
> > >>> programmatically in the node in question. The implication though is
> > that
> > >>> if
> > >>> we do things at the domain level under the covers the real
> > processing is
> > >>>
> > >>> delegated to the nodes in the domain.
> > >>>
> > >>> So opinions please on how you see domains and nodes working.
> > >>>
> > >>> Regards
> > >>>
> > >>> Simon
> > >>>
> > >>> [1]
> > http://www.mail-archive.com/[email protected]/msg23008.html
> > >>> [2]
> > http://www.mail-archive.com/[email protected]/msg18920.html
> > >>> [3]
> > http://www.mail-archive.com/[email protected]/msg22589.html
> > >>>
> > >>>
> > >> +1 to moving to one SCADomain.
> > >>
> > >> I've always found the SCADomain impls a bit confusing so i guess now
> > is
> > >> the
> > >> chance to ask questions -
> > >>
> > >>
> > >
> > >
> > > Why all the static and abstract methods? Is there a reason SCADomain
> > >
> > >> couldn't just be an interface with a separate SCADomainFactory for
> > >> creating
> > >> instances?
> > >>
> > >
> > >
> > >  I don't know. A factory works for me.
> >
> > +1 for making SCADomain an interface
> >
> > +1 for having a factory
> >
> > So instead of:
> > SCADomain domain = SCADomain.newInstance(...)
> >
> > We'll have:
> > SCADomainFactory domainFactory;
> > SCADomain domain = domainFactory.createSCADomain(domainURI)
> >
> > Now how do people would like to the get factory? a pretty common pattern
> > is:
> > SCADomainFactory domainFactory = SCADomainFactory.newInstance(...)
> >
> > Is there a better pattern?
>
>
> +1  allows us to abtract away the factory implementation
>
> Does that answer the question about "why the static and abstract
> > methods"? :)
> >
> > > I think there is a lack of clarity
> > > about creating an SCA Domain vs creating an object in a JVM that
> > represent
> > > an SCA Domain.  IMHO A factory/new instance method doesn't create a
> > new
> > > domain just creates a new object that is able to talk to a domain.
> > Others
> > > may have different opinions.
> > >
> >
> > I think we need to distinguish:
> > - creating a domain... createDomain(domainURI)
> > - getting a handle to an existing domain... getDomain(domainURI)
>
>
> I think we need to distiguish between these two but I would rather it were
> done through factory implementation rather than interface operation. I think
> having two operation causes potential confusion to the user about which to
> call. They potentially need to know how the domain has been implemented to
> make this decision.
>
> > I've also found the contributionLocation and composites parameters of
> > the
> > >
> > >> newInstance methods confusing as well. Why do we need the composites
> > >> parameter, contributions should use the meta-inf/sca-contribution.xmlto
> > >> define the deployable composites shouldn't they?   And I'm not sure
> > what
> > >> is
> > >> really valid for contributionLocation as whatever you specify it
> > seems to
> > >> go
> > >> off and discover all the composites in the path itself anyway. Could
> > the
> > >> composites parameter be dropped and the contributionLocation point at
> > any
> > >> one of these:
> > >> - a single .composite file in which case that will be the only
> > composite
> > >> used and it will get deployed
> > >> - a single contribution jar with a meta-inf/sca-contribution.xml to
> > say
> > >> what
> > >> composites get deployed
> > >> - a folder containing multiple contribution jars and/or subfolders
> > >> containing "un-jar'ed" contributions
> > >>
> > >
> > >
> > > Me too. Has always confused me. I did some investigation to work out
> > exactly
> > > what's going on here (see 
> > > http://issues.apache.org/jira/browse/TUSCANY-1779
> > ).
> > > But I'm still suspicious of combining two notions (the location where
> > > contributions can be found and the contributions that will be loaded
> > from
> > > there) into one method . This would be OK except that passing either a
> >
> > > relative or null contribution location still works as the code invents
> > a
> > > contribution location. I'd rather have a specific interface for this.
> > >
> > > So that would be something like:
> > >
> > >> SCADomainFactory
> > >>      SCADomain createSCADomain(contributionLocation)
> > >>      SCADomain createSCADomain(domainName, contributionLocation)
> > >>      SCADomain createSCADomain(domainName, nodeName,
> > contributionLocation)
> > >>
> > >
> > >
> >
> > It's not the first time we bump into this. Having a method take a
> > contribution location makes a lot of sense. The problem is figuring that
> > location...
> > a) in Eclipse or another IDE
> > b) with a JAR produced by Maven
> > c) with classes under test/classes
>
>
> Do you mean that the problem is figuring out what the location is as we
> move between these environments. The code that we have in svn currently
> doesn't take account of these environments explicitly but follows an
> algorithms of either accepting the absolute location you provide or looking
> on the classpath for various files (.composite, sca-contribution.xml etc.)
> to determine where the contribution is.
>
> With the API you're proposing you're going to have to write the following:
> >
> > URL contributionLocation = <magic code>;
> > Whatever whateverFactory = createWhatever(contributionLocation);
> >
> > Any good idea on how to write the <magic code> that works with [a], [b]
> > and [c]?
>
>
> I don't think we have magic code at present.
>
> [a] we rely on the classpath
> [b] contributions can't appear inside other contributions so, at a push,
> we have the option of saying the whole jar must be the contribution. This is
> how it works no I believe.
> [c] we rely on the classpath
>
> > I'm picking up on three things going on here in various combinations
> > >
> > > 1/ Creating an object that gives you an interface to a domain
> > > 2/ Associating a node with this domain
> > > 3/ Adding contributions to the domain
> > >
> > > I think we could simplify by reducing to 2 things
> > >
> > > 1/ Creating an object that gives you an interface to a domain
> > > 2/ Adding contributions to the domain
> > >
> > >      SCADomain createSCADomain()
> > >           I want to create a local domain object but the domain is not
> >
> > > distributed outside this JVM so I'm not bothering with a domain name.
> > >           I'll add some contributions later
> > >      SCADomain createSCADomain(domainUri, nodeUri)
> > >           I want to create a local domain object to represent the
> > named
> > > domain and add this named node in the domain
> > >           I'll add some contributions later
> > >      SCADomain createSCADomain(contributionLocation)
> > >           just start me a domain object which only knows about a
> > single
> > > local node and a single contribution, i.e. the pattern we use in most
> > of our
> > > tests
> > >      SCADomain createSCADomain(domainUri, nodeUri,
> > contributionLocation)
> > >          I want to create a local domain object to represent the named
> >
> > > domain and add the named node in the domain
> > >          I want to load the contribution from the provided location
> > >
> > > The resulting SCADomain object represents both the local node and the
> > > interface to the domain.
> > >
> > > It still feels a bit strange to me that it's called SCADomain. I still
> > have
> > > this feeling that we should have a domain thing that knows about the
> > domain
> > > and a node thing that knows how to run contributions.
> > +1 to separate the two:
> > - Domain - you go to a domain to declare contributions and domain
> > composites
> > - Node - you go to a node to run components (to simplify let's say that
> > a node runs a composite containing components)
>
>
> Why not a contribution containing a composite containing components? The
> composite will need to artifacts of its containing contribution anyhow
>
> > I.e. you create a
> > > domain object and talk to the domain (locate a service etc.) and if
> > you want
> > > to provide some runtime resources you create a node and add it to the
> > > domain.
> >
> > +1 and I'd like to start with the following simplifying assumptions:
> >
> > - A node belongs to a domain, you specify the domain when you create the
> > node, the node does not migrate from one domain to another
>
>
> +1
>
> - A node does not have complicated lifecycle operations, a node is
> > created, configured with a composite and the contributions needed by the
> > composite, runs off of that, then dies or gets recycled. In other words
> > a node is immutable.
>
>
> +0.5 Immutable once it's started?
>
> > This of course is currently hidden by the SCADomain interface. This
> > > separate domain/node view is inconvenient and looks heavyweight if you
> > want
> > > to write a quick sample so maybe having this convenience of single
> > method
> > > construction is good but under the covers that is my mental model of
> > what is
> > > going on.
> > >
> >
> > Well, I think we have two use cases:
> >
> > - I want to deal with the node myself, I create a node, configure it
> > with a composite and contributions, start it etc.
>
>
> +1
>
> - I don't care about nodes, I go to the domain, contribute
> > contributions, declare composites, then just ask the domain do start my
> > composite, however it wants, wherever it wants. To do that the domain
> > will have to create one or more nodes under the covers, configure them
>
>
> Or nodes are crated and added to the domain. Just saying it doesn't have
> to me some magic remote deployment mechanism.
>
> with the composite and contributions, start it etc. But as a user of the
> > domain, I'm not exposed to nodes at all.
>
>
> +1
>
> > We also need management interfaces for adding contributions, controlling
> > > components etc. We did this before by providing operations that
> > returned
> > > management objects, as the current SCADomain interface does, but there
> > were
> > > objections to this approach.
> > >
> >
> > We will need management interfaces, but I think we should know where
> > we're going with the basic concepts and experiment with simpler APIs -
> > just two interfaces Domain and Node - before adding more APIs.
>
>
> By management I mean
>
> Add/remove contribution
> Add/remove composite
> Start/stop component
>
> Am completely happy to leave
>
> getNodeInfo
> getComponentInfo
> etc.
>
> Until later.
>
> >    ...ant
> > >
> > >
> > > Simon
> > >
> >
> > To help with the discussion, I put my thoughts around domain and node in
> >
> > code there:
> >
> > Samples showing node and domain use cases:
> > http://svn.apache.org/repos/asf/incubator/tuscany/sandbox/sebastien/java/sca/domain-and-node/samples/
> >
> >
> > Strawman node and domain interfaces:
> > http://svn.apache.org/repos/asf/incubator/tuscany/sandbox/sebastien/java/sca/domain-and-node/org/apache/tuscany/sca/node/
> >
> > http://svn.apache.org/repos/asf/incubator/tuscany/sandbox/sebastien/java/sca/domain-and-node/org/apache/tuscany/sca/domain/
> >
> >
> > Thoughts?
> >
> > --
> > Jean-Sebastien
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > For additional commands, e-mail: [EMAIL PROTECTED]
> >
> >
> 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?

  $2 The fundamental operation is starting/stopping components.
Starting/stopping composites is a useful shortcut


  $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.

  $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.

  $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.

  $6 Has the effect of removing all configuration.

  $7 Wondering if this should return the domain URL so that you get the
domain object manually. 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

Simon

Reply via email to