The Source for Java Technology Collaboration


ext:config : extensible JXTA configuration with ease

Table of Contents

Abstract

The ext:config library is an optional JXTA extension that both eases and extends the core JXTA configuration principals. This is achieved through the combination of a comprehensive bean API that is backed with common use-case defaults in addition to declarative preset support and UI utilities, all of which progressively build upon one another and are in part or in full optional.

Each of the following ext:config principals will be discussed in detail:

Dependencies

The required ext:config jars:

  • JXTA
    • bcprov-jdk14.jar
    • log4j.jar
    • javax.servlet.jar
    • jxta.jar
    • jxtaext.jar
    • org.mortbay.jetty.jar
  • 3rd party
    • jdom.jar (required only for UI)
    • swixml.jar (required only for UI)

These jars can be obtained from the JXTA Download Site.

Introduction

JXTA applications are typically self configuring. This is due in part to the JXTA design principal that peers actively seek to leverage discovered services and in part due to the wide domain upon which JXTA applications are deployed, collectively resulting in the need for autonomous configuration. In the first case, the application's role is largely that of a "service consumer" by connecting to existing JXTA networks and associated provisioned resources. On the other hand, some applications can benefit from fine tuning, augmenting and extending core JXTA configuration parameters.

ext:config's role is to make \uffffeasy things trivial and all things possible.\uffff As such, ext:config can be leveraged to seamlessly construct, update, extend, validate, optimize and integrate JXTA configuration processes as best suited for the hosting application.

Principal JXTA configuration information is collected the form of a PlatformConfig object. For file based persistent environments, a PlatformConfig XML file often resides within the application's specified working directory, aka JXTA HOME, as a JXTA Platform start up precondition. In memory only application environments as well as runtime configuration support is also available and is actively under development.

The ext:config/api library is principally a bean (or property sheet) styled API with which one can construct, manipulate and generate a valid JXTA configuration in the form of a PlatformConfig object. The principal classes in ext:config/api are AbstractConfigurator and Configurator.

The ext:config/profile is a declarative means to manage JXTA configuration processes by driving the afore mentioned ext:config/api via "profiles" which are largely configuration presets. The principal class in in ext:config/profile is:

  • net.jxta.ext.config.Profile

The ext:config/ui provides a series of user interface elements to manage JXTA configuration data.

API (aka ext:config)

The ext:config API is the core of the ext:config package with both the Profile and UI tiers layering above, in succession. A Configurator provides the ability instantiate and persist JXTA configuration state based upon the provided information and applied heuristics. The Configurator serves primarily as a JXTA Configuration Bean, or property sheet, and as such implements very little attribute association logic beyond that of what is required to perform fundamental configuration integrity validation.

The principal constituents of a JXTA Configurator are:

  • Peer Information
  • JXTA Network Description
  • Peer Transports
  • Peer Services
  • Configuration Extensions

Peer Information describes the local JXTA instance that a specified Configurator instance represents. The bulk of the peer information configuration data is optional and includes:

  • name
  • ID
  • descriptor
  • JXTA Home
  • Log4J trace level
  • security
  • root certificate
  • HTTP Proxy

The JXTA Network information specifies JXTA Network Services upon which the to be instantiated peer will leverage as initialing seeding (aka bootstrap) information:

  • Network
  • RendezVous
  • Relays

Peer Transports describe the physical address and transports with which a peer connects to the greater JXTA Network. Transports can be specified as incoming (aka server), outgoing (aka client) and both. Transport implementations include:

  • TCP
  • HTTP

Peer Services represent the JXTA Services that the to be instantiated peer will provision, which include:

  • RendezVous
  • Relay
  • Proxy

The Configuration Extensions information includes extensible configuration features such as end user provided Optimizer implementations:

The principal API classes are:

  • net.jxta.ext.config.AbstractConfigurator
  • net.jxta.ext.config.Configurator

A number of supporting classes are also available that aid in the overall configuration management process.

The easiest means to leverage the ext:config API is to implement an AbstractConfigurator by implementing the singular abstract createPlatformConfig() method. This method is invoked during the configuration lifecylce when either a PlatformConfig object does not exist or is invalid. The method signature is as follows:

  public abstract PlatformConfig createPlatformConfig(PlatformConfigurator configurator)
  throws ConfiguratorException;

With this in mind, following is a complete AbstractConfigurator implementation, assuming some hardwired values for the time being:

import net.jxta.ext.config.AbstractConfigurator;
import net.jxta.ext.config.Configurator;
import net.jxta.exception.ConfiguratorException;
import net.jxta.impl.protocol.PlatformConfig;

public class MyConfigurator
extends AbstractConfigurator {

  private static final String NAME = "name";
  private static final String PRINCIPAL = "principal";
  private static final String PASSWORD = "password";

  public PlatformConfig createPlatformConfig(Configurator c)
  throws ConfiguratorException {
    c.setName(NAME);
    c.setSecurity(PRINCIPAL, PASSWORD);

    return c.getPlatformConfig();
  }
}

In order to perform configuration changes during each configuraiton cycle configuration the provided updatePlatformConfig() method can be overridden:

  public PlatformConfig updatePlatformConfig(PlatformConfigurator configurator)
  throws ConfiguratorException

Lastly, the configure() method can be invoked to trigger the configuration life cycle:

  public PlatformConfig configure()
  throws ConfiguratorException

The derived PlatformConfig can be used to immediately instantiate a peer or passed along to another process as is. With that in mind, a comprehensive code example is as follows:

import net.jxta.ext.config.AbstractConfigurator;
import net.jxta.ext.config.Configurator;
import net.jxta.exception.ConfiguratorException;
import net.jxta.exception.PeerGroupException;
import net.jxta.impl.protocol.PlatformConfig;
import net.jxta.peergroup.PeerGroup;
import net.jxta.peergroup.PeerGroupFactory;
...

  private static final String NAME = "name";
  private static final String PRINCIPAL = "principal";
  private static final String PASSWORD = "password";
...

  PeerGroup npg = null;

  // xxx: specifying a System property for JXTA_HOME will no longer be required in future releases
  System.setProperty("JXTA_HOME", new File("myHome").getAbsolutePath());

  try {
    new AbstractConfigurator() {
      public PlatformConfig createPlatformConfig(Configurator c)
      throws ConfiguratorException {
        c.setName(NAME);
        c.setSecurity(PRINCIPAL, PASSWORD);

        return c.getPlatformConfig();
      }
    }.configure();

    npg = PeerGroupFactory.newNetPeerGroup(...);
  } catch(ConfigurationException ce) {
    ...
  } catch (PeerGroupException pge) {
    ...
  }
...

The above code will perform the following actions:

  • create the default "./.jxta" working directory if it doesn't exist
  • read the ./.jxta/PlatformConfig file in the specified home
  • read the ./.jxta/profile.xml file in the specified home
  • create and return a PlatformConfig

The information used to initialize the AbstractConfigurator instance can be influenced by a number optional constructors, including:

  • no-arg
  • URI representing the working directory (aka JXTA Home)
  • Profile
  • alternative backing Configurator delegate

Typical usage is to override the defaults by specifying an application specific working directory (aka JXTA HOME) and application specific Profile. Following is such an example with the addition of a Profile, which we will address shortly:

...
import net.jxta.ext.config.Profile
import java.net.URI;
...

  try {
    new AbstractConfigurator(new URI(...), new Profile(...)) {
      ...
    }.configure();

    npg = PeerGroupFactory.newNetPeerGroup(...);
  } catch(URISyntaxException use) {
   ...
  } catch(ConfigurationException ce) {
    ...
  } catch (PeerGroupException pge) {
...

In addition to the above mentioned processes, the above code will:

  • create and/or read the specified working directory
  • reference the specified profile

When specifying a non-default working directory, aka JXTA Home, it is currently required to specify the system property named JXTA_HOME the value of the absolute file path. Further, it is incumbent upon the developer to copy into the working directory "private network" resources. These issues will be resolved in the next release (see issue #1488 and #1500).

Barring exceptions, one can then instantiate a JXTA Platform by referencing the derived JXTA Home and it's included artifacts, namely PlatformConfig.

A future release of JXTA (see Platform 2.3.7 + patches 1488 and 1500) will enable one to efficiently and fully configure and subsequently start a peer instance in addition to optionally persisting the configuration artifacts (see commons/modules/ext):

...
import net.jxta.peergroup.NetPeerGroupFactory;
...
  try {
    AbstractConfigurator c = new AbstractConfigurator(new URI(...), new Profile(...)) {
      ...
    };

    npg = NetPeerGroupFactory(c.configure(), c.getJxtaHome());

    c.save();
  } catch(URISyntaxException use) {
   ...
  } catch(ConfigurationException ce) {
    ...
  } catch (PeerGroupException pge) {
...

We'll touch on the different types of Profiles shortly but that aside for a moment now is a good time to mention that you can trivially vary the profile used by your AbstractConfigurator implementation via it's constructor, as follows:

...

  try {
    AbstractConfigurator c = new AbstractConfigurator(new URI(...), Profile.EDGE) {
//    AbstractConfigurator c = new AbstractConfigurator(new URI(...), Profile.SUPER) {
...

Further, you can readily instantiate a specialized applications specific profile as follows:

...

  try {
    URI p = getClass().getResourceAsStream("/path/to/my/profile.xml");
//    URI p = new URI("file:./path/to/my/profile.xml");
    AbstractConfigurator c = new AbstractConfigurator(new URI(...), new Profile(p)) {
...

AbstractConfigurator can be used as a PlatformConfig factory, e.g. cluster configuration generation, by simply invoking the getPlatformConfig() method:

  public PlatformConfig getPlatformConfig()
  throws ConfiguratorException

As an application developer convenience, named resources can be registered which will be deposited in the working directory. A common use for these APIs is to scope your applications data to the running JXTA instance.

...

  try {
    new AbstractConfigurator() {
      {
        addResource(PROFILE_KEY, "/net/jxta/myjxta/resources/profile.xml");
        addResource("log4j.xml", "/net/jxta/myjxta/resources/log4j.xml");
      }

      public PlatformConfig createPlatformConfig(Configurator c)
      throws ConfiguratorException {
...

Before we move on to the next topic, let's recap the AbstractConfigurator life cycle:

  • instantiation
    • optionally specifying
      • working directory
      • Profile
      • configuration delegate
    • process current configuration state
      • PlatformConfig
      • profile.xml
  • create a PlatformConfig
    • invoke configure to create and persist a PlatformConfig
      • invokes createPlatformConfig()
      • inovkes updatePlatformConfig()
      • (ed: subject to change) invokes save()
    • or invoke getPlatformConfig() to create a PlatformConfig
      • invokes createPlatformConfig()
      • inokes updatePlatformConfig()

When implementing AbstractConfigurator createPlatformConfig() and updatePlatformConfig() methods you will work directly with the underlying configuration delegate, aptly named Configurator. With that, we turn our attention to the Configurator API.

The Configurator class serves to programmatically create new or update existing PlatformConfig instances by managing all configuration attributes in addition to performing data integrity and optional data optimizations. As mentioned above, a Configurator is most often managed via an AbstractConfigurator implementation although it can just as easily be used as a standalone component.

The lifecycle of a Configurator is typically quite short and follows along the lines of:

  • instantiation
    • optionally specifying
      • working directory
      • Profile
      • PlatformConfig
      • convenience peer information
    • process current configuration state
      • PlatformConfig
      • profile.xml
  • invocation of any number of Configurator state modifiers (aka setters)
  • create a PlatformConfig
    • invoke getPlatformConfig()
      • normalization
      • validation with possible generation of a chained ConfiguratorException?
      • optimization
      • create PlatformConfig
  • optionally persist configuration artifacts

Internally, Configurator uses Profile.DEFAULT, effectively Profile.EDGE, to establish common use case defaults, after which, any number of setter methods may be invoked to further tune the desired configuration state.

During instantiation, existing PlatformConfig and profile.xml references are processed in order to implement "configuration update" support. Existing PlatformConfig instances are given ultimate preference in this regard. Lastly, the provided constructor arguments are processed accordingly and serve to overlay the current state. None of the Configurator constructors throw exceptions at this time so generating a Configurator instance is ensured.

Generating a PlatformConfig is achieved by invoking getPlatformConfig():

  public PlatformConfig getPlatformConfig()
  throws ConfiguratorException

Optionally, the derived configuration state can be persisted by invoking save() noting that save() will invoke getPlatformConfig() in the event it has not been invoked directly:

  public boolean save()
  throws ConfiguratorException

The ConfiguratorException object chains all causal exceptions which are in turn accessible via getCauses():

  public List getCauses()

To bring this home, let's construct a trivial Configurator that given the provided peer principal and password will construct and persist a PlatformConfig instance:

import net.jxta.ext.config.Configurator;
import net.jxta.exception.ConfiguratorException;
import java.util.Iterator;
...

  private static final String NAME = "name";
  private static final String PASSWORD = "password";

  Configurator c = new Configurator(NAME, PASSWORD);

  try {
    c.save();
  } catch (ConfiguratorException ce) {
    for (Iterator c = ce.getCauses().iterator(); c.hasNext(); ) {
      System.out.println(((Throwable)c.next()).getMesasge());
    }
  }

Alas, life is typically not so simple and as such we move on to explore the available Configurator modifier methods. Before doing so, let's align with the afore mentioned AbstractConfigurator code sample by overriding the default constructor with an alternative working directory and profile, as follows:

...
import java.net.URI;
...

  Configurator c = new Configurator(new URI(...), new Profile(...));
   ...

Again, the type of Profile can readily vary during instantiation. Further, you can use Configurator to update an existing PlatformConfig at any time by invoking the setPlatformConfig() method:

  public void setPlatformConfig(PlatformConfig pc)

Given Configurator is all encompassing by design and largely a bean (aka property sheet) by implementation the list of setter methods is extensive and but can be broken down into the following categories:

  • peer [peer, application and working environment information]
    • name [peer name]
    • description [peer description, e.g. configuration implementation]
    • id [peer id]
    • debug [log level]
    • security [root certificate principal]
  • network [jxta network resources including network, rendezVous and relays]
    • seeding rendezVous [initial rendezVous context]
    • seeding relays [initial relays context]
  • services [peer provisioned services]
    • RendezVous [rendezVous service]
    • Relay [relay service]
    • Proxy [proxy service]
  • transports [physical network resources]
    • TCP [tcp address(es)]
    • HTTP [http address(es)]
    • others as implemented
  • endpoint [local resource configuration]
  • miscellaneous [e.g. configuration and extensions]

At this time we'll expand on some key members within the configuration family noting that all Configurator modifiers are listed shortly along with a brief description.

Peer information including name, working directory, certificate, and logging information can be specified as follows:

  public void setName(String)

  public void setPeerId(PeerID)

  public void setDescription(String)

  public void setJxtaHome(URI)

  public void setRootCertificate(Certificate)

  public void setRootCertificateAddress(URI)

  public void setRootCertificateBase64(String)

  public void setSecurity(String, String)

  public void setTrace(Trace)

  public void setRendezVousAutoStart(long)

The default JXTA network is known as the Public Network (aka PubNet) which serves as an available testbed network. Specifying a non-default JXTA network is achieved by invoking the "infrastructure group" APIs, which allows one to construct, deploy, operate and scope systems resources to a dedicated network of services:

  public void setInfrastructurePeerGroupId(PeerGroupID id)

  public void setInfrastructurePeerGroupName(String name)

  public void setInfrastructurePeerGroupDescription(String description)

In order to establish initial JXTA network context it is optimal to specify seeding (aka bootstrap) information after which the peer is free to leverage discovered resources as needed at runtime. Seeding RendezVous and Relays are typical and in fact for "edge" scenarios only the later is required. RendezVous peers serve as a connection resource with which newly instantiated peers can leverage in the form of leases. Relay relationships are established for peers that can not otherwise communicate with one another in a direct fashion which is common for applications running behind corporate firewalls accessing services available on the open internet. These relationships change dynamically as the netork itself changes yet the developer is presented with a unified view of the overall network. A seeding address, be it RendezVous or Relay, takes the form of a fully qualified IP based URI, with examples being:

tcp://1.2.3.4:9701
http://1.2.3.4:9700

A seeding URI is a simply a resource that returns a list of available seeding addresses as defined above. As such, as seeding URI is often specified with a common domain name, e.g.:

http://rdv.jxtahosts.net/cgi-bin/rendezvous.cgi?2
http://rdv.jxta.hosts.net/cgi-gin/relays.cgi?2

Any URI is available to use as a seeding URI and need not resolve at runtime to be used. As an example, for standalone development environments a file based URI is optimal, e.g.:

file:./myrdv.txt

The following methods can be used to specify RendezVous and Relays network resources in addition to whether or not the to be configured peer can leverage newly discovered services:

  public void setRendezVous(URI)

  public void addRendezVous(URI)

  public void setRendezVous(List)

  public void setRendezVousBootstrapAddress(URI)

  public void setRendezVousDiscovery(boolean)

  public void setRelays(URI)

  public void addRelays(URI)

  public void setRelays(List)

  public void setRelayBootstrapAddress(URI)

  public void setRelaysDiscovery(boolean)

For some network deployments, it can be optimal to restrict "edge" peers from leasing against unknown peers that happen to be provisioning RendezVous and/or Relays services.

Your peer's physical address(es) are utilized to establish bidirectional communications over existing and supported networking protocols. By default, the application's local IP address is used being specified as the Any/All address (e.g. IPv6 "::" or IPv4 "0.0.0.0"). You can specify an explicit address by constructing a Transport instance. Further, for configurations where the actual system IP is not resolvable by all (e.g. NAT) you can specify the public address and opt to keep the internal and unresolvable by many address private. The following code sample constructs just such a configuration:

import net.jxta.ext.config.MulticastAddress;
import net.jxta.ext.config.TcpTransport;
import net.jxta.ext.config.TcpTransportAddress;
import java.net.URISyntaxException;
...

  TcpTransportAddress ta = new TcpTransportAddress();

  try {
    ta.setAddress(new URI("tcp://1.2.3.4:9701"));
  } catch (URISyntaxException use) {
    ...
  }

  try {
    ta.set
  } catch (URISyntaxException use) {
    ...
  }

  MulticastAddress ma = new MulticastAddress();

  ma.setMulticast(true);

  try {
    ma.setAddress(new URI("udp://4.3.2.1:1079"));
  } catch (URISyntaxException use) {
    ...
  }

  ta.setMulticastAddress(ma);

  PublicAddress pa = new PublicAddress();

  pa.setExclusive(true);

  try {
    pa.setAddress(new URI("tcp://10.20.30.40:9701"));
  } catch (URISyntaxException use) {
    ...
  }

  TcpTransport tt = new TcpTransport();

  tt.setAddress(ta);
  tt.setPublicAddress(pa);

  c.setTransport(tt);

It should be noted that doing the equivalent Transport configuration using Profile constructs is significantly more intuitive and less prone to error, a topic we will touch on shortly. Till then, with a Transport object in hand, we can augment the configuration state via the following methods:

  public void setTransport(Transport)

  public void addTransport(Transport)

  public void addTransports(List)

  public void setTransports(List)

An Optimizer is a concrete implementation of the Optimizer interface:

  public interface Optimizer {
    public void addProperty(String key, String value);

    public List getProperty(String key);

    public void optimize(Configurator c);
  }

Optimizers provide the opportunity to apply application specific configuration heuristics against a Configurator object. Optimizers may be provided with a series of name-values tuples and are supported via Profile constructs. Further, the Configurator implementation may opt to apply a number of internal optimizers during PlatformConfig generation.

Optimizers are applied to the Configurator via the following methods:

  public void addOptimizer(Optimizer)

  public void addOptimizers(List)

An abstract BaseOptimizer can be implemented easing the manufacturing of specialized optimizers, e.g.:

...
import net.jxta.ext.config.optimzers.BaseOptimizer;
...

  Configurator c = new Configurator(new URI(...), new Profile(...));
  ...

  c.addOptimizer(new BaseOptimizer() {
    public void optimize(Configurator c) {
      ...
    }
  });
...

While Configurator includes several methods, common practice is to instantiate a Configurator from a baseline Profile and only invoke the few remaining modifiers that are of specific interest.

Now that we have a desired configuration state the next step is to generate the representative PlatformConfig object, which is done by inoking the getPlatformConfig() method:

  public PlatformConfig getPlatformConfig()
  throws ConfiguratorException

The following steps are preformed during PlatformConfig generation:

  • normalization
  • optimzation
  • validation
  • PlatformConfig generation

All exceptions that may occur as a result of the above processing is captured in a single ConfiguratorException in for form a chained exception list, as noted above.

Normalization is the process that fills in any blank attributes with the specified default values. Profile macros are expanded at this time. This step of the process generates no exceptions.

Next up, the registered Optimizers are invoked in succession, passing the modified Configurator object in turn. An Optimizer provides the application developer with a concrete API with which to influence configuration life cycle process.

Lastly, the resulting configuration state is applied against a series of internal integrity constraints assuring configuration viability and possibly throwing a ConfiguratorException that is comprised of a chained list of all validation valure root causes.

Before disposing of the Configurator instance, one can optionally persist the derived configuration artifacts by invoking the save() method. save() invokes the getPlatformConfig() method in the event is has not been previously invoked.

Profile (aka ext:config/profile)

A Profile is a declarative means to manage Configurator instantiation and state via composable presets that represent distinct configuration models. ext:config/profile represents this tier of the configuration package. A series of common configuration presets accessible as static members of the Profile class. Further, one can construct an application specific profile in order to manage specialized configuration requirements.

All profile addresses are specified as URIs. Addresses that do not specify scheme information will be defaulted according to the respective context. Further, partial addresses will be resolved against a backing contextual template.

All fields have backing defaults enabling one to specify only the required overrides in order to efficiently construct complete configuration profiles.

The principal ext:config/profile class is:

  • net.jxta.ext.config.Profile

Available Profile presets include:

Profile.EDGE service consumer
Profile.DEFAULT synonynm for Profile.EDGE
Profile.EDGE_TCP service consumer with tcp address
Profile.EDGE_HTTP service consumer with http address
Profile.SUPER rendezVous and relay service provisioner
Profile.SUPER_TCP rendezVous and relay service provisioner with tcp address
Profile.SUPER_HTTP rendezVous and relay service provisioner with http address
Profile.RENDEZVOUS rendezVous service provisioner
Profile.RENDEZVOUS_TCP rendezVous service provisioner with tcp address
Profile.RENDEZVOUS_HTTP rendezVous service provisioner with http address
Profile.RELAY relay service provisioner
Profile.RELAY_TCP relay service provisioner with tcp address
Profile.RELAY_HTTP relay service provisioner with http address
Profile.LOCAL loopback only
Profile.ADHOC multicast

For added flexibility, profiles can be instantiated with either a URI or InputStream constructor argument the content of which conforms to the profile schema definition which can be found in both the Profile javadoc and net.jxta.ext.config.resources.profile.xsd schema definition file. URI arguments can specify JAR or external resources easing application deployment by consistently managing application configuration meta data.

Following is the prototypical edge profile which can serve as the basis for creating your specialized Profile:

<!DOCTYPE org.jxta:configuration>

<jxta>
  <peer descriptor="edge"/>

  <transport>
    <tcp>
      <address range="100">
        <multicast>udp://224.0.1.85:1234</multicast>
      </address>
      <publicAddress exclusive="false"/>
    </tcp>

    <http>
      <address range="100"/>
      <publicAddress exclusive="false"/>
      <proxy enabled="false"/>
    </http>
  </transport>

  <service>
    <relay>
      <outgoing enabled="true"/>
    </relay>
  </service>
</jxta>

Default profile information is typically not displayed, further easing extension by allowing one to specify only the overrides. A future Profile.EDGE release will largely be an emtpy file as all the values are defaults, allowing one to add only data elements which are specified as overrides.

Although we've seen Profile instantiation in the above code examples it might prove enlightening to walk through a couple of use cases. The following example instantiates a Profile from a file based URI resource:

import net.jxta.ext.config.Profile;
import net.jxta.ext.config.ResourceNotFoundException;
import java.net.URI;
import java.net.URISyntaxException;
...

  Profile p = null;

  try {
    p = new Profile(new URI("file:./myprofile.xml"));
  } catch (MalformedURLException mue) {
    ...
  } catch (URISyntaxException use) {
    ...
  }

While the following example instantiates a Profile from a class resource:

...

//    p = new Profile(new URI("file:./myprofile.xml"));
    p = new Profile(getClass().getResourceAsStream("/path/to/myprofile.xml"));
...

The edge profile does not include all possible configuration options as some services are not enabled. Further, defaults are not displayed thereby simplifying overall profile usage. Following is a comprehensive breakdown of the principal configuration elements:

  • /jxta [jxta configuration]
    • /peer [peer, application and working environment information]
      • @name [peer name (e.g. "myPeer")]
      • @id [peer id (e.g. "urn:jxta:uuid-59616261646162614A78746150325033D186291E80AB4CD1875F8FF5C2CE2F9503)"]
      • @descriptor [peer description, (e.g. "me myself i")]
      • @home [working directory (e.g. "file:./myjxta")]
      • @trace [log level (e.g. "debug")]
      • /description [peer description (e.g. "long version of me myself i")]
      • /security [credentials]
        • @enabled [?security activation? (e.g. "true")]
        • @principal [credential principal (e.g. "me")]
      • /rootCert [root certificate (e.g. "MIICEDCCAXmgAwIBA...")]
        • @address [root certificate address (e.g. "file:./mycert.pem")]
      • /proxy [http proxy (e.g. "http://[usr:pwd@]proxy.org[:port]")]
        • @enabled [http proxy activation (e.g. "true")]
    • /network [jxta network resources including network, rendezVous and relays]
      • @id [net peer group id (e.g. "urn:jxta:uuid-59616261646162...E2F9503")]
      • @name [net peer group name (e.g. "MyNet")]
      • @description [net peer group description (e.g. "me myself i network")]
      • /rendezVous [seeding rendezVous]
        • @bootstrap [seeding address (e.g. "file:./rdv.txt")]
        • @discovery [leverage discovered rendezVous peers activation (e.g. "false")]
        • /address [rendezVous seed address (e.g. "tcp://1.2.3.4:9701")]
      • /relays [seeding relays]
        • @bootstrap [seeding address (e.g. "file:./rly.txt")]
        • @discovery [leverage discovered relay peers activation (e.g. "false") - nop]
        • /address [relay seed address, (e.g. "tcp://1.2.3.4:9701")]
    • /transport [physical network resources]
      • /tcp [tcp address(es)]
        • @enabled [tcp transport activation (e.g. "true")]
        • /incoming [server]
          • @enabled [server activation (e.g. "true")]
        • /outgoing [client]
          • @enabled [client activation (e.g. "true")]
        • /address [physical tcp address (e.g. "tcp://1.2.3.4:9701")]
          • @range [port range (e.g. "100")]
          • /multicast [multicast address (e.g. "udp://224.0.1.85:1234")]
            • @enable [multicast activation (e.g. "false")]
            • @size [multicat packet size (e.g. "16338")]
        • /publicAddress [publicly addressable address (e.g. "tcp://5.6.7.8:9701")]
          • @exclusive [don't publish physical tcp address (e.g. "false")]
        • /proxy [tcp proxy address (e.g. "tcp://5.6.7.8:8080")]
          • @enabled [proxy activation (e.g. "false")]
      • /http [http address(es)]
        • @enabled [http transport activation (e.g. "true")]
        • /incoming [server]
          • @enabled [server activation (e.g. "false")]
        • /outgoing [client]
          • @enabled [client activation (e.g. "true")]
        • /address [physical http address ("http://1.2.3.4:9700")]
          • @range [port range (e.g. "100")]
        • /publicAddress [publicly addressable address (e.g. "http://5.6.8.9:9700")]
          • @exclusive [don't publish physical http address (e.g. "false")]
        • /proxy [http proxy address (e.g. "http://5.6.7.8:8080")]
          • @enabled [proxy activation (e.g. "false")]
    • /service [provisioned services]
      • /rendezVous [rendezVous service]
        • @enabled [rendezVous activation (e.g. "false")]
        • /autoStart [start rendezVous if unable to establish a lease after specified milliseconds (e.g. "120000")]
          • @enabled [auto rendezVous activation (e.g. "false")]
      • /relay [relay service]
        • @enabled [relay activation (e.g. "false")]
        • @queueSize [relay queue size (e.g. "20")]
        • /incoming [server]
          • @enabled [server activation (e.g. "false")]
          • @maximum [maximum leases (e.g. "100")]
          • @lease [lease time (e.g. "7200000")]
        • /outgoing [client]
          • @enabled [client activation (e.g. "true")]
          • @maximum [maximum leases (e.g. "100")]
          • @lease [lease time (e.g. "7200000")]
      • /endpoint [local resource configuration]
        • @queueSize [queue size (e.g. "100")]
      • /proxy [proxy service]
        • @enabled [proxy activation (e.g. "false")]
    • /configuration [configuration]
      • /optimizer [optimizer]
        • @class [optimizer class name (e.g. "path.to.MyOptimizer")]
          • /property [property value (e.g. "path.to.MyOptimizer.foo")]
            • @name [property key (e.g. "bar")]

To close on this section, one can trivially instantiate a Configurator, or AbstractConfigurator, with a named Profile as follows:

import net.jxta.ext.config.Configurator;
import net.jxta.ext.config.Profile;
...

  Configurator c = new Configurator(Profile.EDGE);
//  Configurator c = new Configurator(Profile.SUPER);

A specialized Profile can be readily used as follows:

...
import java.net.URI;
...

  Configurator c = new Configurator(new Profile(new URI(...)));

As we've seen above, AbstractConfigurators can be instantiated with a Profile in like fashion, further simplifying JXTA configuration within one's application, all the while the underlying Configurator can readily be manipulated via any of the available APIs. This model supports configuration experimentation without having to recompile. Lastly, profiles are used internally by the Configurator class and as such are most assuredly first class citizens within the ext:config package.

UI (aka ext:config/ui)

Lastly, the ext:config/ui tier provides an extensible UI above the ext:config/profile tier by providing Swing utilities to aid in interactive configuration. See JXTA ext:UI doc for more information.

The principal ext:config/ui class is:

  • net.jxta.ext.config.ui.Configurator

status: work in progress

Just Code

Following are the steps necessary to compile and run the included functional code samples. The prerequisites are:

Obtain a working copy of the ext-config-lab.zip code samples and uncompress it accordingly followed by changing your working directory to that of the top-level jxta directory provided by the distribution. Running Ant with no arguments will display the usage message:

% ant
Buildfile: build.xml

usage:
     [echo] % ant [option]
     [echo]   [exercise number]
     [echo]   all
     [echo]   clean

The excercises are contained under the src directory and organized as incremental and progressive code samples. The lib directory includes the necessary JXTA and ext:config libraries:

JXTA JARs:

  • bcprov-jdk14.jar
  • javax.servlet.jar
  • jxta.jar
  • jxtaext.jar
  • log4j.jar
  • org.mortbay.jetty.jar

To run an excercise simply provide the excercise directory as an Ant argument:

% ant 1
Buildfile: build.xml

http.proxy:

socks.proxy:

prepare:

1:

1.compile:

compile:

1.run:

run:
     [java] create PlatformConfig with the following properties:
     [java]   name = MyPeerName
     [java]   description = MyPeerDescription
     [java]   principal = MyPeerPrincipal
     [java]   password = MyPeerPassWord
     [java] saving PlatformConfig to: .../jxta/build/1/home

BUILD SUCCESSFUL
Total time: 9 seconds

Feel free to make changes to the exercises via your editor of choice and recompile and run them via Ant. You can always start over if needed by uncompressing the distribution file.

Have fun! Learn by doing!

Next Steps

  • consider adding annotation support to (net.jxta.ext.config.)Profile

Resources

-- JamesTodd - 01 Feb 2005
-- updated.RayGao - 21, Nov. 2005

Topic ExtConfig . { Edit | Ref-By | Printable | Diffs r22 < r21 < r20 < r19 < r18 | More }
 XML java.net RSS

Revision r22 - 13 Jun 2006 - 01:28:18 - Main.gonzo
Parents: WebHome