<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"../support/support/docbook-dtd/docbookx.dtd">
<book>
  <bookinfo>
    <title>JBoss Remoting Guide</title>

    <subtitle>JBoss Remoting version 2.0.0.CR1</subtitle>

    <releaseinfo>July 31, 2006</releaseinfo>

    <mediaobject>
      <imageobject>
        <imagedata fileref="images/JBoss_logo.jpg" />
      </imageobject>
    </mediaobject>

    <copyright>
      <year>2006</year>

      <holder>JBoss, Inc.</holder>
    </copyright>
  </bookinfo>

  <chapter>
    <title>Overview</title>

    <section>
      <title>What is JBoss Remoting</title>

      <para>The purpose of JBoss Remoting is to provide a single API for most
      network based invocations and related service that uses pluggable
      transports and data marshallers. The JBossRemoting API provides the
      ability for making synchronous and asynchronous remote calls, push and
      pull callbacks, and automatic discovery of remoting servers. The
      intention is to allow for the use of different transports to fit
      different needs, yet still maintain the same API for making the remote
      invocations and only requiring configuration changes, not code
      changes.</para>

      <para>JBossRemoting is a standalone project, separate from the JBoss
      Application Server project, but will be the framework used for many of
      the JBoss projects and components when making remote calls.
      JBossRemoting is included in the recent releases of the JBoss
      Application Server and can be run as a service within the container as
      well. Service configurations are included in the configuration section
      below.</para>
    </section>

    <section>
      <title>Features</title>

      <para>The features available with JBoss Remoting are:</para>

      <itemizedlist>
        <listitem>
          <para><emphasis role="bold">Server identification</emphasis> – a
          simple url based identifier which allows for remoting servers to be
          identified and called upon.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">Pluggable transports</emphasis> – can
          use different protocol transports the same remoting API.</para>

          <para>Provided transports:</para>

          <itemizedlist>
            <listitem>
              <para>Socket (SSL Socket)</para>
            </listitem>

            <listitem>
              <para>RMI (SSL RMI)</para>
            </listitem>

            <listitem>
              <para>HTTP(S)</para>
            </listitem>

            <listitem>
              <para>Multiplex (SSL Multiplex)</para>
            </listitem>

            <listitem>
              <para>Servlet</para>
            </listitem>
          </itemizedlist>
        </listitem>

        <listitem>
          <para><emphasis role="bold">Pluggable data marshallers</emphasis> –
          can use different data marshallers and unmarshallers to convert the
          invocation payloads into desired data format for wire
          transfer.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">Pluggable serialization</emphasis> - can
          use different serialization implementations for data streams.</para>

          <para>Provided serialization implementations:</para>

          <itemizedlist>
            <listitem>
              <para>Java serialization</para>
            </listitem>

            <listitem>
              <para>JBoss serialization</para>
            </listitem>
          </itemizedlist>
        </listitem>

        <listitem>
          <para><emphasis role="bold">Automatic discovery</emphasis> – can
          detect remoting servers as they come on and off line.</para>

          <para>Provided detection implementations:</para>

          <itemizedlist>
            <listitem>
              <para>Multicast</para>
            </listitem>

            <listitem>
              <para>JNDI</para>
            </listitem>
          </itemizedlist>
        </listitem>

        <listitem>
          <para><emphasis role="bold">Server grouping</emphasis> – ability to
          group servers by logical domains, so only communicate with servers
          within specified domains.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">Callbacks</emphasis> – can receive
          server callbacks via push and pull models. Pull model allows for
          persistent stores and memory management.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">Asynchronous calls</emphasis> – can make
          asynchronous, or one way, calls to server.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">Local invocation</emphasis> – if making
          an invocation on a remoting server that is within the same process
          space, remoting will automatically make this call by reference, to
          improve performance.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">Remote classloading</emphasis> – allows
          for classes, such as custom marshallers, that do not exist within
          client to be loaded from server.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">Sending of streams</emphasis> – allows
          for clients to send input streams to server, which can be read on
          demand on the server.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">Clustering</emphasis> - seamless client
          failover for remote invocations.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">Connection failure
          notification</emphasis> - notification if client or server has
          failed</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">Data Compression</emphasis> - can use
          compression marshaller and unmarshaller for compresssion of large
          payloads.</para>
        </listitem>
      </itemizedlist>

      <para>All the features within JBoss Remoting were created with ease of
      use and extensibility in mind. If you have a suggestion for a new
      feature or an improvement to a current feature, please log in our issue
      tracking system at <!--<link linkend="???">http://jira.jboss.com</link>-->
      <ulink url="http://jira.jboss.com">http://jira.jboss.com</ulink></para>
    </section>

    <section>
      <title>How to get JBoss Remoting</title>

      <para>The JBossRemoting distribution can be downloaded from <ulink
      url="http://www.jboss.org/products/remoting">
      http://www.jboss.org/products/remoting </ulink> . This distribution
      contains everything needed to run JBossRemoting stand alone. The
      distribution includes binaries, source, documentation, javadoc, and
      sample code.</para>
    </section>
  </chapter>

  <chapter>
    <title>Architecture</title>

    <para>The most critical component of the JBoss Remoting architecture is
    how servers are identified. This is done via an InvokerLocator, which can
    be represented by a simple String with a URL based format (e.g.,
    socket://myhost:5400). This is all that is required to either create a
    remoting server or to make a call on a remoting server. The remoting
    framework will then take the information embedded within the
    InvokerLocator and construct the underlying remoting components needed and
    build the full stack required for either making or receiving remote
    invocations.</para>

    <para>There are several layers to this framework that mirror each other on
    the client and server side. The outermost layer is the one which the user
    interacts with. On the client side, this is the Client class upon which
    the user will make its calls. On the server side, this is the
    InvocationHandler, which is implemented by the user and is the ultimate
    receiver of invocation requests. Next is the transport, which is
    controlled by the invoker layer. Finally, at the lowest layer is the
    marshalling, which converts data type to wire format.</para>

    <graphic fileref="images/design.jpg" />

    <para>When a user calls on the Client to make an invocation, it will pass
    this invocation request to the appropriate client invoker, based on the
    transport specified by the locator url. The client invoker will then use
    the marshaller to convert the invocation request object to the proper data
    format to send over the network. On the server side, an unmarshaller will
    receive this data from the network and convert it back into a standard
    invocation request object and send it on to the server invoker. The server
    invoker will then pass this invocation request on to the user’s
    implementation of the invocation handler. The response from the invocation
    handler will pass back through the server invoker and on to the
    marshaller, which will then convert the invocation response object to the
    proper data format and send back to the client. The unmarshaller on the
    client will convert the invocation response from wire data format into
    standard invocation response object, which will be passed back up through
    the client invoker and Client to the original caller.</para>

    <bridgehead>Client</bridgehead>

    <para>On the client side, there are a few utility class that help in
    figuring out which client invoker and marshal instances should be
    used.</para>

    <graphic fileref="images/design_client.jpg" />

    <para>For determining which client invoker to use, the Client will pass
    the InvokerRegistry the locator for the target server it wishes to make
    invocations on. The InvokerRegistry will return the appropriate client
    invoker instance based on information contained within the locator, such
    as transport type. The client invoker will then call upon the
    MarshalFactory to get the appropriate Marshaller and UnMarshaller for
    converting the invocation objects to the proper data format for wire
    transfer. All invokers have a default data type that can be used to get
    the proper marshal instances, but can be overridden within the locator
    specified.</para>

    <bridgehead>Server</bridgehead>

    <para>On the server side, there are also a few utility classes for
    determining the appropriate server invoker and marshal instances that
    should be used. There is also a server specific class for tying the
    invocation handler to the server invoker.</para>

    <graphic fileref="images/design_server.jpg" />

    <para>On the server side, it is the Connector class that is used as the
    external point for configuration and control of the remoting server. The
    Connector class will call on the InvokerRegistry with its locator to
    create a server invoker. Once the server invoker is returned, the
    Connector will then register the invocation handlers on it. The server
    invoker will use the MarshalFactory to obtain the proper marshal instances
    as is done on the client side.</para>

    <bridgehead>Detection</bridgehead>

    <para>To add automatic detection, a remoting Detector will need to be
    added on both the client and the server side as well as a NetworkRegistry
    to the client side.</para>

    <graphic fileref="images/design_detection.jpg" />

    <para>When a Detector on the server side is created and started, it will
    periodically pull from the InvokerRegistry all the server invokers that it
    has created. The detector will then use the information to publish a
    detection message containing the locator and subsystems supported by each
    server invoker. The publishing of this detection message will be either
    via a multicast broadcast or a binding into a JNDI server. On the client
    side, the Detector will either receive the multicast broadcast message or
    poll the JNDI server for detection messages. If the Detector determines a
    detection message is for a remoting server that just came online it will
    register it in the NetworkRegistry. The NetworkRegistry houses the
    detection information for all the discovered remoting servers. The
    NetworkRegistry will also emit a JMX notification upon any change to this
    registry of remoting servers. The change to the NetworkRegistry can also
    be for when a Detector has discovered that a remoting server is no longer
    available and removes it from the registry.</para>
  </chapter>

  <chapter>
    <title>JBoss Remoting Components</title>

    <para>This section covers a few of the main components exposed within the
    Remoting API with a brief overview.</para>

    <para><emphasis role="bold">org.jboss.remoting.Client</emphasis> – is the
    class the user will create and call on from the client side. This is the
    main entry point for making all invocations and adding a callback
    listener. The Client class requires only the InvokerLocator for the server
    you wish to call upon and that you call connect before use and disconnect
    after use (which is technically only required for stateful transports and
    when client leasing is turned on, but good to call in either case).</para>

    <para><emphasis role="bold">org.jboss.remoting.InvokerLocator</emphasis> –
    is a class, which can be described as a string URI, for identifying a
    particular JBossRemoting server JVM and transport protocol. For example,
    the InvokerLocator string socket://192.168.10.1:8080 describes a TCP/IP
    Socket-based transport, which is listening on port 8080 of the IP address,
    192.168.10.1. Using the string URI, or the InvokerLocator object,
    JBossRemoting can make a client connection to the remote JBoss server. The
    format of the locator string is the same as the URI type:
    <code>[transport]://[host]:&lt;port&gt;/path/?&lt;parameter=value&gt;&amp;&lt;parameter=value&gt;</code>
    A few important points to note about the InvokerLocator. The string
    representation used to construct the InvokerLocator may be modified after
    creation. This can occur if the host supplied is 0.0.0.0, in which case
    the InvokerLocator will attempt to replace it with the value of the local
    host name. This can also occur if the port specified is less than zero or
    not specified at all (in which case remoting will select a random port to
    use).</para>

    <para><emphasis
    role="bold">org.jboss.remoting.transport.Connector</emphasis> - is an
    MBean that loads a particular ServerInvoker implementation for a given
    transport subsystem and one or more ServerInvocationHandler
    implementations that handle Subsystem invocations on the remote server
    JVM. The Connector is the main user touch point for configuring and
    managing a remoting server.</para>

    <para><emphasis
    role="bold">org.jboss.remoting.ServerInvocationHandler</emphasis> – is the
    interface that the remote server will call on with an invocation received
    from the client. This interface must be implemented by the user. This
    implementation will also be required to keep track of callback listeners
    that have been registered by the client as well.</para>

    <para><emphasis role="bold">org.jboss.remoting.InvocationRequest
    </emphasis> – is the actual remoting payload of an invocation. This class
    wraps the caller’s request and provides extra information about the
    invocation, such as the caller’s session id and its callback locator (if
    one exists). This will be object passed to the
    ServerInvocationHandler.</para>

    <para><emphasis
    role="bold">org.jboss.remoting.stream.StreamInvocationHandler</emphasis> –
    extends the ServerInvocationHandler interface and should be implemented if
    expecting to receive invocations containing an input stream.</para>

    <para><emphasis
    role="bold">org.jboss.remoting.callback.InvokerCallbackHandler</emphasis>
    – the interface for any callback listener to implement. Upon receiving
    callbacks, the remoting client will call on this interface if registered
    as a listener.</para>

    <para><emphasis
    role="bold">org.jboss.remoting.callback.Callback</emphasis> – the callback
    object passed to the InvokerCallbackHandler. It contains the callback
    payload supplied by the invocation handler, any handle object specified
    when callback listener was registered, and the locator from which the
    callback came.</para>

    <para><emphasis
    role="bold">org.jboss.remoting.network.NetworkRegistry</emphasis> – this
    is a singleton class that will keep track of remoting servers as new ones
    are detected and dead ones are detected. Upon a change in the registry,
    the NetworkRegistry fires a NetworkNotification.</para>

    <para><emphasis role="bold">org.jboss.remoting.network.NetworkNotification
    </emphasis> – a JMX Notification containing information about a remoting
    server change on the network. The notification contains information in
    regards to the server’s identity and all its locators.</para>

    <para><emphasis
    role="bold">org.jboss.remoting.detection.Detection</emphasis> – is the
    detection message fired by the Detectors. Contains the locator and
    subsystems for the server invokers of a remoting server as well as the
    remoting server’s identity.</para>

    <para><emphasis role="bold">org.jboss.remoting.ident.Identity</emphasis> –
    is one of the main components remoting uses during discovery to identify
    remoting server instances (is actually the way it guarantees uniqueness).
    If have two remoting servers running on the same server, they can be
    uniquely identified. The reason the identity is persisted (currently only
    able to do this to the file system) is so if a server crashes and then
    restarts, can identify it when it restarts as the one that crashed
    (instead of being a completely new instance that is being started). This
    may be important from a monitoring point as would want to know that the
    crashed server is back online.</para>

    <para>When creating the identity to be presisted, remoting will first look
    to see if a system property for 'jboss.identity' has been set already. If
    it has, will use that one. If not, will get the value for the
    'ServerDataDir' attribute of the 'jboss.system:type=ServerConfig' mbean.
    If can retrieve this value, will just this as the directory to write out
    the 'jboss.identity' file. If not, will look to see if a system property
    has been set for 'jboss.identity.dir'. If it has, will use this as the
    directory to write the 'jboss.identity' file to, otherwise, will default
    to '.'. If for some reason the file can not be written to, will throw a
    RuntimeException, which will cause the detector to error during startup.
    For more details on how and where the identity is persisted, can refer to
    org.jboss.remoting.ident.Identity.createId().</para>

    <para><emphasis
    role="bold">org.jboss.remoting.detection.multicast.MulticastDetector</emphasis>
    – is the detector implementation that broadcasts its Detection message to
    other detectors using multicast.</para>

    <para><emphasis role="bold">org.jboss.remoting.detection.jndi.JNDIDetector
    </emphasis> – is the detector implementation that registers its Detection
    message to other detectors in a specified JNDI server.</para>

    <para>There are a few other components that are not represented as a
    class, but important to understand.</para>

    <para><emphasis role="bold">Subsystem</emphasis> – a sub-system is an
    identifier for what higher level system an invocation handler is
    associated with. The sub-system is declared as any String value. The
    reason for identifying sub-systems is that a remoting Connector’s server
    invoker may handle invocations for multiple invocation handlers, which
    need to be routed based on sub-system. For example, a particular socket
    based server invoker may handle invocations for both customer processing
    and order processing. The client making the invocation would then need to
    identify the intended sub-system to handle the invocation based on this
    identifier. If only one handler is added to a Connector, the client does
    not need to specify a sub-system when making an invocation.</para>

    <para><emphasis role="bold">Domain</emphasis> – a logical name for a group
    to which a remoting server can belong. The detectors can discriminate as
    to which detection messages they are interested based on their specified
    domain. The domain to which a remoting server belongs is stored within the
    Identity of that remoting server, which is included within the detection
    messages. Detectors can be configured to accept detection messages from
    one, many or all domains.</para>
  </chapter>

  <chapter>
    <title>Remoting libraries and thirdparty dependancies</title>

    <para>The remoting distribution comes several different version of the
    remoting libraries. This is mainly done so the size of the footprint for
    can be controlled based on the features of remoting that will be used.
    Remoting distribution will include the following remoting binaries (found
    in the lib directory of the distribution)</para>

    <para><emphasis role="bold">jboss-remoting.jar</emphasis> - this binary
    contains all the remoting classes. This is the only remoting jar that is
    needed to perform any remoting funtion within JBoss Remoting.</para>

    <para>Since some may want to better control size of the binary footprint
    needed to use remoting, the remoting classes have been broken out into
    multiple remoting binaries based on their function. There are four
    categories of these binaries; core, detection, transport, and
    other.</para>

    <bridgehead>core</bridgehead>

    <para><emphasis role="bold">jboss-remoting-core.jar</emphasis> - contains
    all the core remoting classes needed for remoting to function. If not
    using jboss-remoting.jar, then jboss-remoting.core.jar will be
    required.</para>

    <bridgehead>detection</bridgehead>

    <para><emphasis role="bold">jboss-remoting-detection</emphasis> - contains
    all the remoting classes needed to perform automatic discovery of remoting
    servers. It includes both the jndi and multicast detector classes as well
    as the network registry classes.</para>

    <bridgehead>transport</bridgehead>

    <para><emphasis role="bold">jboss-remoting-socket.jar</emphasis> -
    contains all the classes needed for the socket and sslsocket transports to
    function as both a client and a server.</para>

    <para><emphasis><emphasis
    role="bold">jboss-remoting-socket-client.jar</emphasis></emphasis> -
    contains all the classes needed for the socket and sslsocket transports to
    function as a client only. This means will not be able to perform any push
    callbacks or sending of streams using this jar.</para>

    <para><emphasis role="bold">jboss-remoting-http.jar</emphasis> - contains
    all the classes needed for the http and https transports to function as a
    client and a server.</para>

    <para><emphasis role="bold">jboss-remoting-http-client.jar</emphasis> -
    contains all the classes needed for the http, https, servlet, and
    sslservlet transports to function as a client only. This means will not be
    able to perform any push callbacks or sending of streams using this
    jar.</para>

    <para><emphasis role="bold">jboss-remoting-servlet.jar</emphasis> -
    contains all the classes needed for the servlet or sslservlet transports
    to function as a server only (also requires servlet-invoker.war be
    deployed within web container as well)</para>

    <para><emphasis role="bold">jboss-remoting-rmi.jar</emphasis> - contains
    all the classes needed for the rmi and sslrmi transports to function as a
    client and a server.</para>

    <para><emphasis role="bold">jboss-remoting-multiplex.jar</emphasis> -
    contains all the classes needed for the multiplex and sslmultiplex
    transports to function as a client and a server. Use of this jar also
    requires jboss-remoting-socket.jar be on classpath as well.</para>

    <bridgehead>other</bridgehead>

    <para><emphasis role="bold">jboss-remoting-serialization.jar</emphasis> -
    contains just the remoting serialization classes (and serialization
    manager implementations for java and jboss).</para>

    <para><emphasis role="bold"><emphasis
    role="bold">jboss-remoting-samples.jar</emphasis> </emphasis>- all the
    remoting samples showing example code for different remotng
    functions.</para>

    <section>
      <title>Thirdparty libraries</title>

      <para>This section covers which thirdparty jars are required based on
      the feature or transport to be used. Remember, whenever see
      jboss-remoting-XXX.jar mentioned, they can all be replaced with just the
      jboss-remoting.jar.</para>

      <para><emphasis role="bold">All remoting servers:</emphasis>
      jboss-remoting-core.jar, jboss-common.jar, jboss-jmx.jar,
      log4j.jar</para>

      <para><emphasis role="bold">All remoting clients:
      </emphasis>jboss-remoting-core.jar, jboss-common.jar, jboss-jmx.jar,
      log4j.jar, concurrent.jar</para>

      <para>Note: concurrent.jar needed because of org.jboss.util.id.GUID used
      to create session id within Client
      (http://jira.jboss.com/jira/browse/JBREM-549)</para>

      <para>Remoting requires the use of JMX classes. It does not require the
      JBoss implementation (jboss-jmx.jar) of JMX in order to function
      correctly, so can replace jboss-jmx.jar with another JMX implementation
      library (or exclude it if using jdk 1.5 or higher, which has JMX
      implementation built in).</para>

      <para><emphasis role="bold">Multicast detection:
      </emphasis>jboss-remoting-detection.jar, concurrent.jar,
      dom4j.jar</para>

      <para><emphasis role="bold">JNDI detection:</emphasis>
      jboss-remoting-detection.jar, concurrent.jar, dom4j.jar, jnpserver.jar
      (for jndi api classes)</para>

      <para>The dom4j.jar for use of detection is required because using
      jboss-jmx.jar.</para>

      <para><emphasis role="bold">Socket server:</emphasis>
      jboss-remoting-socket.jar</para>

      <para><emphasis role="bold">Socket client:</emphasis>
      jboss-remoting-socket-client.jar</para>

      <para><emphasis role="bold">HTTP server:</emphasis>
      jboss-remoting-http.jar, tomcat-coyote.jar, tomcat-util.jar,
      commons-logging-api.jar, tomcat-http.jar</para>

      <para>Note: need tomcat-apr.jar and tcnative-1.dll/tcnative-1.so on
      system path if want to use APR based tomcat connector</para>

      <para><emphasis role="bold">HTTP client:</emphasis>
      jboss-remoting-http-client.jar</para>

      <para><emphasis role="bold">Servlet server:</emphasis>
      servlet-invoker.war (deployed in web container),
      jboss-remoting-servlet.jar</para>

      <para><emphasis role="bold">Servlet client:</emphasis>
      jboss-remoting-http-client.jar</para>

      <para><emphasis role="bold">RMI server and client:</emphasis>
      jboss-remoting-rmi.jar</para>

      <para><emphasis role="bold">Multiplex server and client:</emphasis>
      jboss-remoting-socket.jar, jboss-remoting-multiplex.jar</para>

      <para><emphasis role="bold">JBoss serialization:</emphasis>
      jboss-serialization.jar, trove.jar</para>
    </section>
  </chapter>

  <chapter>
    <title>Configuration</title>

    <para>This covers the configuration for JBoss Remoting discovery,
    connectors, marshallers, and transports. All the configuration properties
    specified can be set either via calls to the object itself, including via
    JMX (so can be done via the JMX or Web console), or via a JBoss AS service
    xml file. Examples of service xml configurations can be seen with each of
    the sections below. There is also an example-service.xml file included in
    the remoting distribution that shows full examples of all the remoting
    configurations.</para>

    <section>
      <title>General Connector and Invoker configuration</title>

      <para>The server invoker and invocation handlers are configured via the
      Connector. Only one invoker can be declared per connector (multiple
      InvokerLocator attributes or invoker elements within the Configuration
      attribute is not permitted). Although declaring an invocation handler is
      not required, it should only be omitted in the case of declaring a
      callback server that will not receive direct invocations, but only
      callback messages. Otherwise client invocations can not be processed.
      The invocation handler is the only interface that is required by the
      remoting framework for a user to implement and will be what the remoting
      framework calls upon when receiving invocations.</para>

      <para>There are two ways in which to specify the server invoker
      configuration via a service xml file. The first is to specify just the
      InvokerLocator attribute as a sub-element of the Connector MBean. For
      example, a possible configuration for a Connector using a socket invoker
      that is listening on port 8084 on the test.somedomain.com address would
      be:</para>

      <programlisting>
         &lt;mbean code="org.jboss.remoting.transport.Connector"
               xmbean-dd="org/jboss/remoting/transport/Connector.xml"
               name="jboss.remoting:service=Connector,transport=Socket"
               display-name="Socket transport Connector"&gt;
            &lt;attribute name="<emphasis role="bold">InvokerLocator</emphasis>"&gt;
               &lt;![CDATA[<emphasis role="bold">socket://test.somedomain.com:8084</emphasis>]]&gt;
            &lt;/attribute&gt;
            &lt;attribute name="Configuration"&gt;
               &lt;config&gt;
                  &lt;handlers&gt;
                     &lt;handler <emphasis role="bold">subsystem</emphasis>="mock"&gt;
                        <emphasis role="bold">org.jboss.remoting.transport.mock.MockServerInvocationHandler</emphasis>
                     &lt;/handler&gt;
                  &lt;/handlers&gt;
               &lt;/config&gt;
            &lt;/attribute&gt;
         &lt;/mbean&gt;
      </programlisting>

      <para>Note that all the server side socket invoker configurations will
      be set to their default values in this case. Also, it is important to
      add CDATA to any locator uri that contains more than one
      parameter.</para>

      <para>The other way to configure the Connector and its server invoker in
      greater detail is to provide an <code>invoker</code> sub-element within
      the config element of the Configuration attribute. The only attribute of
      invoker element is transport, which will specify which transport type to
      use (e.g.. socket, rmi, http, or multiplex). All the sub-elements of the
      invoker element will be attribute elements with a name attribute
      specifying the configuration property name and then the value. An
      <code>isParam</code> attribute can also be added to indicate that the
      attribute should be added to the locator uri, in the case the attribute
      needs to be used by the client. An example using this form of
      configuration is as follows:</para>

      <programlisting> 
         &lt;mbean code="org.jboss.remoting.transport.Connector"
               xmbean-dd="org/jboss/remoting/transport/Connector.xml"
               name="jboss.remoting:service=Connector,transport=Socket"
               display-name="Socket transport Connector"&gt;

            &lt;attribute name="Configuration"&gt;
               &lt;config&gt;
               <emphasis role="bold"> 
                  &lt;invoker transport="socket"&gt;
                     &lt;attribute name="numAcceptThreads"&gt;1&lt;/attribute&gt;
                     &lt;attribute name="maxPoolSize"&gt;303&lt;/attribute&gt;
                     &lt;attribute name="clientMaxPoolSize" isParam="true"&gt;304&lt;/attribute&gt;
                     &lt;attribute name="socketTimeout"&gt;60000&lt;/attribute&gt;
                     &lt;attribute name="serverBindAddress"&gt;192.168.0.82&lt;/attribute&gt;
                     &lt;attribute name="serverBindPort"&gt;6666&lt;/attribute&gt;
                     &lt;attribute name="clientConnectAddress"&gt;216.23.33.2&lt;/attribute&gt;
                     &lt;attribute name="clientConnectPort"&gt;7777&lt;/attribute&gt;
                     &lt;attribute name="enableTcpNoDelay" isParam="true"&gt;false&lt;/attribute&gt;
                     &lt;attribute name="backlog"&gt;200&lt;/attribute&gt;
                  &lt;/invoker&gt;
               </emphasis>
                  &lt;handlers&gt;
                     &lt;handler subsystem="mock"&gt;
                        org.jboss.remoting.transport.mock.MockServerInvocationHandler
                     &lt;/handler&gt;
                  &lt;/handlers&gt;
               &lt;/config&gt;
            &lt;/attribute&gt;

         &lt;/mbean&gt;
      </programlisting>

      <para>Also note that <code>${jboss.bind.address}</code> can be used for
      any of the bind address properties, which will be replaced with the bind
      address specified to JBoss when starting (i.e. via the -b
      option).</para>

      <para>All the attributes set in this configuration could be set directly
      in the locator uri of the InvokerLocator attribute value, but would be
      much more difficult to decipher visually and is more prone to editing
      mistakes.</para>

      <para>One of the components of a locator uri that can be expressed
      within the InvokerLocator attribute is the path. For example, can
      express a locator uri path of 'foo/bar' via the InvokerLocator attribute
      as:</para>

      <programlisting>            &lt;attribute name="InvokerLocator"&gt;&lt;![CDATA[socket://test.somedomain.com:8084/<emphasis
          role="bold">foo/bar</emphasis>]]&gt;&lt;/attribute&gt;
</programlisting>

      <para>To include the path using the Configuration attribute, can include
      a specific 'path' attribute. So the same InvokerLocator can be expressed
      as follows with the Configuration attribute:</para>

      <programlisting>
            &lt;attribute name="Configuration"&gt;
               &lt;config&gt;
                 &lt;invoker transport="socket"&gt;
                   &lt;attribute name="serverBindAddress"&gt;test.somedomain.com&lt;/attribute&gt;
                   &lt;attribute name="serverBindPort"&gt;8084&lt;/attribute&gt;
                   <emphasis role="bold">&lt;attribute name="path"&gt;foo/bar&lt;/attribute&gt;</emphasis>
                 &lt;/invoker&gt;
                 ...
</programlisting>

      <para>Note: The value for the 'path' attribute should NOT start or end
      with a / (slash).</para>
    </section>

    <section>
      <title>Handlers</title>

      <para>Handlers are classes that the invocation is given to on the server
      side (the final target for remoting invocations). To implement a
      handler, all that is needed is to implement the
      <code>org.jboss.remoting.ServerInvocationHandler</code> interface. There
      are a two ways in which to register a handler with a Connector. The
      first is to do it programmatically. The second is via service
      configuration. For registering programmatically, can either pass the
      ServerInvocationHandler reference itself or an ObjectName for the
      ServerInvocationHandler (in the case that it is an MBean). To pass the
      handler reference directly, call
      <code>Connector::addInvocationHandler(String subsystem,
      ServerInvocationHandler handler)</code>. For example (from
      <code>org.jboss.remoting.samples.simple.SimpleServer</code>):</para>

      <programlisting>
            InvokerLocator locator = new InvokerLocator(locatorURI);
            Connector connector = new Connector();
            connector.setInvokerLocator(locator.getLocatorURI());
            connector.create();

            SampleInvocationHandler invocationHandler = new SampleInvocationHandler();
            // first parameter is sub-system name. can be any String value.
            connector.addInvocationHandler("sample", invocationHandler);

            connector.start();
         </programlisting>

      <para>To pass the handler by ObjectName, call
      <code>Connector::addInvocationHandler(String subsystem, ObjectName
      handlerObjectName)</code> . For example (from
      <code>org.jboss.test.remoting.handler.mbean.ServerTest</code>):</para>

      <programlisting>
            MBeanServer server = MBeanServerFactory.createMBeanServer();
            InvokerLocator locator = new InvokerLocator(locatorURI);
            Connector connector = new Connector();
            connector.setInvokerLocator(locator.getLocatorURI());
            connector.start();

            server.registerMBean(connector, new ObjectName("test:type=connector,transport=socket"));

            // now create Mbean handler and register with mbean server
            MBeanHandler handler = new MBeanHandler();
            ObjectName objName = new ObjectName("test:type=handler");
            server.registerMBean(handler, objName);

            connector.addInvocationHandler("test", objName);
         </programlisting>

      <para>Is important to note that if not starting the Connector via the
      service configuration, will need to explicitly register it with the
      MBeanServer (will throw exception otherwise).</para>

      <para>If using a service configuration for starting the Connector and
      registering handlers, can either specify the fully qualified class name
      for the handler, which will instantiate the handler instance upon
      startup (which requires there be a void parameter constructor), such
      as:</para>

      <programlisting>           
            &lt;handlers&gt;
              &lt;handler subsystem="mock"&gt;
                org.jboss.remoting.transport.mock.MockServerInvocationHandler
              &lt;/handler&gt;
            &lt;/handlers&gt;
         </programlisting>

      <para>where MockServerInvocationHandler will be constructed upon startup
      and registered with the Connector as a handler.</para>

      <para>Can also use an ObjectName to specify the handler. The
      configuration is the same, but instead of specifying a fully qualified
      class name, you specify the ObjectName for the handler, such as (can see
      <code>mbeanhandler-service.xml</code> under remoting tests for full
      example):</para>

      <programlisting>          
            &lt;handlers&gt;
              &lt;handler subsystem="mock"&gt;test:type=handler&lt;/handler&gt;
            &lt;/handlers&gt;
         </programlisting>

      <para>The only requirement for this configuration is that the handler
      MBean must already be created and registered with the MBeanServer at the
      point the Connector is started.</para>

      <bridgehead>Handler implementations</bridgehead>

      <para>The Connectors will maintain a reference to the handler instances
      provided (either indirectly via the MBean proxy or directly via the
      instance object reference). For each request to the server invoker, the
      handler will be called upon. Since the server invokers can be
      multi-threaded (and in most cases would be), this means that the handler
      may receive concurrent calls to handle invocations. Therefore, handler
      implementations should take care to be thread safe in their
      implementations.</para>

      <bridgehead>Stream handler</bridgehead>

      <para>There is also an invocation handler interface that extends the
      ServerInvocationHandler interface specifically for handling of input
      streams as well as normal invocations. See the section on sending
      streams for further details. As for Connector configuration, it is the
      same.</para>

      <bridgehead>HTTP handlers</bridgehead>

      <para>Since there is extra information needed when dealing with the http
      transport, such as headers and response codes, special consideration is
      needed by handlers. The handlers receiving http invocations can get and
      set this extra information via the InvocationRequest that is passed to
      the handler.</para>

      <para>Server invoker for the http transport will add the following to
      the InvocationRequest's request payload map:</para>

      <para><emphasis role="bold">MethodType</emphasis> - the http request
      type (i.e., GET, POST, PUT, HEADER, OPTIONS). Can use the contant value
      HTTPMetadataConstants.METHODTYPE, if don't want to use the actual string
      'MethodType' as the key to the request payload map.</para>

      <para><emphasis role="bold">Path</emphasis> - the url path. Can use the
      contant value HTTPMetadataConstants.PATH, if don't want to use the
      actual string 'Path' as the key to the request payload map.</para>

      <para><emphasis role="bold">HttpVersion</emphasis> - the client's http
      version. Can use the contant value HTTPMetadataConstants.HTTPVERSION, if
      don't want to use the actual string 'HttpVersion' as the key to the
      request payload map.</para>

      <para>Other properties from the original http request will also be
      included in the request payload map, such as request headers. Can
      reference
      org.jboss.test.remoting.transport.http.method.MethodInvocationHandler as
      an example for pulling request properties from the
      InvocationRequest.</para>

      <para>The only time this will not be added is a POST request where an
      InvocationRequest is passed and is not binary content type
      (application/octet-stream).</para>

      <para>The handlers receiving http invocations can also set the response
      code, response message, and response headers. To do this, will need to
      get the return payload map from the InvocationRequest passed (via its
      getReturnPayload() method). Then populate this map with whatever
      properties needed. For response code and message, will need to use the
      following keys for the map:</para>

      <para><emphasis role="bold">ResponseCode</emphasis> - Can use the
      constant value HTTPMetaDataConstants.RESPONSE_CODE, if don't want to use
      the actual string 'ResponseCode' as they key. <emphasis
      role="bold">IMPORTANT</emphasis> - The value put into map for this key
      MUST be of type java.lang.Integer.</para>

      <para><emphasis role="bold">ResponseCodeMessage</emphasis> - Can use the
      constant value HTTPMetadataConstants.RESPONSE_CODE_MESSAGE, if don't
      want to use the actual string 'ResponseCodeMessage' as the key. The
      value put into map for this key should be of type
      java.lang.String.</para>

      <para>Is also important to note that ALL http requests will be passed to
      the handler. So even OPTIONS, HEAD, and PUT method requests will need to
      be handled. So, for example, if want to accept OPTIONS method requests,
      would need to populate response map with key of 'Allow' and value of
      'OPTIONS, POST, GET, HEAD, PUT', in order to tell calling client that
      all these method types are allowed. Can see an example of how to do this
      within
      org.jboss.test.remoting.transport.http.method.MethodInvocationHandler.</para>

      <para>The PUT request will be handled the same as a POST method request
      and the PUT request payload will be included within the
      InvocationRequest passed to the server handler. It is up to the server
      handler to set the proper resonse code (or throw proper exception) for
      the processing of the PUT request. See <ulink
      url="http://www.ietf.org/rfc/rfc2616.txt?number=2616">
      http://www.ietf.org/rfc/rfc2616.txt?number=2616 </ulink>, section 9.6
      for details on response codes and error responses).</para>

      <bridgehead>HTTP Client</bridgehead>

      <para>The HttpClientInvoker will now put the return from
      HTTPURLConnection's getHeaderFields() method into the metadata map
      passed to the Client's invoke() method (if not null). This means that if
      the caller passes a non-null Map, it can then get the response headers.
      It is important to note that each response header field key in the
      metadata map is associated with a list of response header values, so to
      get a value, would need code similar to:</para>

      <programlisting>Object response = remotingClient.invoke((Object) null, metadata); 
String allowValue = (String) ((List) metadata.get("Allow").get(0);
</programlisting>

      <para>Can reference
      org.jboss.test.remoting.transport.http.method.HTTPInvokerTestClient for
      an example of this.</para>

      <para>Note that when making a http request using the OPTIONS method
      type, the return from the Client's invoke() method will ALWAYS be
      null.</para>

      <para>Also, if the response code is 400, the response returned will be
      that of the error stream and not the standard input stream. So is
      important to check for the response code.</para>

      <para>Two values that will always be set within the metadata map passed
      to the Client's invoke() method (when not null), is the response code
      and response message from the server. These can be found using the
      keys:</para>

      <para><emphasis role="bold">ResponseCode</emphasis> - Can use the
      constant value HTTPMetaDataConstants.RESPONSE_CODE, if don't want to use
      the actual string 'ResponseCode' as the key. <emphasis
      role="bold">IMPORTANT</emphasis> - The value returned for this key will
      be of type java.lang.Integer.</para>

      <para><emphasis role="bold">ResponseCodeMessage</emphasis> - Can use the
      constant value from HTTPMetadataConstants.RESPONSE_CODE_MESSAGE, if
      don't want to use the actual string 'ResponseCodeMessage' as the key.
      The value returned for this key will be of type java.lang.String.</para>

      <para>An example of getting the response code can be found within
      org.jboss.test.remoting.transport.http.method.HTTPInvokerTestClient.</para>
    </section>

    <section>
      <title>Discovery (Detectors)</title>

      <bridgehead>Domains</bridgehead>

      <para>Detectors have the ability to accept multiple domains. What
      domains that the detector will accept as viewable can either be set
      programmatically via the method:</para>

      <para><code>public void setConfiguration(org.w3c.dom.Element xml)
      </code></para>

      <para>or by adding to jboss-service.xml configuration for the detector.
      The domains that the detector is currently accepting can be retrieved
      from the method:</para>

      <para><code>public org.w3c.dom.Element getConfiguration()</code></para>

      <para>The configuration xml is a MBean attribute of the detector, so can
      be set or retrieved via JMX.</para>

      <para>There are three possible options for setting up the domains that a
      detector will accept. The first is to not call the
      <code>setConfiguration()</code> method (or just not add the
      configuration attribute to the service xml). This will cause the
      detector to use only its domain and is the default behavior. This
      enables it to be backwards compatible with earlier versions of JBoss
      Remoting (JBoss 4, DR2 and before).</para>

      <para>The second is to call the <code>setConfiguration()</code> method
      (or add the configuration attribute to the service xml) with the
      following xml element:</para>

      <programlisting>    
          &lt;domains&gt;
            &lt;domain&gt;domain1&lt;/domain&gt;
            &lt;domain&gt;domain2&lt;/domain&gt;
          &lt;/domains&gt;
         </programlisting>

      <para>where <code>domain1</code> and <code>domain2</code> are the two
      domains you would like the detector to accept. This will cause the
      detector to accept detections only from the domains specified, and no
      others.</para>

      <para>The third and final option is to call the setConfiguration()
      method (or add the configuration attribute to the service xml) with the
      following xml element:</para>

      <programlisting>
          &lt;domains&gt;
          &lt;/domains&gt;
      </programlisting>

      <para>This will cause the detector to accept all detections from any
      domain.</para>

      <para>By default, remoting detection will ignore any detection message
      the it receives from a server invoker running within its own jvm. To
      disable this, add an element called 'local' to the detector
      configuration (alongside the domain element) to indicate should accept
      detection messages from local server invokers. This will be false by
      default, so maintains the same behavior as previous releases. For
      example:</para>

      <programlisting>        &lt;domains&gt;
            &lt;domain&gt;domain1&lt;/domain&gt;
            &lt;domain&gt;domain2&lt;/domain&gt;
        &lt;/domains&gt;
        &lt;local/&gt; </programlisting>

      <para>An example entry of a Multicast detector in the jboss-service.xml
      that accepts detections only from the roxanne and sparky domains using
      port 5555, including servers in the same jvm, is as follows:</para>

      <programlisting>
         &lt;mbean code="org.jboss.remoting.detection.multicast.MulticastDetector"
               name="jboss.remoting:service=Detector,transport=multicast"&gt;
            &lt;attribute name="Port"&gt;5555&lt;/attribute&gt;
            &lt;attribute name="Configuration"&gt;
              &lt;domains&gt;
                &lt;domain&gt;roxanne&lt;/domain&gt;
                &lt;domain&gt;sparky&lt;/domain&gt;
              &lt;/domains&gt;
              &lt;local/&gt;
            &lt;/attribute&gt;
         &lt;/mbean&gt;
      </programlisting>

      <bridgehead>Global Detector Configuration</bridgehead>

      <para>The following are configuration attributes for all the remoting
      detectors.</para>

      <para><emphasis role="bold">DefaultTimeDelay</emphasis> - amount of
      time, in milliseconds, which can elapse without receiving a detection
      event before suspecting that a server is dead and performing an explicit
      invocation on it to verify it is alive. If this invocation, or ping,
      fails, the server will be removed from the network registry. The default
      is 5000 milliseconds.</para>

      <para><emphasis role="bold">HeartbeatTimeDelay</emphasis> - amount of
      time to wait between sending (and sometimes receiving) detection
      messages. The default is 1000 milliseconds.</para>

      <bridgehead>JNDIDetector</bridgehead>

      <para><emphasis role="bold">Port</emphasis> - port to which detector
      will connect for the JNDI server.</para>

      <para><emphasis role="bold">Host</emphasis> - host to which the detector
      will connect for the JNDI server.</para>

      <para><emphasis role="bold">ContextFactory</emphasis> - context factory
      string used when connecting to the JNDI server. The default is
      <code>org.jnp.interfaces.NamingContextFactory</code> .</para>

      <para><emphasis role="bold">URLPackage</emphasis> - url package string
      to use when connecting to the JNDI server. The default is
      <code>org.jboss.naming:org.jnp.interfaces</code> .</para>

      <para><emphasis role="bold">CleanDetectionNumber</emphasis> - Sets the
      number of detection iterations before manually pinging remote server to
      make sure still alive. This is needed since remote server could crash
      and yet still have an entry in the JNDI server, thus making it appear
      that it is still there. The default value is 5.</para>

      <para>Can either set these programmatically using setter method or as
      attribute within the remoting-service.xml (or anywhere else the service
      is defined). For example:</para>

      <programlisting>
         &lt;mbean code="org.jboss.remoting.detection.jndi.JNDIDetector"
               name="jboss.remoting:service=Detector,transport=jndi"&gt;
            &lt;attribute name="Host"&gt;localhost&lt;/attribute&gt;
            &lt;attribute name="Port"&gt;5555&lt;/attribute&gt;
         &lt;/mbean&gt;
      </programlisting>

      <para>If the JNDIDetector is started without the Host attribute being
      set, it will try to start a local JNP instance (the JBoss JNDI server
      implementation) on port 1088.</para>

      <bridgehead>MulticastDetector</bridgehead>

      <para><emphasis role="bold">DefaultIP</emphasis> - The IP that is used
      to broadcast detection messages on via multicast. To be more specific,
      will be the ip of the multicast group the detector will join. This
      attribute is ignored if the Address has already been set when started.
      Default is 224.1.9.1.</para>

      <para><emphasis role="bold">Port</emphasis> - The port that is used to
      broadcast detection messages on via multicast. Default is 2410.</para>

      <para><emphasis role="bold">BindAddress</emphasis> - The address to bind
      to for the network interface.</para>

      <para><emphasis role="bold">Address</emphasis> - The IP of the multicast
      group that the detector will join. The default will be that of the
      DefaultIP if not explicitly set.</para>
    </section>

    <section>
      <title>Transports (Invokers)</title>

      <section>
        <title>Server Invokers</title>

        <para>The following configuration properties are common to all the
        current server invokers.</para>

        <para><emphasis role="bold">serverBindAddress</emphasis> - The address
        on which the server binds to listen for requests. The default is an
        empty value which indicates the server should be bound to the host
        provided by the locator url, or if this value is null, the local host
        as provided by <code>InetAddress.getLocalHost()</code> .</para>

        <para><emphasis role="bold">serverBindPort</emphasis> - The port to
        listen for requests on. A value of 0 or less indicates that a free
        anonymous port should be chosen.</para>

        <para><emphasis role="bold">maxNumThreadsOneway</emphasis> - specifies
        the maximum number of threads to be used within the thread pool for
        accepting one way invocations on the server side. This property will
        only be used in the case that the default thread pool is used. If a
        custom thread pool is set, this property will have no meaning. This
        property can also be retrieved or set programmatically via the
        <code>MaxNumberOfOnewayThreads</code> property.</para>

        <para><emphasis role="bold">onewayThreadPool</emphasis> - specifies
        either the fully qualified class name for a class that implements the
        <code>org.jboss.util.threadpool.ThreadPool</code> interface or the JMX
        ObjectName for an MBean that implements the
        <code>org.jboss.util.threadpool.ThreadPool</code> interface. This will
        replace the default
        <code>org.jboss.util.threadpool.BasicThreadPool</code> used by the
        server invoker.</para>

        <para>Note that this value will NOT be retrieved until the first
        one-way (server side) invocation is made. So if the configuration is
        invalid, will not be detected until this first call is made. The
        thread pool can also be accessed or set via the
        <code>OnewayThreadPool</code> property programmatically.</para>

        <para>Important to note that the default thread pool used for the
        one-way invocations on the server side will block the calling thread
        if all the threads in the pool are in use until one is
        released.</para>
                
      </section>

      <section>
        <title>Configurations affecting the invoker client</title>

        <para>There are some configurations which will impact the invoker
        client. These will be communicated to the client invoker via
        parameters in the Locator URI. These configurations can not be changed
        during runtime, so can only be set up upon initial configuration of
        the server invoker on the server side. The following is a list of
        these and their effects.</para>

        <para><emphasis role="bold">clientConnectPort</emphasis> - the port
        the client will use to connect to the remoting server. This would be
        needed in the case that the client will be going through a router that
        forwards requests made externally to a different port
        internally.</para>

        <para><emphasis role="bold">clientConnectAddress</emphasis> - the ip
        or hostname the client will use to connect to the remoting server.
        This would be needed in the case that the client will be going through
        a router that forwards requests made externally to a different ip or
        host internally.</para>

        <para>If no client connect address or server bind address specified,
        will use the local host's address (via
        <code>InetAddress.getLocalHost().getHostAddress()</code> ).</para>
      </section>

      <section>
        <title>How the server bind address and port is ultimately
        determined</title>

        <para>If the serverBindAddress property is set, it will be used for
        binding. If the serverBindAddress is not set, but the
        clientConnectAddress property is set, the server invoker will bind to
        local host address. If neither the serverBindAddress nor the
        clientConnectAddress properties are set, then will try to bind to the
        host specified within the InvokerLocator. If the host value of the
        InvokerLocator is also not set, will bind to local host.</para>

        <para>If there is a system property called 'remoting.bind_by_host' and
        if is false, will bind by IP address instead of host. Otherwise will
        use host name. This only applies when configured address is 0.0.0.0.
        To facilitate setting this property, the following static variable is
        defined in <classname>InvokerLocator</classname>:</para>

        <programlisting>
           public static final String BIND_BY_HOST = "remoting.bind_by_host";
        </programlisting>

        <para>If the serverBindPort property is set, it will be used. If this
        value is 0 or a negative number, then the next available port will be
        found and used. If the serverBindPort property is not set, but the
        clientConnectPort property is set, then the next available port will
        be found and used. If neither the serverBindPort nor the
        clientConnectPort is set, then the port specified in the original
        InvokerLocator will be used. If this is 0 or a negative number, then
        the next available port will be found and used. In the case that the
        next available port is used because either the serverBindPort or the
        original InvokerLocator port value was either 0 or negative, the
        InvokerLocator will be updated to reflect the new port value.</para>
      </section>

      <section>
        <title>Socket Invoker</title>

        <para>The following configuration properties can be set at any time,
        but will not take effect until the socket invoker, on the server side,
        is stopped and restarted.</para>

        <para><emphasis role="bold">timeout</emphasis> - The socket timeout
        value passed to the Socket.setSoTimeout() method. The default on the
        server side is 60000 (one minute). If the timeout parameter is set,
        its value will also be passed to the client side (see below).</para>

        <para><emphasis role="bold">backlog</emphasis> - The preferred number
        of unaccepted incoming connections allowed at a given time. The actual
        number may be greater than the specified backlog. When the queue is
        full, further connection requests are rejected. Must be a positive
        value greater than 0. If the value passed if equal or less than 0,
        then the default value will be assumed. The default value is
        200.</para>

        <para><emphasis role="bold">numAcceptThreads</emphasis> - The number
        of threads that exist for accepting client connections. The default is
        1.</para>

        <para><emphasis role="bold">maxPoolSize</emphasis> - The number of
        server threads for processing client. The default is 300.</para>

        <para><emphasis role="bold">serverSocketClass</emphasis> - specifies
        the fully qualified class name for the custom SocketWrapper
        implementation to use on the server.</para>

        <bridgehead>Configurations affecting the Socket invoker
        client</bridgehead>

        <para>There are some configurations which will impact the socket
        invoker client. These will be communicated to the client invoker via
        parameters in the Locator URI. These configurations can not be changed
        during runtime, so can only be set up upon initial configuration of
        the socket invoker on the server side. The following is a list of
        these and their effects.</para>

        <para><emphasis role="bold">enableTcpNoDelay</emphasis> - can be
        either true or false and will indicate if client socket should have
        TCP_NODELAY turned on or off. TCP_NODELAY is for a specific purpose;
        to disable the Nagle buffering algorithm. It should only be set for
        applications that send frequent small bursts of information without
        getting an immediate response; where timely delivery of data is
        required (the canonical example is mouse movements). The default is
        false.</para>

        <para><emphasis role="bold">timeout</emphasis> - The socket timeout
        value passed to the Socket.setSoTimeout() method. The default on the
        client side is 1800000 (or 30 minutes).</para>

        <para><emphasis role="bold">clientMaxPoolSize</emphasis> - the client
        side maximum number of threads. The default is 10.</para>

        <para><emphasis role="bold">clientSocketClass</emphasis> - specifies
        the fully qualified class name for the custom SocketWrapper
        implementation to use on the client. Note, will need to make sure this
        is marked as a client parameter (using the 'isParam' attribute).
        Making this change will not affect the marshaller/unmarshaller that is
        used, which may also be a requirement.</para>

        <para>An example of locator uri for a socket invoker that has
        TCP_NODELAY set to false and the client’s max pool size of 30 would
        be:</para>

        <para><code>
        socket://test.somedomain.com:8084/?enableTcpNoDelay=false&amp;maxPoolSize=30
        </code></para>

        <para>To reiterate, these client configurations can only be set within
        the server side configuration and will not change during
        runtime.</para>
      </section>

      <section>
        <title>SSL Socket Invoker</title>

        <para>Supports all the configuration attributes as the Socket Invoker,
        plus the following:</para>

        <para><emphasis role="bold">serverSocketFactory</emphasis> - Sets the
        server socket factory. If want ssl support use a server socket factory
        that supports ssl. The only requirement is that the server socket
        factory value must be an ObjectName, meaning the server socket factory
        implementation must be an MBean and also MUST implement the
        <code>org.jboss.remoting.security.ServerSocketFactoryMBean</code>
        interface.</para>
      </section>

      <section>
        <title>RMI Invoker</title>

        <para><emphasis role="bold">registryPort</emphasis> - the port on
        which to create the RMI registry. The default is 3455. This also needs
        to have the isParam attribute set to true.</para>
      </section>

      <section>
        <title>SSL RMI Invoker</title>

        <para>This is essentially identical to the RMI invoker, except that it
        creates SSL socket and server socket factories by default.</para>

        <para><emphasis role="bold">Note.</emphasis> Both the RMI and SSL RMI
        server invokers create a socket factory and pass it to a client
        invoker along with the RMI stub. Therefore, the socket factory must be
        serializable. If the SSL RMI server invoker is allowed to create an
        <classname>SSLSocketFactory</classname> from SSL parameters, it will
        take care to create a serializable socket factory. However, if a
        socket factory is passed in to the server invoker by one of the
        methods discussed earlier, then the user is responsible for supplying
        a serializable socket factory.</para>

        <para>The rules discussed above for configuring socket and server
        socket factories apply to the SSL RMI transport, but there is a twist,
        since the server invoker creates the (client) socket factory and
        packages it with its own stub. The server invoker creates a copy of
        <classname>org.jboss.remoting.transport.rmi.ssl.SerializableSSLClientSocketFactory</classname>,
        which is essentially just a holder for the configuration map passed to
        the server invoker, with any parameters removed which concern trust
        store and key store configuration. On the client side, when a client
        SSL RMI invoker is created, it stores its own configuration map in a
        static variable which the transferred
        <classname>SerializableSSLClientSocketFactory</classname> can retrieve
        and merge with the configuration information it brought with it from
        the server. In particular, if a socket factory is explicitly passed to
        the client invoker, then
        <classname>SerializableSSLClientSocketFactory</classname> will use it.
        If not, then <classname>SerializableSSLClientSocketFactory</classname>
        will use any key store and trust store information passed to the
        client to create and configure a socket factory.</para>
      </section>

      <section>
        <title>HTTP Invoker</title>

        <para>The HTTP server invoker implementation is based on the Apache
        Tomcat connector components which support GET, POST, HEAD, OPTIONS,
        and HEAD method types and keep-alive. Therefore, most any
        configuration allowed for Tomcat can be configured for the remoting
        HTTP server invoker. For more information on the configuration
        attributes available for the Tomcat connectors, please refer to <ulink
        url="http://tomcat.apache.org/tomcat-5.5-doc/config/http.htm">http://tomcat.apache.org/tomcat-5.5-doc/config/http.htm</ulink>.
        <!--<link linkend="???">http://tomcat.apache.org/tomcat-5.5-doc/config/http.html</link>-->
        So for example, if wanted to set the maximum number of threads to be
        used to accept incoming http requests, would use the 'maxThreads'
        attribute. The only exception when should use remoting configuration
        over the Tomcat configuration is for attribute 'address' (use
        serverBindAddress instead) and attribute 'port' (use serverBindPort
        instead).</para>

        <para>Note: The http invoker no longer has the configuration
        attributes 'maxNumThreadsHTTP' or 'HTTPThreadPool' as thread pooling
        is now handled within the Tomcat connectors, which does not expose
        external API for setting these.</para>

        <para>Since the remoting HTTP server invoker implementation is using
        Tomcat connectors, is possible to swap out the Tomcat protocol
        implementations being used. By default, the protocol being used is
        <code>org.apache.coyote.http11.Http11Protocol</code>. However, it is
        possible to switch to use the
        <code>org.apache.coyote.http11.Http11AprProtocol</code> protocol,
        which is based on the Apache Portable Runtime (see <ulink
        url="http://tomcat.apache.org/tomcat-5.5-doc/apr.html">http://tomcat.apache.org/tomcat-5.5-doc/apr.html</ulink>
        <!--<link linkend="???">http://tomcat.apache.org/tomcat-5.5-doc/apr.html</link>-->
        and <ulink url="http://apr.apache.org/">http://apr.apache.org/</ulink>
        <!--<link linkend="???">http://apr.apache.org/</link>--> for more
        details). If want to use the APR implementation, simply put the
        tcnative-1.dll (or tcnative-1.so) on the system path so can be loaded.
        The APR native binaries can be found at <ulink
        url="http://tomcat.heanet.ie">http://tomcat.heanet.ie</ulink>.<!--<link linkend="???">http://tomcat.heanet.ie</link>--></para>

        <para>Note: There is a bug with release 1.1.1 of APR where get an
        error upon shutting down (see JBREM-277 for more information). This
        does not impact anything while running, but is still an issue when
        shutting down (as upon starting up again, can get major problems).
        This should be fixed in a later release of APR and since can just
        replace the 1.1.1 version of tcnative-1.dll with the new one.</para>

        <bridgehead>Client request headers</bridgehead>

        <para>The HTTP Invoker allows for some of the properties to be passed
        as request headers from client caller. The following are possible http
        headers and what they mean:</para>

        <para><emphasis role="bold">sessionId</emphasis> - is the remoting
        session id to identify the client caller. If this is not passed, the
        HTTP server invoker will try to create a session id based on
        information that is passed. Note, this means if the sessionId is not
        passed as part of the header, there is no gurantee that the sessionId
        supplied to the invocation handler will always indicate the request
        from the same client.</para>

        <para><emphasis role="bold">subsystem</emphasis> - the subsystem to
        call upon (which invoker handler to call upon). If there is more than
        one handler per Connector, this will need to be set (otherwise will
        just use the only one available).</para>

        <para>These request headers are set automatically when using a
        remoting client, but if using another client to send request to the
        HTTP server invoker, may want to add these headers.</para>

        <bridgehead>Exception Handling</bridgehead>

        <para>When using remoting on the client side to connect to a remoting
        server (or any web server for that matter) via the http transport, if
        the server returns a response code greater than 400, the remoting
        client will read the error stream and return that as the response.
        Thus, the response returned will be of type java.lang.Exception. NOTE:
        this does NOT mean that the call to the Client's invoke() method will
        throw the exception, but instead will return the actual Exception
        object instance as a normally returned response. Therefore, is
        important that if want to check if response is an error instead of
        normal response, will need to look at the response code put in the
        metadata Map passed to the invoke() method on the Client instance. See
        the HTTP Handler section above for more details.</para>
      </section>

      <section>
        <title>HTTPS Invoker</title>

        <para>Supports all the configuration attributes as the HTTP Invoker,
        plus the following:</para>

        <para><emphasis role="bold">serverSocketFactory</emphasis> - Sets the
        server socket factory. If want ssl support, use a server socket
        factory that supports ssl. The only requirement is that the server
        socket factory value must be an ObjectName, meaning the server socket
        factory implementation must be an MBean and also MUST implement the
        <code>org.jboss.remoting.security.ServerSocketFactoryMBean</code>
        interface.</para>

        <para><emphasis role="bold">SSLImplementation</emphasis> - Sets the
        Tomcat SSLImplementation to use. This should always be
        <code>org.jboss.remoting.transport.coyote.ssl.RemotingSSLImplementation</code>.</para>
      </section>

      <section>
        <title>HTTP(S) Client Invoker - proxy and basic authentication</title>

        <para>This section covers configuration specific to the HTTP Client
        Invoker only and is NOT related to HTTP(S) invoker configuration on
        the server side (via service xml).</para>

        <bridgehead>proxy</bridgehead>

        <para>There are a few ways in which to enable http proxy using the
        HTTP client invoker. The first is simply to add the following
        properties to the metadata Map passed on the Client's invoke() method:
        <code>http.proxyHost</code> and <code>http.proxyPort</code></para>

        <para>An example would be:</para>

        <programlisting>
               Map metadata = new HashMap();
               ...

               // proxy info
               metadata.put("http.proxyHost", "ginger");
               metadata.put("http.proxyPort", "80");

               ...

               response = client.invoke(payload, metadata);
            </programlisting>

        <para>The http.proxyPort property is not required and if not present,
        will use default of 80.</para>

        <para>The other way to enable use of an http proxy server from the
        HTTP client invoker is to set the following system properties (either
        via <code>System.setProperty()</code> method call or via JVM
        arguments): <code>http.proxyHost</code>, <code>http.proxyPort</code>,
        and <code>proxySet</code></para>

        <para>An example would be setting the following JVM arguments:</para>

        <programlisting>-Dhttp.proxyHost=ginger -Dhttp.proxyPort=80 -DproxySet=true</programlisting>

        <para>Note: when testing with Apache 2.0.48 (mod_proxy and
        mod_proxy_http), all of the properties above were required.</para>

        <para>Setting the system properties will take precedence over setting
        the metadata Map.</para>

        <bridgehead>Basic authentication - direct and via proxy</bridgehead>

        <para>The HTTP client invoker also has support for BASIC
        authentication for both proxied and non-proxied invocations. For
        proxied invocations, the following properties need to be set:
        <code>http.proxy.username</code> and
        <code>http.proxy.password</code>.</para>

        <para>For non-proxied invocations, the following properties need to be
        set: <code>http.basic.username</code> and
        <code>http.basic.password</code>.</para>

        <para>For setting either proxied or non-proxied properties, can be
        done via the metadata map or system properties (see setting proxy
        properties above for how to). However, for authentication properties,
        values set in the metadata Map will take precedence over those set
        within the system properties.</para>

        <para>Note: Only the proxy authentication has been tested using Apache
        2.0.48; non-proxied authentication has not.</para>

        <para>Since there are many different ways to do proxies and
        authentication in this great world of web, not all possible
        configurations have been tested (or even supported). If you find a
        particular problem or see that a particular implementation is not
        supported, please enter an issue in Jira ( <!--<link linkend="???">http://jira.jboss.com</link>-->
        <ulink url="http://jira.jboss.com">http://jira.jboss.com</ulink> )
        under the JBossRemoting project, as this is where bugs and feature
        requests belong. If after reading the documentation have unanswered
        questions about how to use these features, please post them to the
        remoting forum ( <!--<link linkend="???">http://www.jboss.org/index.html?module=bb&amp;op=viewforum&amp;f=176</link> -->
        <ulink
        url="http://www.jboss.org/index.html?module=bb&amp;op=viewforum&amp;f=176">
        http://www.jboss.org/index.html?module=bb&amp;op=viewforum&amp;f=176
        </ulink> ).</para>

        <bridgehead>Host name verification</bridgehead>

        <para>During the SSL handshake when making client calls using https
        transport, if the URL's hostname and the server's identification
        hostname mismatch, a javax.net.ssl.HostnameVerifier implementation
        will be called to determine if this connection should be allowed. The
        default implementation will not allow this. To override this behavior
        to allow this by changing the HostnameVerifier implementation, can use
        the 'org.jboss.security.ignoreHttpsHost' property'. This property can
        either be set using a system property or within the metadata Map
        passed to the Client's invoke() method (which will override both the
        default value and the setting from the system property).</para>
      </section>

      <section>
        <title>Servlet Invoker</title>

        <para>The servlet invoker is a server invoker implementation that uses
        a servlet running within a web container to accept initial client
        invocation requests. The servlet request is then passed on to the
        servlet invoker for processing.</para>

        <para>The deployment for this particular server invoker is a little
        different than the other server invokers since a web deployment is
        also required. To start, the servlet invoker will need to be
        configured and deployed. This can be done by adding the Connector
        MBean service to an existing service xml or creating a new one. The
        following is an example of how to declare a Connector that uses the
        servlet invoker:</para>

        <programlisting>
           &lt;mbean code="org.jboss.remoting.transport.Connector"
                  xmbean-dd="org/jboss/remoting/transport/Connector.xml"
                  name="jboss.remoting:service=Connector,transport=Servlet"
                  display-name="Servlet transport Connector"&gt;

              &lt;attribute name="InvokerLocator"&gt;
                 servlet://localhost:8080/servlet-invoker/ServerInvokerServlet
              &lt;/attribute&gt;

              &lt;attribute name="Configuration"&gt;
                 &lt;config&gt;
                    &lt;handlers&gt;
                       &lt;handler subsystem="test"&gt;
                          org.jboss.test.remoting.transport.web.WebInvocationHandler
                       &lt;/handler&gt;
                    &lt;/handlers&gt;
                 &lt;/config&gt;
              &lt;/attribute&gt;
           &lt;/mbean&gt;
        </programlisting>

        <para>An important point of configuration to note is that the value
        for the InvokerLocator attribute is the exact url used to access the
        servlet for the servlet invoker (more on how to define this below),
        with the exception of the protocol being servlet instead of http. This
        is important because if using automatic discovery, this is the locator
        url that will be discovered and used by clients to connect to this
        server invoker.</para>

        <para>The next step is to configure and deploy the servlet that fronts
        the servlet invoker. The pre-built deployment file for this servlet is
        the servlet-invoker.war file (which can be found in the release
        distribution or under the output/lib/ directory if doing a source
        build). By default, it is actually an exploded war, so the
        servlet-invoker.war is actually a directory so that can be more easily
        configured (feel free to zip up into an actual war file if prefer). In
        the WEB-INF directory is located the web.xml file. This is a standard
        web configuration file and should look like:</para>

        <programlisting>
           &lt;?xml version="1.0" encoding="UTF-8"?&gt;
           &lt;!DOCTYPE web-app PUBLIC
               "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
               "http://java.sun.com/dtd/web-app_2_3.dtd"&gt;

           &lt;!--The the JBossRemoting server invoker servlet web.xml descriptor--&gt;
           &lt;web-app&gt;
              &lt;servlet&gt;
                 &lt;servlet-name&gt;ServerInvokerServlet&lt;/servlet-name&gt;
                 &lt;description&gt;The ServerInvokerServlet receives requests via HTTP protocol
                    from within a web container and passes it onto the ServletServerInvoker for processing.
                 &lt;/description&gt;
                 &lt;servlet-class&gt;
                    org.jboss.remoting.transport.servlet.web.ServerInvokerServlet
                 &lt;/servlet-class&gt;
                 &lt;init-param&gt;
                    &lt;param-name&gt;invokerName&lt;/param-name&gt;
                    &lt;param-value&gt;
                       jboss.remoting:service=invoker,transport=servlet
                    &lt;/param-value&gt;
                    &lt;description&gt;The servlet server invoker&lt;/description&gt;
                 &lt;/init-param&gt;
                 &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
              &lt;/servlet&gt;
              &lt;servlet-mapping&gt;
                 &lt;servlet-name&gt;ServerInvokerServlet&lt;/servlet-name&gt;
                 &lt;url-pattern&gt;/ServerInvokerServlet/*&lt;/url-pattern&gt;
              &lt;/servlet-mapping&gt;
           &lt;/web-app&gt;
        </programlisting>

        <para>This file can be changed to meet any web requirements you might
        have, such as adding security or changing the actual url context that
        the servlet maps to. If the url that the servlet maps to is changed,
        will need to change the value for the InvokerLocator in the Connector
        configuration mentioned above. Also note that there is a parameter,
        invokerName, that has the value of the object name of the servlet
        server invoker. This is what the ServerInvokerServlet uses to look up
        the server invoker which it will pass the requests on to.</para>

        <para>Due to the way the servlet invoker is currently configured and
        deployed, it must run within the JBoss application server and is not
        portable to other web servers.</para>

        <bridgehead>Exception handling</bridgehead>

        <para>If the ServletServerInvoker catches any exception thrown from
        the invocation handler invoke() call, it will send an error to the
        client with a status of 500 and include the original exception message
        as its error message. From the client side, the client invoker will
        actually throw a CannotConnectException, which will have root
        exception as its cause. The cause should be an IOException with the
        server's message. For example, the stack trace from the exception
        thrown within the test case
        org.jboss.remoting.transport.servlet.test.ServletInvokerTestClient
        is:</para>

        <programlisting>
               org.jboss.remoting.CannotConnectException: Can not connect http client invoker.
               at org.jboss.remoting.transport.http.HTTPClientInvoker.useHttpURLConnection(HTTPClientInvoker.java:154)
               at org.jboss.remoting.transport.http.HTTPClientInvoker.transport(HTTPClientInvoker.java:68)
               at org.jboss.remoting.RemoteClientInvoker.invoke(RemoteClientInvoker.java:113)
               at org.jboss.remoting.Client.invoke(Client.java:221)
               at org.jboss.remoting.Client.invoke(Client.java:184)
               at
               org.jboss.remoting.transport.servlet.test.ServletInvokerTestClient.testInvocation(ServletInvokerTestClient.java:65)
               at
               org.jboss.remoting.transport.servlet.test.ServletInvokerTestClient.main(ServletInvokerTestClient.java:98)
               at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
               at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
               at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
               at java.lang.reflect.Method.invoke(Method.java:324)
               at com.intellij.rt.execution.application.AppMain.main(AppMain.java:78)
               Caused by: java.io.IOException: Server returned HTTP response code: 500 for URL:
               http://localhost:8080/servlet-invoker/ServerInvokerServlet
               at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:791)
               at org.jboss.remoting.transport.http.HTTPClientInvoker.useHttpURLConnection(HTTPClientInvoker.java:139)
               ... 11 more
            </programlisting>

        <bridgehead>Issues</bridgehead>

        <para>One of the issues of using Servlet invoker is that the
        invocation handlers (those that implement ServerInvocationHandler) can
        not return very much detail in regards to a web context. For example,
        the content type used for the response is the same as that of the
        request.</para>
      </section>

      <section>
        <title id="section-multiplex" xreflabel="Multiplex Invoker">Multiplex
        Invoker</title>

        <para>The multiplex invoker is intended to replicate the functionality
        of the socket invoker with the added feature that it supports multiple
        streams of communication over a single pair of sockets. Multiplexing
        may be motivated by, for example, a desire to conserve socket
        resources or by firewall restrictions on port availability. This
        additional service is made possible by the Multiplex subproject, which
        provides "virtual" sockets and "virtual" server sockets. Please refer
        to the Multiplex documentation at</para>

        <blockquote>
          <para><ulink
          url="http://labs.jboss.com/portal/jbossremoting/docs/index.html">
          http://labs.jboss.com/portal/jbossremoting/docs/index.html</ulink></para>
        </blockquote>

        <para>for further details.</para>

        <para>In a typical multiplexed scenario a
        <classname>Client</classname> on a client host, through a
        <classname>MultiplexClientInvoker</classname> <emphasis>C</emphasis>,
        could make synchronous method invocations to a
        <classname>MultiplexServerInvoker</classname> on a server host, and at
        the same time (and over the same TCP connection) asynchronous push
        callbacks could be made to a
        <classname>MultiplexServerInvoker</classname> <emphasis>S</emphasis>
        on the client host. In this, the <emphasis role="bold">Prime
        Scenario</emphasis>, which motivated the creation of the multiplex
        invoker, <emphasis>C</emphasis> and <emphasis>S</emphasis> use two
        different virtual sockets but share the same port and same actual
        socket. We say that <emphasis>C</emphasis> and <emphasis>S</emphasis>
        belong to the same <emphasis role="bold">invoker
        group</emphasis>.</para>

        <para>One of the primary design goals of the Multiplex subsystem is
        for virtual sockets and virtual server sockets to demonstrate behavior
        as close as possible to their real counterparts, and, indeed, they
        implement complete socket and server socket APIs. However, they are
        necessarily different in some respects, and it follows that the
        multiplex invoker is somewhat different than the socket invoker. In
        particular, there are three areas specific to the multiplex invoker
        that must be understood in order to use it effectively:</para>

        <orderedlist>
          <listitem>
            <para>Establishing on the server an environment prerequisite for
            creating multiplex connections</para>
          </listitem>

          <listitem>
            <para>Configuring the client for multiplexed method invocations
            and callbacks</para>
          </listitem>

          <listitem>
            <para>Shutting down invoker groups.</para>
          </listitem>
        </orderedlist>

        <section>
          <title>Setting up the server</title>

          <para>There are two kinds of
          <classname>MultiplexServerInvoker</classname>s, <emphasis
          role="bold">master</emphasis> and <emphasis
          role="bold">virtual</emphasis>, corresponding to the two kinds of
          virtual server sockets: <classname>MasterServerSocket</classname>
          and <classname>VirtualServerSocket</classname>. Briefly, the
          difference between the two virtual server socket classes is that a
          <classname>MasterServerSocket</classname> is derived from
          <classname>java.net.ServerSocket</classname> and its
          <methodname>accept()</methodname> method is implemented by way of
          the inherited method <methodname>super.accept()</methodname>. A
          <classname>MasterServerSocket</classname> can accept connect
          requests from multiple machines. A
          <classname>VirtualServerSocket</classname>, on the other hand, is
          based on an actual socket connected to another actual socket on some
          host <emphasis>H</emphasis>, and consequently a
          <classname>VirtualServerSocket</classname> can accept connect
          requests only from <emphasis>H</emphasis>.</para>

          <para>Each multiplex connection depends on a pair of connected real
          sockets, one on the client host and one on the server host, and this
          connection is created when an actual socket contacts an actual
          server socket. It follows that a multiplex connection begins with a
          connection request to a <classname>MasterServerSocket</classname>.
          Once the connection is established, it is possible to build up
          <emphasis role="bold">virtual socket groups</emphasis>, consisting
          of virtual sockets (and at most one
          <classname>VirtualServerSocket</classname>) revolving around the
          actual socket at each end of the connection. Each virtual socket in
          a socket group at one end is connected to a virtual socket in the
          socket group at the other end.</para>

          <para>Master and virtual
          <classname>MultiplexServerInvoker</classname>s assume the
          characteristics of their server sockets:
          <classname>MasterServerSocket</classname> and
          <classname>VirtualServerSocket</classname>, respectively. That is, a
          master <classname>MultiplexServerInvoker</classname> can accept
          requests from any host, while a virtual
          <classname>MultiplexServerInvoker</classname> can accept requests
          only from the particular host to which it has a multiplex
          connection. Since a multiplex connection begins with a connection
          request to a <classname>MasterServerSocket</classname>, it follows
          that the use of the multiplex invoker must begin with a connection
          request from the client (made by either a
          <classname>MultiplexClientInvoker</classname> or a virtual
          <classname>MultiplexServerInvoker</classname>: see below) to a
          master <classname>MultiplexServerInvoker</classname> on the server.
          The master <classname>MultiplexServerInvoker</classname> responds by
          "cloning" itself (metaphorically, not necessarily through the use of
          <methodname>clone()</methodname>) into a virtual
          <classname>MultiplexServerInvoker</classname> with the same
          parameters and same set of invocation handlers but with a
          <classname>VirtualServerSocket</classname> belonging to a new socket
          group. In so doing the master
          <classname>MultiplexServerInvoker</classname> builds up a <emphasis
          role="bold">server invoker farm</emphasis> of virtual
          <classname>MultiplexServerInvoker</classname>s, each in contact with
          a different <classname>MultiplexClientInvoker</classname> over a
          distinct multiplex connection. The virtual
          <classname>MultiplexServerInvoker</classname>s do the actual work of
          responding to method invocation requests, sent by their
          corresponding <classname>MultiplexClientInvoker</classname>s through
          virtual sockets in a socket group at the client end of a multiplex
          connection to virtual sockets created by the
          <classname>VirtualServerSocket</classname> in the socket group at
          the server end of the connection. Note that virtual
          <classname>MultiplexServerInvoker</classname>s share data structures
          with the master, so that registering invocation handlers with the
          master makes them available to the members of the farm. The members
          of a master <classname>MultiplexServerInvoker</classname>'s invoker
          farm are accessible by way of the methods</para>

          <blockquote>
            <orderedlist>
              <listitem>
                <para><methodname>MultiplexServerInvoker.getServerInvokers()</methodname>
                and</para>
              </listitem>

              <listitem>
                <para><methodname>MultiplexServerInvoker.getServerInvoker(InetSocketAddress)</methodname></para>
              </listitem>
            </orderedlist>
          </blockquote>

          <para>the latter of which returns a virtual
          <classname>MultiplexServerInvoker</classname> keyed on the address
          to which its <classname>VirtualServerSocket</classname> is
          connected. When the master
          <classname>MultiplexServerInvoker</classname> shuts down, its farm
          of virtual invokers shuts down as well</para>

          <para>There are two ways of constructing a virtual
          <classname>MultiplexServerInvoker</classname>, one being the cloning
          method just discussed. It is also possible to construct one
          directly. Once a multiplex connection is established, a virtual
          <classname>MultiplexServerInvoker</classname> can be created with a
          <classname>VirtualServerSocket</classname> belonging to a socket
          group at one end of the connection. The
          <classname>MultiplexServerInvoker</classname> constructor determines
          whether to create a virtual or master invoker according to the
          presence or absence of certain parameters, discussed below, that may
          be added to its <classname>InvokerLocator</classname>. Server rules
          1 through 3 described below result in the construction of a virtual
          <classname>MultiplexServerInvoker</classname>, and server rule 4
          (the absence of these parameters) results in the construction of a
          master <classname>MultiplexServerInvoker</classname>.</para>

          <para>Setting up the server, then, is simply a matter of starting a
          master <classname>MultiplexServerInvoker</classname> with a simple
          <classname>InvokerLocator</classname>, unadorned with any parameters
          specific to the multiplex invoker. As always, the server invoker is
          not created directly but by way of a
          <classname>Connector</classname>, as in the following:</para>

          <blockquote>
            <programlisting>
            Connector connector = new Connector();
            Connector.setInvokerLocator("multiplex://demo.jboss.com:8080");
            Connector.create()
            Connector.start()
            </programlisting>
          </blockquote>
        </section>

        <section>
          <title>Setting up the client</title>

          <para>Before multiplex connections can be established, a master
          <classname>MultiplexServerInvoker</classname> must be created as
          described in the previous section. For example, the Prime Scenario
          would begin with starting a master
          <classname>MultiplexServerInvoker</classname> on the server host,
          followed by starting, on the client host, a
          <classname>MultiplexClientInvoker</classname> <emphasis>C</emphasis>
          and a virtual <classname>MultiplexServerInvoker</classname>
          <emphasis>S</emphasis> (in either order). The first to start
          initiates a multiplex connection to the master
          <classname>MultiplexServerInvoker</classname> and requests the
          creation of a virtual <classname>MultiplexServerInvoker</classname>.
          Note that it is crucial for <emphasis>C</emphasis> and
          <emphasis>S</emphasis> to know that they are meant to share a
          multiplex connection, i.e., that they are meant to belong to the
          same invoker group. Consider the following attempt to set up a
          shared connection between hosts bluemonkey.acme.com and
          demo.jboss.com. First, <emphasis>C</emphasis> is initialized on host
          bluemonkey.acme.com with the <classname>InvokerLocator</classname>
          multiplex://demo.jboss.com:8080, and, assuming the absence of an
          existing multiplex connection to demo.jboss.com:8080, a new virtual
          socket group based on a real socket bound to an arbitrary port, say
          32000, is created. Then <emphasis>S</emphasis> is initialized with
          <classname>InvokerLocator</classname>
          multiplex://bluemonkey.acme.com:4444, but since it needs to bind to
          port 4444, it is unable to share the existing connection. [Actually,
          the example is slightly deceptive, since
          multiplex://bluemonkey.acme.com:4040 would result in the creation of
          a master <classname>MultiplexServerInvoker</classname>. But if it
          were suitably extended with the parameters discussed below so that a
          virtual <classname>MultiplexServerInvoker</classname> were created,
          the virtual invoker would be unable to share the existing
          connection.]</para>

          <para>So <emphasis>C</emphasis> and <emphasis>S</emphasis> need to
          agree on the address and port of the real socket underlying the
          virtual socket group they are intended to share on the client host
          and the address and port of the real socket underlying the peer
          virtual socket group on the server host. Or, more succintly, they
          must know that they are meant to belong to the same invoker group.
          Note the relationship between an invoker group and the virtual
          socket group which supports it: a
          <classname>MultiplexClientInvoker</classname> uses virtual sockets
          in its underlying virtual socket group, and a
          <classname>MultiplexServerInvoker</classname> in an invoker group
          has a <classname>VirtualServerSocket</classname> that creates
          virtual sockets in the underlying virtual socket group.</para>

          <para><emphasis>C</emphasis> and <emphasis>S</emphasis> each get
          half of the information necessary to identify their invoker group
          directly from their respective
          <classname>InvokerLocator</classname>s. In particular,
          <emphasis>C</emphasis> gets the remote address and port, and
          <emphasis>S</emphasis> gets the binding address and port. The
          additional information may be provided through the use of <emphasis
          role="bold">invoker group parameters</emphasis>, which may be
          communicated to <emphasis>C</emphasis> and <emphasis>S</emphasis> in
          one of two ways:</para>

          <orderedlist>
            <listitem>
              <para>they may be appended to the
              <classname>InvokerLocator</classname> passed to the
              <classname>Client</classname> which creates
              <emphasis>C</emphasis> and/or to the
              <classname>InvokerLocator</classname> passed to the
              <classname>Connector</classname> which creates
              <emphasis>S</emphasis></para>
            </listitem>

            <listitem>
              <para>they may be stored in a configuration
              <classname>Map</classname> which is passed to the
              <classname>Client</classname> and/or
              <classname>Connector</classname>.</para>
            </listitem>
          </orderedlist>

          <para>In either case, there are two ways in which the missing
          information can be supplied to <emphasis>C</emphasis> and
          <emphasis>S</emphasis>:</para>

          <orderedlist>
            <listitem>
              <para>The information can be provided explicitly by way of
              invoker group parameters:</para>

              <orderedlist>
                <listitem>
                  <para><emphasis>multiplexBindHost</emphasis> and
                  <emphasis>multiplexBindPort</emphasis> parameters can be
                  passed to <emphasis>C</emphasis>, and</para>
                </listitem>

                <listitem>
                  <para><emphasis>multiplexConnectHost</emphasis> and
                  <emphasis>multiplexConnectPort</emphasis> parameters can be
                  passed to <emphasis>S</emphasis>.</para>
                </listitem>
              </orderedlist>
            </listitem>

            <listitem>
              <para><emphasis>C</emphasis> and <emphasis>S</emphasis> can be
              tied together by giving them the same <emphasis
              role="bold">multiplexId</emphasis>, supplied by invoker group
              parameters:</para>

              <orderedlist>
                <listitem>
                  <para><emphasis>clientMultiplexId</emphasis>, for the
                  <classname>MultiplexClientInvoker</classname>, and</para>
                </listitem>

                <listitem>
                  <para><emphasis>serverMultiplexId</emphasis>, for the
                  <classname>MultiplexServerInvoker</classname>.</para>
                </listitem>
              </orderedlist>

              <para>Giving them matching multiplexIds tells them that they are
              meant to belong to the same invoker group and that they should
              provide the missing information to each other.</para>
            </listitem>
          </orderedlist>

          <para>The behavior of a starting
          <classname>MultiplexClientInvoker</classname> <emphasis>C</emphasis>
          is governed by the following four <emphasis role="bold">client
          rules</emphasis>:</para>

          <orderedlist>
            <listitem>
              <para>If <emphasis>C</emphasis> has a
              <emphasis>clientMultiplexId</emphasis> parameter, it will use it
              to attempt to find a
              <classname>MultiplexServerInvoker</classname>
              <emphasis>S</emphasis> with a
              <emphasis>serverMultiplexId</emphasis> parameter with the same
              value. If it succeeds, it will retrieve binding host and port
              values, create or reuse a suitable multiplex connection to the
              server, and start. Moreover, if <emphasis>S</emphasis> was
              unable to start because of insufficient information (server rule
              3), then <emphasis>C</emphasis> will supply the missing
              information and <emphasis>S</emphasis> will start. Note that in
              this situation <emphasis>C</emphasis> will ignore any
              <emphasis>multiplexBindHost</emphasis> and
              <emphasis>multiplexBindPort</emphasis> parameters passed to
              it.</para>
            </listitem>

            <listitem>
              <para>If <emphasis>C</emphasis> does not find a
              <classname>MultiplexServerInvoker</classname> through a
              multiplexId (either because it did not get a
              <emphasis>clientMultiplexId</emphasis> parameter or because
              there is no <classname>MultiplexServerInvoker</classname> with a
              matching multiplexId), but it does have
              <emphasis>multiplexBindHost</emphasis> and
              <emphasis>multiplexBindPort</emphasis> parameters, then it will
              create or reuse a suitable multiplex connection to the server,
              and start. Also, if it has a multiplexId, it will advertise
              itself for the benefit of a
              <classname>MultiplexServerInvoker</classname> that may come
              along later (see server rule 1).</para>
            </listitem>

            <listitem>
              <para>If <emphasis>C</emphasis> has a multiplexId and neither
              finds a <classname>MultiplexServerInvoker</classname> with a
              matching multiplexId nor has
              <emphasis>multiplexBindHost</emphasis> and
              <emphasis>multiplexBindPort</emphasis> parameters, then it will
              not start, but it will advertise itself so that it may be found
              later by a <classname>MultiplexServerInvoker</classname> (see
              server rule 1).</para>
            </listitem>

            <listitem>
              <para>If <emphasis>C</emphasis> has neither
              <emphasis>clientMultiplexId</emphasis> nor
              <emphasis>multiplexBindHost</emphasis> and
              <emphasis>multiplexBindPort</emphasis> parameters, it will
              create or reuse a multiplex connection from an arbitrary local
              port to the host and port given in its
              <classname>InvokerLocator</classname>, and start.</para>
            </listitem>
          </orderedlist>

          <para>Similarly, the behavior of a starting
          <classname>MultiplexServerInvoker</classname> <emphasis>S</emphasis>
          is governed by the following four <emphasis role="bold">server
          rules</emphasis>:</para>

          <orderedlist>
            <listitem>
              <para>If <emphasis>S</emphasis> has a
              <emphasis>serverMultiplexId</emphasis> parameter, it will use it
              to attempt to find a
              <classname>MultiplexClientInvoker</classname>
              <emphasis>C</emphasis> with a matching
              <emphasis>clientMultiplexId</emphasis>. If it succeeds, it will
              retrieve server host and port values, create a
              <classname>VirtualServerSocket</classname>, create or reuse a
              suitable multiplex connection to the server, and start.
              Moreover, if <emphasis>C</emphasis> was unable to start due to
              insufficient information (client rule 3), then
              <emphasis>S</emphasis> will supply the missing information and
              <emphasis>C</emphasis> will start. Note that in this situation
              <emphasis>S</emphasis> will ignore
              <emphasis>multiplexConnectHost</emphasis> and
              <emphasis>multiplexConnectPort</emphasis> parameters, if any, in
              its <classname>InvokerLocator</classname>.</para>
            </listitem>

            <listitem>
              <para>If <emphasis>S</emphasis> does not find a
              <classname>MultiplexClientInvoker</classname> through a
              multiplexId (either because it did not get a
              <emphasis>serverMultiplexId</emphasis> parameter or because
              there is no <classname>MultiplexClientInvoker</classname> with a
              matching multiplexId), but it does have
              <emphasis>multiplexConnectHost</emphasis> and
              <emphasis>multiplexConnectPort</emphasis> parameters, then it
              will create a <classname>VirtualServerSocket</classname>, create
              or reuse a suitable multiplex connection to the server, and
              start. Also, if it has a multiplexId, it will advertise itself
              for the benefit of a
              <classname>MultiplexClientInvoker</classname> that may come
              along later (see client rule 1).</para>
            </listitem>

            <listitem>
              <para>If <emphasis>S</emphasis> has a multiplexId and neither
              finds a <classname>MultiplexClientInvoker</classname> with a
              matching multiplexId nor has
              <emphasis>multiplexConnectHost</emphasis> and
              <emphasis>multiplexConnectPort</emphasis> parameters, then it
              will not start, but it will advertise itself so that it may be
              found later by a <classname>MultiplexClientInvoker</classname>
              (see client rule 1).</para>
            </listitem>

            <listitem>
              <para>If <emphasis>S</emphasis> has neither
              <emphasis>serverMultiplexId</emphasis> nor
              <emphasis>multiplexConnectHost</emphasis> and
              <emphasis>multiplexConnectPort</emphasis> parameters, it will
              create a <classname>MasterServerSocket</classname> bound to the
              host and port in its <classname>InvokerLocator</classname> and
              start.</para>
            </listitem>
          </orderedlist>

          <section>
            <title>Notes</title>

            <orderedlist>
              <listitem>
                <para>Like server invokers, client invokers are not started
                directly but are started indirectly through calls to
                <methodname>Client(InvokerLocator locator)</methodname>, such
                as:</para>

                <programlisting>
            Client client = new Client("multiplex://demo.jboss.com:8080/?clientMultiplexId=id0");
            client.connect();
                  </programlisting>

                <para><emphasis role="bold">N.B.</emphasis> For the multiplex
                invoker, it is important to call
                <methodname>Client.connect()</methodname>. Otherwise, the last
                <classname>MultiplexClientInvoker</classname> that leaves an
                invoker group will not get a chance to shut the group
                down.</para>
              </listitem>

              <listitem>
                <para>It should not be inferred that
                <classname>MultiplexClientInvoker</classname>s and
                <classname>MultiplexServerInvoker</classname>s belong to the
                same invoker group <emphasis>only if </emphasis> they are
                required to do so by invoker group parameters. In fact, if two
                <classname>Client</classname>s are created with the
                <classname>InvokerLocator</classname>
                multiplex://demo.jboss.com, the second one, lacking any
                constraints on its binding address and port, is certainly not
                prevented from sharing a connection with the first. Rather,
                the function of the invoker group parameters is to
                <emphasis>force</emphasis>
                <classname>MultiplexClientInvoker</classname>s and
                <classname>MultiplexServerInvoker</classname>s to share a
                connection.</para>
              </listitem>

              <listitem>
                <para>There are situations in which the method of passing
                parameters by way of the configuration map is preferable to
                appending them to an <classname>InvokerLocator</classname>.
                One of the functions of an
                <classname>InvokerLocator</classname> is to identify a server,
                and modifying the content of its
                <classname>InvokerLocator</classname> may interfere with the
                ability to locate the server. For example, one of the features
                of JBoss Remoting is the substitution of method calls for
                remote invocations when it discovers that a server runs in the
                same JVM as the client. However, appending multiplex
                parameters to the <classname>InvokerLocator</classname> by
                which the server is identified will prevent the Remoting
                runtime from recognizing the local presence of the server, and
                the optimization will not occur.</para>
              </listitem>

              <listitem>
                <para>It is possible, and convenient, to set up a multiplexing
                scenario using no parameters other than
                <emphasis>clientMultiplexId</emphasis> and
                <emphasis>serverMultiplexId</emphasis>. Note, however, that in
                this case neither the <classname>Clients</classname> nor the
                <classname>Connector</classname> will be fully initialized
                until after both have been started. If the
                <classname>Clients</classname> and the
                <classname>Connector</classname> are to be started
                independently, then the other parameters must be used.
                <emphasis role="bold">N.B.</emphasis> If a
                <classname>Client</classname> depends on
                <classname>Connector</classname> in the same invoker group to
                supply binding information, it is an error to call methods
                such as <methodname>Client.connect()</methodname> and
                <methodname>Client.invoke()</methodname> until the
                <classname>Connector</classname> has been started.</para>
              </listitem>

              <listitem>
                <para><classname>Clients</classname> and the optional
                <classname>Connector</classname> may be created (and the
                <classname>Connector</classname> started) in any order.</para>
              </listitem>
            </orderedlist>
          </section>
        </section>

        <section>
          <title>Shutting down invoker groups.</title>

          <para>A virtual socket group will shut down, releasing a real socket
          and a number of threads, when (1) its last member has closed and (2)
          the socket group at the remote end of the multiplex connection
          agrees to the proposed shut down. The second condition prevents a
          situation in which a new virtual socket tries to join what it thinks
          is a viable socket group at the same time that the peer socket group
          is shutting down. So for a virtual socket group to shut down, all
          members at both ends of the connection must be closed.</para>

          <para>The implication of this negotiated shutdown mechanism is that
          as long as the <classname>VirtualServerSocket</classname> used by a
          virtual <classname>MultiplexServerInvoker</classname> remains open,
          resources at the client end of the connection cannot be freed, and
          for this reason it is important to understand how to close virtual
          <classname>MultiplexServerInvoker</classname>s.</para>

          <para>There are three ways in which a virtual
          <classname>MultiplexServerInvoker</classname> that belongs to a
          master <classname>MultiplexServerInvoker</classname>'s invoker farm
          can shut down. <itemizedlist>
              <listitem>
                <para>When a master
                <classname>MultiplexServerInvoker</classname> is closed, it
                closes all of the virtual
                <classname>MultiplexServerInvoker</classname>s it
                created.</para>
              </listitem>

              <listitem>
                <para>A virtual <classname>MultiplexServerInvoker</classname>
                can be retrieved by calling either
                <methodname>MultiplexServerInvoker.getServerInvokers()</methodname>
                or
                <methodname>MultiplexServerInvoker.getServerInvoker(InetSocketAddress)</methodname>
                on its master <classname>MultiplexServerInvoker</classname>
                and then closed directly.</para>
              </listitem>

              <listitem>
                <para>When the <methodname>accept()</methodname> method of its
                <classname>VirtualServerSocket</classname> times out, and when
                it detects that all multiplex invokers in the invoker group at
                the client end of the connection have shut down, a virtual
                <classname>MultiplexServerInvoker</classname> will shut itself
                down. Note that when all members leave an invoker group, it is
                guaranteed not to be revived, i.e., no new members may
                join.</para>
              </listitem>
            </itemizedlist> The third method insures that without any explicit
          intervention, closing all multiplex invokers on the client (by way
          of calling <methodname>Client.disconnect()</methodname> and
          <methodname>Connector.stop()</methodname>) is guaranteed to result
          in the eventual release of resources. The timeout period may be
          adjusted by setting the <emphasis>timeout</emphasis> parameter (see
          below). Alternatively, the second method, in conjunction with the
          use of
          <methodname>MultiplexServerInvoker.isSafeToShutdown()</methodname>,
          which returns <code>true</code> on
          <classname>MultiplexServerInvoker</classname> <code>M</code> if and
          only if (1) <code>M</code> is not virtual, or (2) all of the
          multiplex invokers in the invoker group at the client end of
          <code>M</code>'s connection have shut down. For example, a thread
          could be dedicated to looking for useless
          <classname>MultiplexServerInvoker</classname>s and terminating them
          before their natural expiration through timing out.</para>
        </section>

        <section>
          <title>Examples</title>

          <para>The following are examples of setting up a client for
          multiplexed synchronous and asynchronous communication. They each
          assume the existence of a master
          <classname>MultiplexServerInvoker</classname> running on
          demo.jboss.com:8080.</para>

          <para>For complete examples see the section <xref
          linkend="section-multiplex-invokers" />.</para>

          <orderedlist>
            <listitem>
              <para>A <classname>MultiplexClientInvoker</classname>
              <emphasis>C</emphasis> starts first:</para>

              <programlisting>
            String parameters = "multiplexBindHost=localhost&amp;multiplexBindPort=7070&amp;clientMultiplexId=demoId1";
            String locatorURI = "multiplex://demo.jboss.com:8080/?" + parameters;
            InvokerLocator locator = new InvokerLocator(locatorURI);
            Client client = new Client(locator);
            client.connect();
               </programlisting>

              <para>and then it is found by a
              <classname>MultiplexServerInvoker</classname> with a matching
              multiplexId, which joins <emphasis>C</emphasis>'s invoker group
              and starts:</para>

              <programlisting>
            Connector connector = new Connector();
            String parameters = "serverMultiplexId=demoId1";
            String locatorURI = "multiplex://localhost:7070/?" + parameters;
            InvokerLocator locator = new InvokerLocator(locatorURI);
            connector.setInvokerLocator(locator.getLocatorURI());
            connector.create();
            connector.start();
               </programlisting>
            </listitem>

            <listitem>
              <para>A <classname>MultiplexClientInvoker</classname>
              <emphasis>C</emphasis> starts:</para>

              <programlisting>
            String parameters = "multiplexBindHost=localhost&amp;multiplexBindPort=7070";
            String locatorURI = "multiplex://demo.jboss.com:8080/?" + parameters;
            InvokerLocator locator = new InvokerLocator(locatorURI);
            Client client = new Client(locator);
            client.connect();
                  </programlisting>

              <para>and a <classname>MultiplexServerInvoker</classname>
              <emphasis>S</emphasis> starts independently, joining
              <emphasis>C</emphasis>'s invoker group by virtue of having
              matching local and remote addresses and ports:</para>

              <programlisting>
            Connector connector = new Connector();
            String parameters = "multiplexConnectHost=demo.jboss.com&amp;multiplexConnectPort=8080";
            String locatorURI = "multiplex://localhost:7070/?" + parameters;
            InvokerLocator locator = new InvokerLocator(locatorURI);
            connector.setInvokerLocator(locator.getLocatorURI());
            connector.create();
            connector.start();
               </programlisting>
            </listitem>

            <listitem>
              <para>A <classname>MultiplexClientInvoker</classname>
              <emphasis>C</emphasis> is created but does not start:</para>

              <programlisting>
            String parameters = "clientMultiplexId=demoId2";
            String locatorURI = "multiplex://demo.jboss.com:8080/?" + parameters;
            InvokerLocator locator = new InvokerLocator(locatorURI);
            Client client = new Client(locator);
               </programlisting>

              <para>and then a <classname>MultiplexServerInvoker</classname>
              <emphasis>S</emphasis> is created with a matching multiplexId,
              allowing both <emphasis>C</emphasis> and <emphasis>S</emphasis>
              to start:</para>

              <programlisting>
            Connector connector = new Connector();
            String parameters = "serverMultiplexId=demoId2";
            String locatorURI = "multiplex://localhost:7070/?" + parameters;
            InvokerLocator locator = new InvokerLocator(locatorURI);
            connector.setInvokerLocator(locator.getLocatorURI());
            connector.create();
            connector.start();
            client.connect();
               </programlisting>

              <para>Note the call to <methodname>Client.connect()</methodname>
              after the call to
              <methodname>Connector.start()</methodname>.</para>
            </listitem>

            <listitem>
              <para>A <classname>MultiplexClientInvoker</classname>
              <emphasis>C</emphasis> starts in an invoker group based on a
              real socket bound to an arbitrary local port:</para>

              <programlisting>
            String locatorURI = "multiplex://demo.jboss.com:8080";
            InvokerLocator locator = new InvokerLocator(locatorURI);
            Client client = new Client(locator);
            client.connect();
               </programlisting>

              <para>and then a <classname>MultiplexServerInvoker</classname>
              <emphasis>S</emphasis> starts independently:</para>

              <programlisting>
            Connector connector = new Connector();
            String locatorURI = "multiplex://localhost:7070";
            InvokerLocator locator = new InvokerLocator(locatorURI);
            connector.setInvokerLocator(locator.getLocatorURI());
            connector.create();
            connector.start();
               </programlisting>

              <para>Note that <emphasis>S</emphasis> creates a
              <classname>MasterServerSocket</classname> rather than a
              <classname>VirtualServerSocket</classname> in this case and so
              does not share a multiplex connection and does not belong to an
              invoker group.</para>
            </listitem>

            <listitem>
              <para>This is example 1, rewritten so that the invoker group
              parameters are passed by way of a configuration
              <classname>Map</classname> instead of
              <classname>InvokerLocator</classname>s. A
              <classname>MultiplexClientInvoker</classname>
              <emphasis>C</emphasis> starts first:</para>

              <programlisting>
            String locatorURI = "multiplex://demo.jboss.com:8080";
            InvokerLocator locator = new InvokerLocator(locatorURI);
            Map configuration = new HashMap();
            configuration.put(MultiplexInvokerConstants.MULTIPLEX_BIND_HOST_KEY, "localhost");
            configuration.put(MultiplexInvokerConstants.MULTIPLEX_BIND_PORT_KEY, "7070");
            configuration.put(MultiplexInvokerConstants.CLIENT_MULTIPLEX_ID_KEY, "demoId1");
            Client client = new Client(locator, configuration);
            client.connect();
               </programlisting>

              <para>and then it is found by a
              <classname>MultiplexServerInvoker</classname> with a matching
              multiplexId, which joins <emphasis>C</emphasis>'s invoker group
              and starts:</para>

              <programlisting>
            String locatorURI = "multiplex://localhost:7070";
            InvokerLocator locator = new InvokerLocator(locatorURI);
            Map configuration = new HashMap();
            configuration.put(MultiplexInvokerConstants.SERVER_MULTIPLEX_ID_KEY, "demoId1");
            Connector connector = new Connector(locator.getLocatorURI(), configuration);
            connector.create();
            connector.start();
               </programlisting>
            </listitem>
          </orderedlist>
        </section>

        <section>
          <title>Configuration properties</title>

          <para>There are four categories of configuration properties
          supported by the multiplex invoker, the last three of which are
          specific to the multiplex invoker. Properties in categories 2 and 3
          may be configured by appending them to the server's locator URI.
          Properties in categories 2, 3, and 4 may be configured by putting
          their values in a configuration <classname>HashMap</classname> and
          passing the map to a <classname>MultiplexServerInvoker</classname>
          and/or <classname>MultiplexClientInvoker</classname> constructor,
          according to the category. Constants for the property names in
          categories 2, 3, and 4 are found in
          <classname>org.jboss.remoting.transport.multiplex.Multiplex</classname>.
          Note that some of them are also found in the older
          <classname>org.jboss.remoting.transport.multiplex.MultiplexInvokerConstants</classname>,
          but the use of that class is now deprecated.</para>

          <orderedlist numeration="arabic">
            <listitem>
              <para>The following properties are managed by ancestor classes
              of <classname>MultiplexServerInvoker</classname>.  See the discussion
              under <classname>SocketServerInvoker</classname> for more
              information.</para>
              <para><emphasis role="bold">socketTimeout</emphasis> - The
              socket timeout value passed to the
              <methodname>Socket.setSoTimeout()</methodname> method and the
              <methodname>ServerSocket.setSoTimeout()</methodname> method. The
              default is 60000 (or 1 minute).</para>

              <para><emphasis role="bold">numAcceptThreads</emphasis> - The
              number of threads that exist for accepting client connections.
              The default is 1.</para>
            </listitem>

            <listitem>
              <para>The following properties are intended to be passed to a
              virtual <classname>MultiplexServerInvoker</classname> to
              configure its multiplex connection. These properties are
              specific to the multiplex invoker.</para>

              <para><emphasis role="bold">multiplexConnectHost</emphasis> -
              the name or address of the host to which the multiplex
              connection should be made.</para>

              <para><emphasis role="bold">multiplexConnectPort</emphasis> -
              the port to which the multiplex connection should be
              made.</para>

              <para><emphasis role="bold">serverMultiplexId</emphasis> - a
              string that associates a
              <classname>MultiplexServerInvoker</classname> with a
              <classname>MultiplexClientInvoker</classname> with which it
              should share a multiplex connection.</para>

              <para><emphasis role="bold">multiplex.maxAcceptErrors</emphasis>
              - Master and virtual
              <classname>MultiplexServerInvoker</classname>s keep a counter of
              errors experienced by their server socket, and they terminate
              when this maximum is exceeded. Note that
              <classname>SSLHandshakeException</classname>s are excluded from
              the count, since they could indicate a client rather than server
              error.</para>
            </listitem>

            <listitem>
              <para>The following properties are intended to be passed to a
              virtual <classname>MultiplexClientInvoker</classname> to
              configure its multiplex connection. These properties are
              specific to the multiplex invoker.</para>

              <para><emphasis role="bold">multiplexBindHost</emphasis> - the
              host name or address to which the local end of the multiplex
              connection should be bound.</para>

              <para><emphasis role="bold">multiplexBindPort</emphasis> - the
              port to which the local end of the multiplex connection should
              be bound</para>

              <para><emphasis role="bold">clientMultiplexId</emphasis> - a
              string that associates a
              <classname>MultiplexClientInvoker</classname> with a
              <classname>MultiplexServerInvoker</classname> with which it
              should share a multiplex connection.</para>
            </listitem>

            <listitem>
              <para>There is also a set of properties which are specific to
              the Multiplex subsystem internal classes. See the Multiplex
              documentation at</para>

              <blockquote>
                <para><ulink
                url="http://labs.jboss.com/portal/jbossremoting/docs/index.html">
                http://labs.jboss.com/portal/jbossremoting/docs/index.html</ulink></para>
              </blockquote>

              <para>for more information.</para>
            </listitem>
          </orderedlist>
        </section>
      </section>

      <section>
        <title>SSL Multiplex Invoker</title>

        <para>This transport is essentially identical to the Multiplex
        transport, except that it will create SSL socket factories and server
        socket factories by default.</para>

        <para>The twist to be found with the multiplex transport is that
        virtual <classname>MultiplexServerInvoker</classname>s use a
        <classname>VirtualServerSocket</classname>, which is based on a client
        rather than a server socket, and consequently they act like a client
        in some ways. In particular, a virtual
        <classname>MultiplexServerInvoker</classname> will, in some cases,
        attempt to connect to a remote master
        <classname>MultiplexServerInvoker</classname>, for which it will need
        an actual client socket. All of the rules for configuring socket
        factories apply to the <classname>MultiplexServerInvoker</classname>,
        which calls the same method that client invokers use to get a socket
        factory. Moreover, if necessary, it will look for a
        <classname>ServerSocketFactoryMBean</classname> to get SSL information
        when configuring a socket factory.</para>
      </section>
    </section>

    <section>
      <title>Marshalling</title>

      <para>Marshalling of data can range from extremely simple to somewhat
      complex, depending on how much customization is needed. The following
      explains how marshallers/unmarshallers can be configured. Note that this
      applies for all the different transports, but will use the socket
      transport for examples.</para>

      <para>The easiest way to configure marshalling is to specify nothing at
      all. This will prompt the remoting invokers to use their default
      marshaller/unmarshallers. For example, the socket invoker will use the
      SerializableMarshaller/SerializableUnMarshaller and the http invoker
      will use the HTTPMarshaller/HTTPUnMarshaller, on both the client and
      server side.</para>

      <para>The next easiest way is to specify the data type of the
      marshaller/unmarshaller as a parameter to the locator url. This can be
      done by simply adding the key word 'datatype' to the url, such
      as:</para>

      <programlisting>socket://myhost:5400/?datatype=serializable</programlisting>

      <para>This can be done for types that are statically bound within the
      <code>MarshalFactory</code> , serializable and http, without requiring
      any extra coding, since they will be available to any user of remoting.
      However, is more likely this will be used for custom marshallers (since
      could just use the default data type from the invokers if using the
      statically defined types). If using custom marshaller/unmarshaller, will
      need to make sure both are added programmatically to the
      <code>MarshalFactory</code> during runtime (on both the client and
      server side). This can be done by the following method call within the
      MarshalFactory:</para>

      <programlisting>public static void addMarshaller(String dataType, Marshaller marshaller, UnMarshaller unMarshaller)
      </programlisting>

      <para>The dataType passed can be any String value desired. For example,
      could add custom InvocationMarshaller and InvocationUnMarshaller with
      the data type of 'invocation'. An example using this data type would
      then be:</para>

      <programlisting>socket://myhost:5400/?datatype=invocation</programlisting>

      <para>One of the problems with using a data type for a custom
      Marshaller/UnMarshaller is having to explicitly code the addition of
      these within the MarshalFactory on both the client and the server. So
      another approach that is a little more flexible is to specify the fully
      qualified class name for both the Marshaller and UnMarshaller on the
      locator url. For example:</para>

      <programlisting>socket://myhost:5400/?datatype=invocation&amp;
            marshaller=org.jboss.invocation.unified.marshall.InvocationMarshaller&amp;
            unmarshaller=org.jboss.invocation.unified.marshall.InvocationUnMarshaller
         </programlisting>

      <para>This will prompt remoting to try to load and instantiate the
      Marshaller and UnMarshaller classes. If both are found and loaded, they
      will automatically be added to the MarshalFactory by data type, so will
      remain in memory. Now the only requirement is that the custom Marshaller
      and UnMarshaller classes be available on both the client and server's
      classpath.</para>

      <para>Another requirement of the actual Marshaller and UnMarshaller
      classes is that they have a void constructor. Otherwise loading of these
      will fail.</para>

      <para>This configuration can also be applied using the service xml. If
      using declaration of invoker using the InvokerLocator attribute, can
      simply add the datatype, marshaller, and unmarshaller parameters to the
      defined InvokerLocator attribute value. For example:</para>

      <programlisting>      
         &lt;attribute name="InvokerLocator"&gt;
            &lt;![CDATA[socket://${jboss.bind.address}:8084/?datatype=invocation&amp;
            marshaller=org.jboss.invocation.unified.marshall.InvocationMarshaller&amp;
            unmarshaller=org.jboss.invocation.unified.marshall.InvocationUnMarshaller]]&gt;
         &lt;/attribute&gt;
      </programlisting>

      <para>If were using config element to declare the invoker, will need to
      add an attribute for each and include the isParam attribute set to true.
      For example:</para>

      <programlisting>
         &lt;invoker transport="socket"&gt;
            &lt;attribute name="dataType" isParam="true"&gt;invocation&lt;/attribute&gt;
            &lt;attribute name="marshaller" isParam="true"&gt;
               org.jboss.invocation.unified.marshall.InvocationMarshaller
            &lt;/attribute&gt;
            &lt;attribute name="unmarshaller" isParam="true"&gt;
                  org.jboss.invocation.unified.marshall.InvocationUnMarshaller
            &lt;/attribute&gt;
         &lt;/invoker&gt;
      </programlisting>

      <para>This configuration is fine if the classes are present within the
      client's classpath. If they are not, can provide configuration for
      allowing clients to dynamically load the classes from the server. To do
      this, can use the parameter 'loaderport' with the value of the port you
      would like your marshal loader to run on. For example:</para>

      <programlisting>
         &lt;invoker transport="socket"&gt;
            &lt;attribute name="dataType" isParam="true"&gt;invocation&lt;/attribute&gt;
            &lt;attribute name="marshaller" isParam="true"&gt;
               org.jboss.invocation.unified.marshall.InvocationMarshaller
            &lt;/attribute&gt;
            &lt;attribute name="unmarshaller" isParam="true"&gt;
               org.jboss.invocation.unified.marshall.InvocationUnMarshaller
            &lt;/attribute&gt;
            &lt;attribute name="loaderport" isParam="true"&gt;5401&lt;/attribute&gt;
         &lt;/invoker&gt;
      </programlisting>

      <para>When this parameter is supplied, the Connector will recognize this
      at startup and create a marshal loader connector automatically, which
      will run on the port specified. The locator url will be exactly the same
      as the original invoker locator, except will be using the socket
      transport protocol and will have all marshalling parameters removed
      (except the dataType). When the remoting client can not load the
      marshaller/unmarshaller for the specified data type, it will try to load
      them from the marshal loader service running on the loader port,
      including any classes they depend on. This will happen automatically and
      no coding is required (only the ability for the client to access the
      server on the specified loader port, so must provide access if running
      through firewall).</para>

      <bridgehead>Compression marshalling</bridgehead>

      <para>A compression marshaller/unmarshaller is available as well which
      uses gzip to compress and uncompress large payloads for wire transfer.
      The implementation classes are
      <classname>org.jboss.remoting.marshal.compress.CompressingMarshaller</classname>
      and
      <classname>org.jboss.remoting.marshal.compress.CompressingUnMarshaller</classname>.
      They extend the
      <code>org.jboss.remoting.marshal.serializable.SerializableMarshaller</code>
      and
      <code>org.jboss.remoting.marshal.serializable.SerializableUnMarshaller</code>
      interfaces and maintain the same behavior with the addition of
      compression.</para>
    </section>

    <section>
      <title>Callbacks</title>

      <section>
        <title>Callback overview</title>

        <para>Although this section covers callback configuration, will need
        to first cover a little general information about callbacks within
        remoting. There are two models for callbacks, push and pull. In the
        push model, the client will register a callback server via an
        InvokerLocator with the target server. When the target server has a
        callback to deliver, it will call on the callback server directly and
        send the callback message.</para>

        <para>The other model, pull callbacks, allows the client to call on
        the target server to collect the callback messages waiting for it. The
        target server then has to manage these callback messages on the server
        until the client calls to collect them. Since the server has no
        control of when the client will call to get the callbacks, it has to
        be aware of memory constraints as it manages a growing number of
        callbacks. The way the callback server does this is through use of a
        persistence policy. This policy indicates at what point the server has
        too little free memory available and therefore the callback message
        should be put into a persistent store. This policy can be configured
        via the <code>memPercentCeiling</code> attribute (see more on
        configuring this below).</para>

        <para>By default, the persistent store used by the invokers is the
        <code>org.jboss.remoting.NullCallbackStore</code> . The
        NullCallbackStore will simply throw away the callback to help avoid
        running out of memory. When the persistence policy is triggered and
        the NullCallbackStore is called upon to store the callback, the
        invocation handler making the call will be thrown an IOException with
        the message:</para>

        <para><literal>Callback has been lost because not enough free memory
        to hold object.</literal></para>

        <para>and there will be an error in the log stating which object was
        lost. In this same scenario, the client will get an instance of the
        <code>org.jboss.remoting.NullCallbackStore</code> .
        <code>FailedCallback</code> class when they call to get their
        callbacks. This class will throw a RuntimeException with the following
        message when <code>getCallbackObject()</code> is called:</para>

        <para><literal>This is an invalid callback. The server ran out of
        memory, so callbacks were lost.</literal></para>

        <para>Also, the payload of the callback will be the same string. The
        client will also get any valid callbacks that were kept in memory
        before the persistence policy was triggered.</para>

        <para>An example case when using the NullCallbackStore might be when
        callback objects A, B, and C are stored in memory because there is
        enough free memory. Then when callback D comes, the persistence policy
        is triggered and the NullCallbackStore is asked to persist callback D.
        The NullCallbackStore will throw away callback D and create a
        FailedCallback object to take its place. Then callback E comes, and
        there is still too little free memory, so that is thrown away by the
        NullCallbackStore.</para>

        <para>Then the client calls to get its callbacks. It will receive a
        List containing callbacks A, B, C and the FailedCallback. When the
        client asks the FailedCallback for its callback payload, it will throw
        the aforementioned exception.</para>

        <para>Besides the default NullCallbackStore, there is a truly
        persistent CallbackStore, which will persist callback messages to disk
        so they will not be lost. The description of the CallbackStore is as
        follows:</para>

        <para><literal>Acts as a persistent list which writes Serializable
        objects to disk and will retrieve them in same order in which they
        were added (FIFO). Each file will be named according to the current
        time (using System.currentTimeMillis() with the file suffix specified
        (see below). When the object is read and returned by calling the
        getNext() method, the file on disk for that object will be deleted. If
        for some reason the store VM crashes, the objects will still be
        available upon next startup. The attributes to make sure to configure
        are:</literal></para>

        <para><literal>file path - this determines which directory to write
        the objects. The default value is the property value of
        'jboss.server.data.dir' and if this is not set, then will be 'data'.
        For example, might be /jboss/server/default/data.</literal></para>

        <para><literal>file suffix - the file suffix to use for the file
        written for each object stored.</literal></para>

        <para><literal>This is also a service mbean, so can be run as a
        service within JBoss AS or stand alone.</literal></para>

        <para>Custom callback stores can also be implemented and defined
        within configuration. The only requirement is that it implements the
        org.jboss.remoting.SerializableStore interface and has a void
        constructor (only in the case of using a fully qualified classname in
        configuration).</para>

        <para>Once a callback client has been removed as a listener, all
        persisted callbacks will be removed from disk.</para>
      </section>

      <section>
        <title>Callback Configuration</title>

        <para>All callback configuration will need to be defined within the
        invoker configuration, since the invoker is the parent that creates
        the callback servers as needed (when client registers for pull
        callbacks). Example service xml are included below.</para>

        <para><emphasis role="bold">callbackMemCeiling</emphasis> - the
        percentage of free memory available before callbacks will be
        persisted. If the memory heap allocated has reached its maximum value
        and the percent of free memory available is less than the
        callbackMemCeiling, this will trigger persisting of the callback
        message. The default value is 20.</para>

        <para>Note: The calculations for this is not always accurate. The
        reason is that total memory used is usually less than the max allowed.
        Thus, the amount of free memory is relative to the total amount
        allocated at that point in time. It is not until the total amount of
        memory allocated is equal to the max it will be allowed to allocate.
        At this point, the amount of free memory becomes relevant. Therefore,
        if the memory percentage ceiling is high, it might not trigger until
        after free memory percentage is well below the ceiling.</para>

        <para><emphasis role="bold">callbackStore</emphasis> - specifies the
        callback store to be used. The value can be either an MBean ObjectName
        or a fully qualified class name. If using class name, the callback
        store implementation must have a void constructor. The default is to
        use the NullCallbackStore.</para>

        <bridgehead>CallbackStore configuration</bridgehead>

        <para>The CallbackStore can be configured via the invoker
        configuration as well.</para>

        <para><emphasis role="bold">StoreFilePath</emphasis> - indicates to
        which directory to write the callback objects. The default value is
        the property value of 'jboss.server.data.dir' and if this is not set,
        then will be 'data'. Will then append 'remoting' and the callback
        client's session id. An example would be
        'data\remoting\5c4o05l-9jijyx-e5b6xyph-1-e5b6xyph-2'.</para>

        <para><emphasis role="bold">StoreFileSuffix</emphasis> - indicates the
        file suffix to use for the callback objects written to disk. The
        default value is ‘ser’.</para>

        <bridgehead>Sample service configuration</bridgehead>

        <para>Socket transport with callback store specified by class name and
        memory ceiling set to 30%:</para>

        <programlisting>
           &lt;mbean code="org.jboss.remoting.transport.Connector"
                 xmbean-dd="org/jboss/remoting/transport/Connector.xml"
                 name="jboss.remoting:service=Connector,transport=Socket"
                 display-name="Socket transport Connector"&gt;

              &lt;attribute name="Configuration"&gt;
                 &lt;config&gt;
                    &lt;invoker transport="socket"&gt;
                       &lt;attribute name="callbackStore"&gt;org.jboss.remoting.CallbackStore&lt;/attribute&gt;
                       &lt;attribute name="callbackMemCeiling"&gt;30&lt;/attribute&gt;
                    &lt;/invoker&gt;
                    &lt;handlers&gt;
                       &lt;handler subsystem="test"&gt;
                          org.jboss.remoting.callback.pull.memory.CallbackInvocationHandler
                       &lt;/handler&gt;
                    &lt;/handlers&gt;
                 &lt;/config&gt;
              &lt;/attribute&gt;
           &lt;/mbean&gt;
        </programlisting>

        <para>Socket transport with callback store specified by MBean
        ObjectName and declaration of CallbackStore as service:</para>

        <programlisting>
           &lt;mbean code="org.jboss.remoting.CallbackStore"
                 name="jboss.remoting:service=CallbackStore,type=Serializable"
                 display-name="Persisted Callback Store"&gt;

              &lt;!-- the directory to store the persisted callbacks into --&gt;
              &lt;attribute name="StoreFilePath"&gt;callback_store&lt;/attribute&gt;
              &lt;!-- the file suffix to use for each callback persisted to disk --&gt;
              &lt;attribute name="StoreFileSuffix"&gt;cbk&lt;/attribute&gt;
           &lt;/mbean&gt;

           &lt;mbean code="org.jboss.remoting.transport.Connector"
                 xmbean-dd="org/jboss/remoting/transport/Connector.xml"
                 name="jboss.remoting:service=Connector,transport=Socket"
                 display-name="Socket transport Connector"&gt;

              &lt;attribute name="Configuration"&gt;
                 &lt;config&gt;
                    &lt;invoker transport="socket"&gt;
                       &lt;attribute name="callbackStore"&gt;
                          jboss.remoting:service=CallbackStore,type=Serializable
                       &lt;/attribute&gt;
                    &lt;/invoker&gt;
                    &lt;handlers&gt;
                       &lt;handler subsystem="test"&gt;
                          org.jboss.remoting.callback.pull.memory.CallbackInvocationHandler
                       &lt;/handler&gt;
                    &lt;/handlers&gt;
                 &lt;/config&gt;
              &lt;/attribute&gt;
           &lt;/mbean&gt;
        </programlisting>

        <para>Socket transport with callback store specified by class name and
        the callback store’s file path and file suffix defined:</para>

        <programlisting>
           &lt;mbean code="org.jboss.remoting.transport.Connector"
                 xmbean-dd="org/jboss/remoting/transport/Connector.xml"
                 name="jboss.remoting:service=Connector,transport=Socket"
                 display-name="Socket transport Connector"&gt;

              &lt;attribute name="Configuration"&gt;
                 &lt;config&gt;
                    &lt;invoker transport="socket"&gt;
                       &lt;attribute name="callbackStore"&gt;org.jboss.remoting.CallbackStore&lt;/attribute&gt;
                       &lt;attribute name="StoreFilePath"&gt;callback&lt;/attribute&gt;
                       &lt;attribute name="StoreFileSuffix"&gt;cst&lt;/attribute&gt;
                    &lt;/invoker&gt;
                    &lt;handlers&gt;
                       &lt;handler subsystem="test"&gt;
                          org.jboss.remoting.callback.pull.memory.CallbackInvocationHandler
                       &lt;/handler&gt;
                    &lt;/handlers&gt;
                 &lt;/config&gt;
              &lt;/attribute&gt;
           &lt;/mbean&gt;
        </programlisting>
      </section>

      <section>
        <title>Callback Exception Handling</title>

        <para>Since performing callbacks can sometimes fail, due to network
        errors or errors produced by the client callback handler, there needs
        to be a mechanism for managing exceptions when delivering callbacks.
        This is handled via use of the
        <code>org.jboss.remoting.callback.CallbackErrorHandler</code>
        interface. Implementations of this interface can be registered with
        the Connector to control the behavior when callback exceptions
        occur.</para>

        <para>The implementation of the CallbackErrorHandler interface can be
        specified by setting the 'callbackErrorHandler' attribute to either
        the ObjectName of an MBean instance of the CallbackErrorHandler which
        is already running and registered with the MBeanServer, or can just
        specify the fully qualified class name of the CallbackErrorHandler
        implementation (which will be constructed on the fly and must have a
        void parameter constructor). The full server invoker configuration
        will be passed along to the CallbackErrorHandler, so if want to add
        extra configuration information in the invoker's configuration for the
        callback error handler, it will be available. If no callback error
        handler is specified via configuration,
        <code>org.jboss.remoting.callback.DefaultCallbackErrorHandler</code>
        will be used by default. This implementation will allow up to 5
        exceptions to occur when trying to deliver a callback message from the
        server to the registered callback listener client (regardless of what
        the cause of the exception is, so could be because could not connect
        or could be because the client actually threw a valid exception).
        After the DefaultCallbackErrorHandler receives its fifth exception, it
        will remove the callback listener from the server invoker handler and
        shut down the callback listener proxy on the server side. The number
        of exceptions the DefaultCallbackErrorHandler will allow before
        removing the listener can by configured by the 'callbackErrorsAllowed'
        attribute.</para>
      </section>
    </section>

    <section>
      <title>Programmatic configuration</title>

      <para>It is possible to configure all this programmatically, if running
      outside the JBoss Application server for example, but is a little more
      tedious. Since the remoting components are all bound together by the
      <code>org.jboss.remoting.transport.Connector</code> class, will need to
      call its <code>setConfiguration(org.w3c.dom.Element xml)</code> method
      with same xml as in the mbean service configuration, before calling its
      <code>start()</code> method.</para>

      <para>The xml passed to the Connector should have
      <code>&lt;config&gt;</code> element as the root element and continue
      from there with <code>&lt;invoker&gt;</code> sub-element and so on. An
      example of this can be found in
      org.jboss.test.remoting.configuration.SocketClientConfigurationTestCase.</para>
    </section>

    <section>
      <title>Socket factories and server socket factories</title>
      
      <para>All current transports depend on sockets and server sockets, and the
      ability to specify their implementation classes provides considerable
      power in configuring Remoting.  Notably, SSL sockets
      and server sockets are the basis of secure communications in Remoting.
      This section covers the configuration of socket factories and server
      socket factories on both the server side and the client side, and then
      focuses on SSL configuration.
      </para>
      
      <section>
         <title>Server side programmatic configuration</title>
         <para>
         All server invokers use server sockets, and it makes sense,
         therefore, to be able to configure server invokers with
         server socket factories.  It is also true, though less obvious.
         that server invokers create sockets (other than by way of
         server sockets).  When a server invoker makes a push
         callback to a client, it creates a client invoker, which creates a
         socket.  Moreover, some server invokers, e.g., the RMI server invoker,
         have their own idiosyncratic uses for socket factories.  Remoting offers a
         number of ways of configuring socket factories and server socket
         factories, and these apply to all transports.
         </para>
         
         <section>
            <title id="section-ssf-serverside" xreflabel="Server socket factories">
               Server socket factories.
            </title>
            <para>For <classname>ServerSocketFactory</classname>s, there are
            ten options for programmatic configuration:</para>
            
            <orderedlist>
               
               <listitem>
                  <para>Get the <classname>ServerInvoker</classname> by calling
                  <methodname>Connector.getServerInvoker()</methodname> and call
                  <methodname>ServerInvoker.setServerSocketFactory()</methodname>.</para>
               </listitem>

               <listitem>
                  <para>Call <methodname>Connector.setServerSocketFactory()</methodname>.
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                  Put a constructed <classname>ServerSocketFactory</classname> in a
                  configuration map, using key
                  <constant>Remoting.CUSTOM_SERVER_SOCKET_FACTORY</constant>,
                  and pass the map to one of the <classname>Connector</classname>
                  constructors.
                  </para>
               </listitem>
                       
               <listitem>
                  <para>
                     Create an xml document with root element <code>&lt;config&gt;</code>,
                     setting the <code>&lt;serverSocketFactory&gt;</code> attribute to
                     the name of a <classname>ServerSocketFactoryMBean</classname> and pass
                     the document to <methodname>Connector.setConfiguration()</methodname>.  For
                     example:
                     
                     <programlisting>
                        StringBuffer buf = new StringBuffer();
                        buf.append("&lt;?xml version=\"1.0\"?&gt;\n");
                        buf.append("&lt;config&gt;");
                        buf.append("   &lt;invoker transport=\"sslsocket\"&gt;");
                        buf.append("      &lt;attribute name=\"serverBindAddress\"&gt;" + getHostName() + "&lt;/attribute&gt;");
                        buf.append("      &lt;attribute name=\"serverBindPort\"&gt;" + freeport + "&lt;/attribute&gt;");
                        buf.append("      &lt;attribute name=\"serverSocketFactory\"&gt;" + socketFactoryObjName + "&lt;/attribute&gt;");
                        buf.append("   &lt;/invoker&gt;");
                        buf.append("&lt;/config&gt;");
                        ByteArrayInputStream bais = new ByteArrayInputStream(buf.toString().getBytes());
                        Document xml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(bais);
                        connector.setConfiguration(xml.getDocumentElement());
                     </programlisting>
                  </para>
               </listitem>
                   
               <listitem>
                  <para>
                     Create an xml document with root element <code>&lt;config&gt;</code>,
                     setting the <code>&lt;serverSocketFactory&gt;</code> attribute to
                     the class name of a <classname>ServerSocketFactory</classname> and pass
                     the document to <methodname>Connector.setConfiguration()</methodname>.  
                     The <code>&lt;serverSocketFactory&gt;</code> class must have a default
                     constructor, which will be used to create a 
                  <classname>ServerSocketFactory</classname>.
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                     Put the <classname>ObjectName</classname> of a
                     <classname>ServerSocketFactoryMBean</classname> in a configuration map,
                     using key <constant>ServerInvoker.SERVER_SOCKET_FACTORY</constant>,
                     and pass the map to one of the <classname>Connector</classname>
                     constructors.
                  </para>
               </listitem>
                           
               <listitem>
                  <para>
                  Put the class name of a <classname>ServerSocketFactory</classname>
                  in a configuration map, using key
                  <constant>ServerInvoker.SERVER_SOCKET_FACTORY</constant>,
                  and pass the map to one of the <classname>Connector</classname> constructors.
                  The <code>&lt;serverSocketFactory&gt;</code> class must have a
                  default constructor, which will be used to create a 
                  <classname>ServerSocketFactory</classname>.
                  </para>
               </listitem>
                           
               <listitem>
                  <para>
                  Put a set of SSL parameters, using the keys in
                  <classname>org.jboss.remoting.security.SSLSocketBuilder</classname>, in a
                  configuration map and pass the map to one of the
                  <classname>Connector</classname> constructors. These will be used by
                  <classname>SSLSocketBuilder</classname> (see below) to create a
                  <classname>CustomSSLServerSocketFactory</classname>.
                  </para>
               </listitem>
                           
               <listitem>
                  <para>
                  Configure an appropriate set of SSL system properties
                  and use one of the SSL transports (https, sslmultiplex,
                  sslrmi, or sslsocket). The properties will be used to
                  create some kind of <classname>SSLServerSocketFactory</classname>,
                  as determined by the transport.
                  </para>
               </listitem>
                           
               <listitem>
                  <para>
                  Use one of the non-SSL transports and do nothing. A default
                  <classname>ServerSocketFactory</classname> will be constructed.
                  </para>
               </listitem>
            </orderedlist>
            
            <para>
               These options are essentially in descending order of precedence.
               If options 3 and 6, for example, are both
               used, the factory passed in option 3 will prevail.
               Options 4 and 5 are mutually exclusive, as are options 6 and 7.
               Options 1, 2, 3, 5, and 7 are illustrated in
               <classname>FactoryConfigSample</classname>
               and options 4, 6, 8, and 9 are illustrated in
               <classname>FactoryConfigSSLSample</classname>,
               both of which are in package
               <classname>org.jboss.remoting.samples.config.factories</classname>.
            </para>
            
            <para>
            <emphasis role="bold">Timing considerations.</emphasis> The 
            <classname>ServerInvoker</classname>, for any transport, is created
            during the call to <methodname>Connector.create()</methodname>, before which 
            option 1 is unavailable. Option 2, on the other hand,
            is only available before the call to
            <methodname>Connector.create()</methodname>.
            Once the <classname>ServerInvoker</classname> has been created, it
            selects a <classname>ServerSocketFactory</classname>, according to
            the rules enumerated above, during the <methodname>create()</methodname>
            phase.  For all current transports, the actual
            <classname>ServerSocket</classname> is created during the call to
            <methodname>Connector.start()</methodname>, so that a call to
            <methodname>ServerInvoker.setServerSocketFactory()</methodname> 
            (option 1) can override the selected <classname>ServerSocketFactory</classname>
            until <methodname>Connector.start()</methodname> is called.
            </para>
         </section>
         
         <section>
            <title>Socket factories</title>
            <para>
            For <classname>SocketFactory</classname>s, there are also ten options
            for programmatic configuration, and they are essentially the same as
            the previous ten:</para>
            
            <orderedlist>
               <listitem>
                  <para>
                     Call <methodname>Connector.setSocketFactory()</methodname>.
                  </para>
               </listitem>
      
               <listitem>
                  <para>
                     Get the <classname>ServerInvoker</classname> by calling
                     <methodname>Connector.getServerInvoker()</methodname> and call
                     <methodname>ServerInvoker.setSocketFactory()</methodname>.
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                     Put a constructed <classname>SocketFactory</classname> in a
                     configuration map, using key
                     <constant>Remoting.CUSTOM_SOCKET_FACTORY</constant>, and pass
                     the map to one of the <classname>Connector</classname> constructors.
                  
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                     Create an xml document with root element <code>&lt;config&gt;</code>,
                     setting the <code>&lt;serverSocketFactory&gt;</code> attribute to
                     the name of a <classname>ServerSocketFactoryMBean</classname> and pass
                     the document to <methodname>Connector.setConfiguration()</methodname>.
                     If the MBean has type
                     <classname>SSLServerSocketFactoryServiceMBean</classname>, its
                     configuration information will be gathered and used to construct a
                     <classname>CustomSSLSocketFactory</classname>.
                     <emphasis role="bold">Note.</emphasis>  This method is guaranteed to
                     work only for callback client invokers.  For other, transport
                     specific, socket factory uses, the transport may or may not
                     use this information.
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                     Put the <classname>ObjectName</classname> of a
                     <classname>ServerSocketFactoryMBean</classname> in a configuration
                     map, using key <constant>ServerInvoker.SERVER_SOCKET_FACTORY</constant>,
                     and pass the map to one of the <classname>Connector</classname>
                     constructors. If the MBean has type
                     <classname>SSLServerSocketFactoryServiceMBean</classname>, its
                     configuration information will be gathered and used to construct a
                     <classname>CustomSSLSocketFactory</classname>.
                     <emphasis role="bold">Note.</emphasis>  This method is guaranteed to
                     work only for callback client invokers.  For other, transport
                     specific, socket factory uses, the transport may or may not
                     use this information.
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                     Create an xml document with root element <code>&lt;config&gt;</code>,
                     setting the <code>&lt;socketFactory&gt;</code> attribute to
                     the class name of a <classname>SocketFactory</classname> and pass
                     the document to <methodname>Connector.setConfiguration()</methodname>.
                     For example:
                     
                     <programlisting>
                        StringBuffer buf = new StringBuffer();
                        buf.append("&lt;?xml version=\"1.0\"?&gt;\n");
                        buf.append("&lt;config&gt;");
                        buf.append("   &lt;invoker transport=\"sslsocket\"&gt;");
                        buf.append("      &lt;attribute name=\"serverBindAddress\"&gt;" + getHostName() + "&lt;/attribute&gt;");
                        buf.append("      &lt;attribute name=\"serverBindPort\"&gt;" + freeport + "&lt;/attribute&gt;");
                        buf.append("      &lt;attribute name=\"socketFactory\"&gt;" + socketFactoryClassname + "&lt;/attribute&gt;");
                        buf.append("   &lt;/invoker&gt;");
                        buf.append("&lt;/config&gt;");
                        ByteArrayInputStream bais = new ByteArrayInputStream(buf.toString().getBytes());
                        Document xml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(bais);
                        connector.setConfiguration(xml.getDocumentElement());
                     </programlisting>
                     
                     The <classname>SocketFactory</classname> class must have a
                     default constructor, which will be used to create a 
                  <classname>SocketFactory</classname>.
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                     Put the class name of a <classname>SocketFactory</classname>
                     in a configuration map, using key
                     <constant>Remoting.SOCKET_FACTORY_NAME</constant>, and pass the map
                     to one of the <classname>Connector</classname> constructors. The 
                     <classname>SocketFactory</classname> class
                     must have a default constructor.
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                     Put a set of SSL parameters, using the keys in
                     <classname>org.jboss.remoting.security.SSLSocketBuilder</classname>,
                     in a configuration map and pass the map to one of the
                     <classname>Connector</classname> constructors. These will be used by
                     <classname>SSLSocketBuilder</classname> (see below) to create a
                     <classname>CustomSSLSocketFactory</classname>.
                  
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                     Configure an appropriate set of SSL system properties and use one of
                     the SSL transports (https, sslmultiplex, sslrmi, or sslsocket). The
                     properties will be used to create some kind of
                     <classname>SSLSocketFactory</classname>, as determined by the
                     transport.
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                     Use one of the non-SSL transports and do nothing. Ordinary
                     <classname>Socket</classname>s will be used.
                  </para>
               </listitem>
           </orderedlist>
             
           <para>Again, these are essentially in descending order of precedence.        
              Options 1, 2, 3, 5, and 7 are illustrated in
              <classname>FactoryConfigSample</classname>
              and options 4, 6, 8, and 9 are illustrated in
              <classname>FactoryConfigSSLSample</classname>,
              both of which are in package
              <classname>org.jboss.remoting.samples.config.factories</classname>.
           </para>
           
            <para>
            <emphasis role="bold">Timing considerations.</emphasis> A new
            <classname>Client</classname>, with a client invoker, is created
            on the server side whenever a callback listener is registered by a
            call to <methodname>Client.addListener()</methodname>.  If a 
            <classname>SocketFactory</classname> is supplied by any of options 1 to 5,
            it will be passed to the <classname>Client</classname>.  Otherwise, any
            information from options 6 to 9 will be passed to the client invoker,
            which will create a <classname>SocketFactory</classname> according
            to the rules given below in the section on client side socket factory
            configuration.  Once <methodname>Connector.create()</methodname>
            has been called,
            <methodname>ServerInvoker.setSocketFactory()</methodname>, may be
            called at any time to determine the 
            <classname>SocketFactory</classname> used by the next callback
            client invoker.
            </para>
         </section>
      </section>

      <section>
         <title>Client side programmatic configuration</title>
         <para>
         On the client side it is possible to configure socket factories for client
         invokers and to configure server socket factories for callback server invokers.
         Configuration on the client side is largely the same as configuration
         on the server side, with the exception that no
         <classname>MBeanServer</classname> is assumed to be present, and the
         <classname>Client</classname> has no facilities for parsing xml
         documents.
         </para>
         
         <section>
            <title>Server socket factories.</title>
            <para>For <classname>ServerSocketFactory</classname>s in callback
            server invokers, there are
            eight options for programmatic configuration, which are identical to
            options 1-3, 5 and 7-10 on the server side (we don't assume the
            existence of an <classname>MBeanServer</classname> on the client
            side:</para>
            
            <orderedlist>
               <listitem>
                  <para>Get the <classname>ServerInvoker</classname> by calling
                  <methodname>Connector.getServerInvoker()</methodname> and call
                  <methodname>ServerInvoker.setServerSocketFactory()</methodname>.</para>
               </listitem>
            
               <listitem>
                  <para>Call <methodname>Connector.setServerSocketFactory()</methodname>.
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                  Put a constructed <classname>ServerSocketFactory</classname> in a
                  configuration map, using key
                  <constant>Remoting.CUSTOM_SERVER_SOCKET_FACTORY</constant>,
                  and pass the map to one of the <classname>Connector</classname>
                  constructors.
                  </para>
               </listitem>
                       
               <listitem>
                  <para>
                     Create an xml document with root element <code>&lt;config&gt;</code>,
                     setting the <code>&lt;serverSocketFactory&gt;</code> attribute to
                     the class name of a <classname>ServerSocketFactory</classname> and pass
                     the document to <methodname>Connector.setConfiguration()</methodname>.
                     For example:
                     
                     <programlisting>
                        StringBuffer buf = new StringBuffer();
                        buf.append("&lt;?xml version=\"1.0\"?&gt;\n");
                        buf.append("&lt;config&gt;");
                        buf.append("   &lt;invoker transport=\"sslsocket\"&gt;");
                        buf.append("      &lt;attribute name=\"serverBindAddress\"&gt;" + getHostName() + "&lt;/attribute&gt;");
                        buf.append("      &lt;attribute name=\"serverBindPort\"&gt;" + freeport + "&lt;/attribute&gt;");
                        buf.append("      &lt;attribute name=\"serverSocketFactory\"&gt;" + serverSocketFactoryClassname + "&lt;/attribute&gt;");
                        buf.append("   &lt;/invoker&gt;");
                        buf.append("&lt;/config&gt;");
                        ByteArrayInputStream bais = new ByteArrayInputStream(buf.toString().getBytes());
                        Document xml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(bais);
                        connector.setConfiguration(xml.getDocumentElement());
                     </programlisting>
                     
                     The <classname>ServerSocketFactory</classname> class must
                     have a default constructor, which will be used to create a
                     <classname>ServerSocketFactory</classname>.
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                  Put the class name of a <classname>ServerSocketFactory</classname>
                  in a configuration map, using key
                  <constant>ServerInvoker.SERVER_SOCKET_FACTORY</constant>,
                  and pass the map to one of the <classname>Connector</classname> constructors.
                  The <classname>ServerSocketFactory</classname> class must
                  have a default constructor, which will be used to create a
                  <classname>ServerSocketFactory</classname>.</para>
               </listitem>
                           
               <listitem>
                  <para>
                  Put a set of SSL parameters, using the keys in
                  <classname>org.jboss.remoting.security.SSLSocketBuilder</classname>, in a
                  configuration map and pass the map to one of the
                  <classname>Connector</classname> constructors. These will be used by
                  <classname>SSLSocketBuilder</classname> (see below) to create a
                  <classname>CustomSSLServerSocketFactory</classname>.
                  </para>
               </listitem>
                           
               <listitem>
                  <para>
                  Configure an appropriate set of SSL system properties
                  and use one of the SSL transports (https, sslmultiplex,
                  sslrmi, or sslsocket). The properties will be used to
                  create some kind of <classname>SSLServerSocketFactory</classname>,
                  as determined by the transport.
                  </para>
               </listitem>
                           
               <listitem>
                  <para>
                  Use one of the non-SSL transports and do nothing. A default
                  <classname>ServerSocketFactory</classname> will be constructed.
                  </para>
               </listitem>
            </orderedlist>
            
            <para>
               These options are essentially in descending order of precedence.
               For example, if options 3 and 5, for example, are both
               used, the factory passed in options 3 will prevail.
               Options 1, 2, 3, 4, and 5 are illustrated in
               <classname>FactoryConfigSample</classname>
               and options 6 and 7 are illustrated in
               <classname>FactoryConfigSSLSample</classname>,
               both of which are in package
               <classname>org.jboss.remoting.samples.config.factories</classname>.
            </para>
            
            <para>
            <emphasis role="bold">Timing considerations.</emphasis>  See the
            discussion in the section on the creation of server socket factories
            on the server side.
            </para>
         </section>
   
         <section>
            <title>Socket factories.</title>
            <para>
            For <classname>SocketFactory</classname>s in client invokers,
            there are seven options
            for programmatic configuration, and they are essentially the same as 
            1-3 and 5-8 in the previous section (<classname>Client</classname>
            has no facility for parsing xml documents:</para>
            
            <orderedlist>
      
               <listitem>
                  <para>
                     Get the <classname>ClientInvoker</classname> by calling
                     <methodname>Client.getInvoker()</methodname> and call
                     <methodname>ClientInvoker.setSocketFactory()</methodname>.
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                     Call <methodname>Client.setSocketFactory()</methodname>.
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                     Put a constructed <classname>SocketFactory</classname> in a
                     configuration map, using key
                     <constant>Remoting.CUSTOM_SOCKET_FACTORY</constant>, and pass
                     the map to one of the <classname>Client</classname> constructors.
                  
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                     Put the class name of a <classname>SocketFactory</classname>
                     in a configuration map, using key
                     <constant>Remoting.SOCKET_FACTORY_NAME</constant>, and pass the map
                     to one of the <classname>Client</classname> constructors.
                     The <classname>SocketFactory</classname> class must
                     have a default constructor, which will be used to create a
                     <classname>SocketFactory</classname>.
                  
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                     Put a set of SSL parameters, using the keys in
                     <classname>org.jboss.remoting.security.SSLSocketBuilder</classname>,
                     in a configuration map and pass the map to one of the
                     <classname>Client</classname> constructors. These will be used by
                     <classname>SSLSocketBuilder</classname> (see below) to create a
                     <classname>CustomSSLSocketFactory</classname>.
                  
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                     Configure an appropriate set of SSL system properties and use one of
                     the SSL transports (https, sslmultiplex, sslrmi, or sslsocket). The
                     properties will be used to create some kind of
                     <classname>SSLSocketFactory</classname>, as determined by the
                     transport.
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                     Use one of the non-SSL transports and do nothing. Ordinary
                     <classname>Socket</classname>s will be used.
                  </para>
               </listitem>
           </orderedlist>
             
           <para>Again, these are essentially in descending order of precedence.
               Options 1, 2, 3, and 4 are illustrated in
               <classname>FactoryConfigSample</classname>
               and options 5 and 6 are illustrated in
               <classname>FactoryConfigSSLSample</classname>,
               both of which are in package
               <classname>org.jboss.remoting.samples.config.factories</classname>.
           </para>
           
           <para>
            <emphasis role="bold">Timing considerations.</emphasis> A 
            <classname>SocketFactory</classname> is created in the constructor
            for <classname>RemoteClientInvoker</classname>, the ancestor of
            all current remote client invokers (that is, all client invokers except
            <classname>LocalClientInvoker</classname>, which can make a call
            by reference on a server invoker in the same JVM), but it is
            currently used only by SSL transports, for which the timing 
            considerations vary.</para>
            
            <orderedlist>
            
               <listitem>
                  <para>
                     <emphasis role="bold">https: </emphasis> 
                     <classname>HTTPSClientInvoker</classname> sets the
                     socket factory on its
                     <classname>HttpsURLConnection</classname> each time
                     <methodname>Client.invoke()</methodname> is called.  Option
                     1 may be used to reset the <classname>SocketFactory</classname>
                     for future invocations at any time.
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                     <emphasis role="bold">sslmultiplex: </emphasis> Whichever
                     of <classname>SSLMultiplexClientInvoker</classname> or
                     <classname>SSLMultiplexServerInvoker</classname> first
                     gets sufficient bind and connect information to create a
                     priming socket (see the section on the multiplex invoker for
                     a discussion of priming sockets) passes the
                     current <classname>SocketFactory</classname> to be
                     used to create the actual
                     socket that supports the multiplexed connection.  This
                     happens during the call to either
                     <methodname>Client.connect()</methodname> or
                     <methodname>Connector.create()</methodname>.  Once the
                     actual socket is created, no further configuration is
                     possible
                  </para>
               </listitem>
               
               <listitem>
                  <para>
                     <emphasis role="bold">sslrmi: </emphasis> A 
                     <classname>SocketFactory</classname>
                     is either created or configured for future creation during
                     <methodname>Client.create()</methodname>.  No further
                     configuration is possible.
                  </para>
               </listitem>
                  
               <listitem>
                  <para>
                     <emphasis role="bold">sslsocket: </emphasis> 
                     <classname>SSLSocketClientInvoker</classname> uses the current
                     <classname>SocketFactory</classname> to create a new socket
                     whenever it runs out of available pooled connections. Option
                     1 may be used to reset the <classname>SocketFactory</classname>
                     for future connections at any time.
                  </para>
               </listitem>
            </orderedlist>
         </section>
      </section>
      
      <section>
         <title>Server side configuration in the JBoss Application Server</title>
         
         <para>
         Everything in the previous two sections applies to configuring socket
         and server socket factories in any environment, including inside the
         JBoss Application Server (JBossAS), but JBossAS adds some new options. 
         In particular, the <classname>SARDeployer</classname> (see
         <emphasis>The JBoss 4 Application Server Guide</emphasis>
         on the labs.jboss.org web site) can read information 
         from a <code>*-service.xml</code> file, as discussed above in the
         section "General Connector and Invoker configuration," and use it to
         configure MBeans such as <classname>Connector</classname>s.</para>
         
         <para>
         An example of a service xml that covers all the different
         transport and service configurations can be found within the
         example-service.xml file under the etc directory of the JBoss Remoting
         distribution.</para>

         <para>The server socket factory to be used by a server invoker can be
         set via configuration within the service xml. To do this, the
         serverSocketFactory attribute will need to be set as a sub-element of
         the invoker element (this cannot be done if just specifying the invoker
         configuration using the InvokerLocator attribute). The attribute value
         must be either</para>
         
         <orderedlist>
            <listitem>
               <para>the JMX ObjectName of an MBean that implements the
               <code>org.jboss.remoting.security.ServerSocketFactoryMBean</code>
               interface, or</para>
            </listitem>
            
            <listitem>
               <para>
               the class name of a <classname>ServerSocketFactory</classname>
               with a default constructor.
               </para>
            </listitem>
         </orderedlist>
         
         
         <para>An example of the first case would be:</para>
   
         <programlisting>
            &lt;mbean code="org.jboss.remoting.transport.Connector"
                  xmbean-dd="org/jboss/remoting/transport/Connector.xml"
                  name="jboss.remoting:service=Connector,transport=Socket"
                  display-name="Socket transport Connector"&gt;
   
               &lt;attribute name="Configuration"&gt;
                  &lt;config&gt;
                     &lt;invoker transport="sslsocket"&gt;
                        &lt;attribute name="serverSocketFactory"&gt;
                           jboss.remoting:service=ServerSocketFactory,type=SSL
                        &lt;/attribute&gt;
                        &lt;attribute name="numAcceptThreads"&gt;1&lt;/attribute&gt;
         </programlisting>
         
         <para>The <code>serverSocketFactory</code> attribute is processed
         as follows:</para>
         
         <orderedlist>
            <listitem>
               <para>Take its String value, create an <classname>ObjectName</classname>
               from it, and look up an MBean with that name from the <classname>MBeanServer</classname>
               that the invoker has been registered with (by
               way of the <classname>Connector</classname>).  If an MBean with that
               name is found, create a proxy to it of type
               <code>org.jboss.remoting.security.ServerSocketFactoryMBean</code>.
               (Technically, a user could set the
               <code>serverSocketFactory</code> property with the locator url, but the
               preferred method is to use the explicit configuration via the invoker
               element’s attribute, as discussed above.)</para>
            </listitem>
            
            <listitem>
               <para>If no MBean is found with a matching
               <classname>ObjectName</classname>,
               treat the <code>serverSocketFactory</code> attribute as a class name
               and try to create an instance using the default constructor.</para>
            </listitem>
         </orderedlist>
         
         <para>The JBossRemoting project provides an implementation of the
         ServerSocketFactoryMBean that can be used and should provide most of the
         customization features that would be needed. More on this implementation
         later.</para>
         
         <para>Note that these two options correspond exactly to options 4 and 5
         in section <xref linkend="section-ssf-serverside"/> (on the server side),
         which is how these two new options are implemented.</para>
         
         <para><emphasis role="bold">Timing considerations.</emphasis>  If a
         <classname>Connector</classname> is accessed by way of the 
         <classname>MBeanServer</classname>, then most of the options for
         configuring the server socket factory discussed in 
         <xref linkend="section-ssf-serverside"/> are irrelevant since 
         <classname>ConnectorMBean</classname> does not expose methods for using
         them.  However, when a <classname>Connector</classname> that is registered
         with an <classname>MBeanServer</classname> creates a
         server invoker during a call to
         <methodname>Connector.create()</methodname>, it also registers the
         server invoker with the same <classname>MBeanServer</classname>, which
         means that the server invoker is accessible by way of its
         <classname>ObjectName</classname>, which has the form</para>
         
         <programlisting>
            jboss.remoting:service=invoker,transport=socket,host=www.jboss.com,port=8765
         </programlisting>

         <para>for example, followed by additional parameter=value pairs.  (See
         the jmx-console for a running instance of JBossAS at
         http://localhost:8080/jmx-console/ to see examples of server invoker
         <classname>ObjectName</classname>s.)  Now, if another
         MBean is configured in a <code>*-service.xml</code> file to be
         dependent on the server invoker MBean, e.g.</para>
         
         <programlisting>
            &lt;mbean code="org.jboss.Blah" name="jboss.remoting:whatever,name=blah"&gt;
               &lt;depends optional-attribute-name="serverInvoker"&gt;
                   jboss.remoting:service=invoker,transport=socket,host=www.jboss.com,port=8765
               &lt;/depends&gt;
            &lt;/mbean&gt;
         </programlisting>
         
         <para>then <methodname>org.jboss.Blah.create()</methodname> will have
         access to the designated server invoker after the invoker has been
         created but before it has been started, which means that
         <methodname>ServerInvoker.setServerSocketFactory()</methodname> will be
         effective.  (See the <emphasis>The JBoss 4 Application Server
         Guide</emphasis>, Chapter 2, for more information about the life cycle
         of JBoss MBeans.)</para>
         </section>
       
      <section>
         <title>SSL transports</title>

         <para>There are now four transports that support SSL: https,
         sslmultiplex, sslrmi, and sslsocket.  All of preceding discussion
         applies to each of these, and, moreover, they are all extensions of their
         non-ssl counterparts, so only some ssl specific information will be
         added here.</para>
         
         <bridgehead>https</bridgehead>
   
         <para>The https transport is a bit different from the sslsocket in
         configuration since the implementation is based off the Tomcat
         connectors. The first major difference is the transport protocol keyword
         to identify it, which is 'https'.</para>
   
         <para>Next is defining the SSL implementation and server socket factory
         to be used. The SSL implementation to be used can be set via the
         'SSLImplementation' attribute and should always have a value of
         <code>org.jboss.remoting.transport.coyote.ssl.RemotingSSLImplementation</code>.
         The server socket factory to be used should be set via the
         'serverSocketFactory' attribute and should always be the
         javax.management.ObjectName value for an implementation of the
         <code>org.jboss.remoting.security.ServerSocketFactoryMBean</code>
         interface, which should already be registered with the MBeanServer and
         running (more details on this in a minute).</para>
   
         <para>An example of setting up https via service.xml configuration would
         be:</para>
   
         <programlisting>     &lt;mbean code="org.jboss.remoting.transport.Connector"
         xmbean-dd="org/jboss/remoting/transport/Connector.xml"
         name="jboss.remoting:service=Connector,transport=HTTPS"
         display-name="HTTPS transport Connector"&gt;
   
         &lt;attribute name="Configuration"&gt;
            &lt;config&gt;
               &lt;invoker transport="https"&gt;
                  &lt;!-- The following is for setting the server socket factory.  If want ssl support --&gt;
                  &lt;!-- use a server socket factory that supports ssl.  The only requirement is that --&gt;
                  &lt;!-- the server socket factory value must be an ObjectName, meaning the --&gt;
                  &lt;!-- server socket factory implementation must be a MBean and also --&gt;
                  &lt;!-- MUST implement the org.jboss.remoting.security.ServerSocketFactoryMBean interface. --&gt;
                  &lt;attribute name="serverSocketFactory"&gt;jboss.remoting:service=ServerSocketFactory,type=SSL&lt;/attribute&gt;
                  &lt;attribute name="SSLImplementation"&gt;org.jboss.remoting.transport.coyote.ssl.RemotingSSLImplementation&lt;/attribute&gt;
                  &lt;attribute name="serverBindAddress"&gt;${jboss.bind.address}&lt;/attribute&gt;
                  &lt;attribute name="serverBindPort"&gt;6669&lt;/attribute&gt;
               &lt;/invoker&gt;
               &lt;handlers&gt;
                  &lt;handler subsystem="mock"&gt;org.jboss.test.remoting.transport.mock.MockServerInvocationHandler&lt;/handler&gt;
               &lt;/handlers&gt;
            &lt;/config&gt;
         &lt;/attribute&gt;
         &lt;!-- This depends is included because need to make sure this mbean is running before configure invoker. --&gt;
         &lt;depends&gt;jboss.remoting:service=ServerSocketFactory,type=SSL&lt;/depends&gt;
      &lt;/mbean&gt;
   </programlisting>
   
         <para>Notice that the 'serverSocketFactory' attribute has a value of
         'jboss.remoting:service=ServerSocketFactory,type=SSL', which is not
         defined in the configuration snippet. More on how to define this in the
         next section.</para>
   
         <para>One of the major changes related to using the Tomcat connectors
         with regards to SSL is that everything within Tomcat is defined via
         properties configuration and there is no external API for making changes
         during runtime. This means that there is no way to set server socket
         factory implementation programatically, other than via configuration (so
         cannot call setServerSocketFactory() method on the server invoker as
         could with the ssl socket invoker). This also means that if not running
         within the JBoss Application Server container, but running stand alone,
         will need to setup an MBeanServer and register the server socket factory
         with it programatically. For an example of how to do this
         programatically, can refer to
         org.jboss.test.remoting.transport.http.ssl.basic.HTTPSInvokerTestServer.</para>
   
         <para>The configuration for SSL support only works when using the java
         based http processor and not with the APR based transport. See section
         4.7 for more information on using the APR based transport.</para>
                  
         <bridgehead>sslmultiplex</bridgehead>
         
         <para>The sslmultiplex server invoker inherits from the socket server
         invoker a method with signature</para>
         
         <programlisting>
            public void setNewServerSocketFactory(ServerSocketFactory serverSocketFactory)
         </programlisting>
         
         <para>which supports dynamic replacement of server socket factories.  The
         principal motivation for this facility is to be able to swap in a
         new <classname>SSLServerSocketFactory</classname> configured with an
         updated keystore.</para>
         
         <bridgehead>sslsocket</bridgehead>
         <para>In addition to the various configuration options discussed above,
         the sslsocket transport exposes the</para>
   
         <programlisting>public void setServerSocketFactory(ServerSocketFactory serverSocketFactory)</programlisting>
         
         <para>method as a JMX operation.</para>
         
         <para>Also, the sslsocket server invoker inherits from the socket server
         invoker a method with signature</para>
         
         <programlisting>
            public void setNewServerSocketFactory(ServerSocketFactory serverSocketFactory)
         </programlisting>
         
         <para>which supports dynamic replacement of server socket factories.  The
         principal motivation for this facility is to be able to swap in a
         new <classname>SSLServerSocketFactory</classname> configured with an
         updated keystore.</para>
         
      </section>
         
      <section>
         <title>SSLSocketBuilder</title>
   
         <para>Throughout this section reference has been made to SSL
         socket factory and server socket factory configuration parameters.
         This subsection will introduce these parameters in the context of
         configuring
         <classname>org.jboss.remoting.security.SSLSocketBuilder</classname>,
         Remoting's flexible, highly customizable master factory for creating
         socket and server socket factories.  It can be used programmatically on
         both the client and server side, and it is also a service MBean, so it 
         can be configured and started from within a service xml in a JBossAS 
         environment.</para>
         
         <para>Once a <classname>SSLSocketBuilder</classname> has been
         constructed and configured, a call to its method
         <methodname>createSSLServerSocketFactory()</methodname> will return a custom
         instance of a <classname>SSLServerSocketFactory</classname>, and a 
         call to <methodname>createSSLSocketFactory()</methodname> will
         return a custom instance of <classname>SSLSocketFactory</classname>.</para>
                  
         <para>
         There are two modes in which the <classname>SSLSocketBuilder</classname>
         can be run. The first is the default mode where all that is needed is to
         declare the <classname>SSLSocketBuilder</classname> and set the system properties
         <code>javax.net.ssl.keyStore</code> and
         <code>javax.net.ssl.keyStorePassword</code>. This will use the JVM
         vendor’s default configuration for creating the SSL server socket
         factory.</para>
   
         <para>In order to customize any of the SSL properties, the
         first requirement is that the default mode is turned off. This is
         <emphasis role="bold">IMPORTANT</emphasis> because otherwise, if the
         default mode is not explicitly turned off, all other settings will be
         IGNORED, even if they are explicitly set. To turn off the default mode
         via service xml configuration, set the
         <code>UseSSLServerSocketFactory</code> attribute to false. This can also
         be done programmatically by calling the
         <code>setUseSSLServerSocketFactory()</code> and passing false as the
         parameter value.</para>
         
         <para>There are two ways to configure a
         <classname>SSLSocketBuilder</classname></para>
         
         <orderedlist>
            <listitem>
               <para>set its bean attributes, either programmatically or by xml
               configuration, or</para>
            </listitem>
            
            <listitem>
               <para>pass to a <classname>SSLSocketBuilder</classname> constructor
               a configuration map with keys defined in the
               <classname>SSLSocketBuilder</classname> class.</para>
            </listitem>
         </orderedlist>
         
   
         <para>The configuration properties for
         <classname>SSLSocketBuilder</classname>are as follows:</para>
         
         <table frame="all" id="SSLSocketBuilderTable" xreflabel="Table 1">
            <title><classname>SSLSocketBuilder</classname> configuration 
            parameters.</title>

            <tgroup cols="5">
      
               <colspec colname="c1" colnum="1"/>
               <colspec colname="c2" colnum="2"/>
               <colspec colname="c3" colnum="3" align="center"/>
               <colspec colname="c4" colnum="4" align="center"/>
               <colspec colname="c5" colnum="5"/>
                           
               <thead>
                  <row>
                     <entry>
                        <para>attribute</para>
                     </entry>
                     <entry>
                        <para>key name</para>
                     </entry>
                     <entry>
                        <para>type</para>
                     </entry>
                     <entry>
                        <para>default</para>
                     </entry>
                     <entry>
                        <para>description</para>
                     </entry>
                  </row>
               </thead>
      
               <tbody>
                  <row>
                     <entry><para>ClientAuthMode</para></entry>
                     <entry><para>REMOTING_CLIENT_AUTH_MODE</para></entry>
                     <entry><para>String</para></entry>
                     <entry><para>need</para></entry>
                     <entry>
                        <para>Determines if sockets need or want
                        client authentication. This configuration option is only
                        useful for sockets in the server mode.  Value may be
                        "none", "want", or "need".</para></entry>
                  </row>
                  
                  <row>
                     <entry><para>KeyAlias</para></entry>
                     <entry><para>REMOTING_KEY_ALIAS</para></entry>
                     <entry><para>String</para></entry>
                     <entry><para></para></entry>
                     <entry>
                        <para>The preferred identity in key store to be used by
                        key managers</para></entry>
                  </row>
                  
                  <row>
                     <entry><para>KeyPassword</para></entry>
                     <entry><para>REMOTING_KEY_PASSWORD</para></entry>
                     <entry><para>String</para></entry>
                     <entry><para></para></entry>
                     <entry>
                        <para>Sets the password to use for the keys within the key store.
                        This only needs to be set if
                        <methodname>setUseSSLServerSocketFactory()</methodname> is set to false
                        (otherwise will be ignored). If this value is not set, but
                        the key store password is, it will use that value for the
                        key password.</para></entry>
                  </row>
                  
                  <row>
                     <entry><para>KeyStoreAlgorithm</para></entry>
                     <entry><para>REMOTING_KEY_STORE_ALGORITHM</para></entry>
                     <entry><para>String</para></entry>
                     <entry><para>SunX509</para></entry>
                     <entry>
                        <para>The algorithm for the key manager factory.</para></entry>
                  </row>
                  
                  <row>
                     <entry><para>KeyStorePassword</para></entry>
                     <entry><para>REMOTING_KEY_STORE_PASSWORD</para></entry>
                     <entry><para>String</para></entry>
                     <entry><para></para></entry>
                     <entry>
                        <para>The password
                        to use for the key store. This only needs to be set if
                        <methodname>setUseSSLServerSocketFactory()</methodname>
                        is set to false (otherwise will be
                        ignored). The value passed will also be used for the
                        key password if the latter attribute is not explicitly
                        set.</para></entry>
                  </row>
                  
                  <row>
                     <entry><para>KeyStoreType</para></entry>
                     <entry><para>REMOTING_KEY_STORE_TYPE</para></entry>
                     <entry><para>String</para></entry>
                     <entry><para>JKS</para></entry>
                     <entry>
                        <para>The type to be
                        used for the key store. Some
                        acceptable values are JKS (Java Keystore - Sun's keystore
                        format), JCEKS (Java Cryptography Extension keystore -
                        More secure version of JKS), and PKCS12 (Public-Key
                        Cryptography Standards #12 keystore - RSA's Personal
                        Information Exchange Syntax Standard). These are not case
                        sensitive.</para></entry>
                  </row>               
                  
                  <row>
                     <entry><para>KeyStoreURL</para></entry>
                     <entry><para>REMOTING_KEY_STORE_FILE_PATH</para></entry>
                     <entry><para>String</para></entry>
                     <entry><para></para></entry>
                     <entry>
                        <para>Property used to define where
                        <classname>SSLSocketBuilder</classname> will
                        look for the keystore file. This can be relative to the thread's
                        classloader or can be an absolute path on the file system or
                        can be a URL.</para></entry>
                  </row>      
                  
                  <row>
                     <entry><para>Provider</para></entry>
                     <entry><para>none</para></entry>
                     <entry><para>java.security.Provider</para></entry>
                     <entry><para></para></entry>
                     <entry>
                        <para>Java Security API implementation to use.</para></entry>
                  </row>  
                  
                  <row>
                     <entry><para>ProviderName</para></entry>
                     <entry><para>REMOTING_SSL_PROVIDER_NAME</para></entry>
                     <entry><para>String</para></entry>
                     <entry><para></para></entry>
                     <entry>
                        <para>Name of Java Security API implementation to use.
                        </para></entry>
                  </row>  
                                 
                  <row>
                     <entry><para>SecureRandom</para></entry>
                     <entry><para>none</para></entry>
                     <entry><para>java.security.SecureRandom</para></entry>
                     <entry><para><code>new SecureRandom()</code></para></entry>
                     <entry>
                        <para>Random number generator to use.</para></entry>
                  </row>  
                  
                  <row>
                     <entry><para>SecureSocketProtocol</para></entry>
                     <entry><para>REMOTING_SSL_PROTOCOL</para></entry>
                     <entry><para>String</para></entry>
                     <entry><para>TLS</para></entry>
                     <entry>
                        <para> The protocol for the <classname>SSLContext</classname>.
                        Some acceptable values are TLS, SSL, and SSLv3</para></entry>
                  </row>  
                  
                  <row>
                     <entry><para>ServerAuthMode</para></entry>
                     <entry><para>REMOTING_SERVER_AUTH_MODE</para></entry>
                     <entry><para>boolean/String</para></entry>
                     <entry><para>true</para></entry>
                     <entry>
                        <para>Determines if a client should attempt to
                        authenticate a server certificate as one it trusts.</para></entry>
                  </row>               
                  
                  <row>
                     <entry><para>ServerSocketUseClientMode</para></entry>
                     <entry><para>REMOTING_SERVER_SOCKET_USE_CLIENT_MODE</para></entry>
                     <entry><para>boolean/String</para></entry>
                     <entry><para>false</para></entry>
                     <entry>
                        <para>Determines if the server sockets will be in
                        client or server mode.</para></entry>
                  </row>  
                                 
                  <row>
                     <entry><para>SocketUseClientMode</para></entry>
                     <entry><para>REMOTING_SOCKET_USE_CLIENT_MODE</para></entry>
                     <entry><para>boolean/String</para></entry>
                     <entry><para>true</para></entry>
                     <entry>
                        <para>Determines if the sockets will be in
                        client or server mode.</para></entry>
                  </row>  
                  
                  <row>
                     <entry><para>TrustStoreAlgorithm</para></entry>
                     <entry><para>REMOTING_TRUST_STORE_ALGORITHM</para></entry>
                     <entry><para>String</para></entry>
                     <entry><para>value of <code>KeyStoreAlgorithm</code>, or
                            SunX509 if <code>KeyStoreAlgorithm</code>
                            is not set</para></entry>
                     <entry>
                        <para>trust store key management algorithm</para></entry>
                  </row>  
                  
                  <row>
                     <entry><para>TrustStorePassword</para></entry>
                     <entry><para>REMOTING_TRUST_STORE_PASSWORD</para></entry>
                     <entry><para>String</para></entry>
                     <entry><para></para></entry>
                     <entry>
                        <para>trust store password</para></entry>
                  </row> 
                  
                  <row>
                     <entry><para>TrustStoreType</para></entry>
                     <entry><para>REMOTING_TRUST_STORE_TYPE</para></entry>
                     <entry><para>String</para></entry>
                     <entry><para>value of <code>KeyStoreType</code>, or
                            JKS if <code>KeyStoreType</code>
                            is not set</para></entry>
                     <entry>
                        <para>type of trust store</para></entry>
                  </row>                 
                  
                  <row>
                     <entry><para>TrustStoreURL</para></entry>
                     <entry><para>REMOTING_TRUST_STORE_FILE_PATH</para></entry>
                     <entry><para>String</para></entry>
                     <entry><para></para></entry>
                     <entry>
                        <para>location of trust store</para></entry>
                  </row> 
                  
                  <row>
                     <entry><para>UseSSLServerSocketFactory</para></entry>
                     <entry><para>none</para></entry>
                     <entry><para>boolean</para></entry>
                     <entry><para>true</para></entry>
                     <entry>
                        <para>Determines if default
                        <classname>SSLServerSocketFactory</classname> should be
                        created.</para></entry>
                  </row> 
                  
                  <row>
                     <entry><para>UseSSLSocketFactory</para></entry>
                     <entry><para>none</para></entry>
                     <entry><para>boolean</para></entry>
                     <entry><para>true</para></entry>
                     <entry>
                        <para>Determines if default
                        <classname>SSLSocketFactory</classname> should be
                        created.</para></entry>
                  </row> 
               </tbody>
            </tgroup>
         </table>

         <para><emphasis role="bold">Note.</emphasis>
            If any of the attributes <code>KeyStoreURL</code>,
            <code>KeyStorePassword</code>, <code>KeyStoreType</code>,
            <code>TrustStoreURL</code>, <code>TrustStorePassword</code>, or
            <code>TrustStoreType</code> are left unconfigured, 
            <classname>SSLSocketBuilder</classname> will also examine the
            corresponding standard SSL system properties "javax.net.ssl.keyStore",
            "javax.net.ssl.keyStorePassword", "javax.net.ssl.keyStoreType",
            "javax.net.ssl.trustStore", "javax.net.ssl.trustStorePassword",
            "javax.net.ssl.trustStoreType". In the cases of 
            <code>KeyStoreType</code> and <code>TrustStoreType</code>, 
            <classname>SSLSocketBuilder</classname> will then
            go on to use default values after checking the system
            properties.</para>
         
         <para>The following is an example of configuring a
         <classname>SSLSocketBuilder</classname> and using it to create a custom
         <classname>SSLSocketFactory</classname>:</para>
         
         <programlisting>
         protected SSLSocketFactory getSocketFactory() throws Exception
         {
            HashMap config = new HashMap();
            config.put(SSLSocketBuilder.REMOTING_KEY_STORE_TYPE, "JKS");
            String keyStoreFilePath = getKeystoreFilePath();
            config.put(SSLSocketBuilder.REMOTING_KEY_STORE_FILE_PATH, keyStoreFilePath);
            config.put(SSLSocketBuilder.REMOTING_KEY_STORE_PASSWORD, "unit-tests-server");
            config.put(SSLSocketBuilder.REMOTING_SSL_PROTOCOL, "SSL");
            SSLSocketBuilder builder = new SSLSocketBuilder(config);
            builder.setUseSSLSocketFactory(false);
            return builder.createSSLSocketFactory();
         }
         </programlisting>
         
         <para>More examples of configuring <classname>SSLSocketBuilder</classname> can
         be found in the class <classname>FactoryConfigSSLSample</classname> in the
         package <code>org.jboss.remoting.samples.config.factories</code>.</para>
         
         <para>The following is an example of configuring
         <classname>SSLSocketBuilder</classname> in a *-service.xml file:</para>
         
         <programlisting>
            &lt;!-- This service is used to build the SSL Server socket factory --&gt;
            &lt;!-- This will be where all the store/trust information will be set. --&gt;
            &lt;!-- If do not need to make any custom configurations, no extra attributes --&gt;
            &lt;!-- need to be set for the SSLSocketBuilder and just need to set the --&gt;
            &lt;!-- javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword system properties. --&gt;
            &lt;!-- This can be done by just adding something like the following to the run --&gt;
            &lt;!-- script for JBoss --&gt;
            &lt;!-- (this one is for run.bat): --&gt;
            &lt;!-- set JAVA_OPTS=-Djavax.net.ssl.keyStore=.keystore --&gt;
            &lt;!-- -Djavax.net.ssl.keyStorePassword=opensource %JAVA_OPTS% --&gt;
            &lt;!-- Otherwise, if want to customize the attributes for SSLSocketBuilder, --&gt;
            &lt;!-- will need to uncomment them below. --&gt;
            &lt;mbean code="org.jboss.remoting.security.SSLSocketBuilder"
                  name="jboss.remoting:service=SocketBuilder,type=SSL"
                  display-name="SSL Server Socket Factory Builder"&gt;
               &lt;!-- IMPORTANT - If making ANY customizations, this MUST be set to false. --&gt;
               &lt;!-- Otherwise, will used default settings and the following attributes will be ignored. --&gt;
               &lt;attribute name="UseSSLServerSocketFactory"&gt;false&lt;/attribute&gt;
               &lt;!-- This is the url string to the key store to use --&gt;
               &lt;attribute name="KeyStoreURL"&gt;.keystore&lt;/attribute&gt;
               &lt;!-- The password for the key store --&gt;
               &lt;attribute name="KeyStorePassword"&gt;opensource&lt;/attribute&gt;
               &lt;!-- The password for the keys (will use KeystorePassword if this is not set explicitly. --&gt;
               &lt;attribute name="KeyPassword"&gt;opensource&lt;/attribute&gt;
               &lt;!-- The protocol for the SSLContext. Default is TLS. --&gt;
               &lt;attribute name="SecureSocketProtocol"&gt;TLS&lt;/attribute&gt;
               &lt;!-- The algorithm for the key manager factory. Default is SunX509. --&gt;
               &lt;attribute name="KeyManagementAlgorithm"&gt;SunX509&lt;/attribute&gt;
               &lt;!-- The type to be used for the key store. --&gt;
               &lt;!-- Defaults to JKS. Some acceptable values are JKS (Java Keystore - Sun's keystore format), --&gt;
               &lt;!-- JCEKS (Java Cryptography Extension keystore - More secure version of JKS), and --&gt;
               &lt;!-- PKCS12 (Public-Key Cryptography Standards #12 keystore - RSA's Personal Information Exchange Syntax Standard). --&gt;
               &lt;!-- These are not case sensitive. --&gt;
               &lt;attribute name="KeyStoreType"&gt;JKS&lt;/attribute&gt;
            &lt;/mbean&gt;
         </programlisting>
      </section>
   
      <section>
         <title>SSLServerSocketFactoryService</title>
  
         <para>Although any server socket factory can be set for the various
         transports, there is a customizable server socket factory service
         provided within JBossRemoting that supports SSL. This is the
         <code>org.jboss.remoting.security.SSLServerSocketFactoryService</code>
         class. The <code>SSLServerSocketFactoryService</code> class extends the
         <code>javax.net.ServerSocketFactory</code> class and also implements the
         <code>SSLServerSocketFactoryServiceMBean</code> interface (so that it
         can be set using the <code>socketServerFactory</code> attribute
         described previously). Other than providing the proper interfaces, this
         class is a simple wrapper around the
         <code>org.jboss.remoting.security.SSLSocketBuilder</code> class.</para>

         <para>The following is an example of configuring
         <classname>SSLServerSocketFactoryService</classname> in a *-service.xml
         file.  Note that it depends on the <classname>SSLSocketBuilder</classname>
         MBean defined in the xml fragment above:</para>
      
      <programlisting>
         &lt;!-- This service provides the exact same API as the ServerSocketFactory, so --&gt;
         &lt;!-- can be set as an attribute of that type on any MBean requiring an ServerSocketFactory. --&gt;
         &lt;mbean code="org.jboss.remoting.security.SSLServerSocketFactoryService"
               name="jboss.remoting:service=ServerSocketFactory,type=SSL"
               display-name="SSL Server Socket Factory"&gt;
            &lt;depends optional-attribute-name="SSLSocketBuilder"
               proxy-type="attribute"&gt;jboss.remoting:service=SocketBuilder,type=SSL&lt;/depends&gt;
         &lt;/mbean&gt;
      </programlisting>
      
      </section>
   
      <section>
         <title>General Security How To</title>
   
         <para>Since we are talking about keystores and truststores, this section
         will quickly go over how to quickly generate a test keystore and
         truststore for testing. This is not intended to be a full security
         overview, just an example of how I originally created mine for
         testing.</para>
   
         <para>To get started, will need to create key store and trust
         store.</para>
   
         <para>Generating key entry into keystore:</para>
   
         <programlisting>
               C:\tmp\ssl&gt;keytool -genkey -alias remoting -keyalg RSA
               Enter keystore password: opensource
               What is your first and last name?
               [Unknown]: Tom Elrod
               What is the name of your organizational unit?
               [Unknown]: Development
               What is the name of your organization?
               [Unknown]: JBoss Inc
               What is the name of your City or Locality?
               [Unknown]: Atlanta
               What is the name of your State or Province?
               [Unknown]: GA
               What is the two-letter country code for this unit?
               [Unknown]: US
               Is CN=Tom Elrod, OU=Development, O=JBoss Inc, L=Atlanta, ST=GA, C=US correct?
               [no]: yes
   
               Enter key password for &lt;remoting&gt;
               (RETURN if same as keystore password):
            </programlisting>
   
         <para>Since did not specify the -keystore filename parameter, created
         the keystore in $HOME/.keystore (or C:\Documents and
         Settings\Tom\.keystore).</para>
   
         <para>Export the RSA certificate (without the private key)</para>
   
         <programlisting>
               C:\tmp\ssl&gt;keytool -export -alias remoting -file remoting.cer
               Enter keystore password: opensource
               Certificate stored in file &lt;remoting.cer&gt;
            </programlisting>
   
         <para>Import the RSE certificate into a new truststore file.</para>
   
         <programlisting>
               C:\tmp\ssl&gt;keytool -import -alias remoting -keystore .truststore -file remoting.cer
               Enter keystore password: opensource
               Owner: CN=Tom Elrod, OU=Development, O=JBoss Inc, L=Atlanta, ST=GA, C=US
               Issuer: CN=Tom Elrod, OU=Development, O=JBoss Inc, L=Atlanta, ST=GA, C=US
               Serial number: 426f1ee3
               Valid from: Wed Apr 27 01:10:59 EDT 2005 until: Tue Jul 26 01:10:59 EDT 2005
               Certificate fingerprints:
               MD5: CF:D0:A8:7D:20:49:30:67:44:03:98:5F:8E:01:4A:6A
               SHA1: C6:76:3B:6C:79:3B:8D:FD:FB:4F:33:3B:25:C9:01:9D:50:BF:9F:8A
               Trust this certificate? [no]: yes
               Certificate was added to keystore
            </programlisting>
   
         <para>Now have two files, .keystore for the server and .truststore for
         the client.</para>
      </section>
      
      <section>
         <title>Troubleshooting Tips</title>
   
         <para>Common errors when using server socket factory:</para>
   
         <programlisting>javax.net.ssl.SSLException: No available certificate corresponds to the SSL cipher suites which are enabled.</programlisting>
   
         <para>The 'javax.net.ssl.keyStore' system property has not been set and
         are using the default SSLServerSocketFactory.</para>
   
         <programlisting>java.net.SocketException: Default SSL context init failed: Cannot recover key</programlisting>
   
         <para>The 'javax.net.ssl.keyStorePassword' system property has not been
         set and are using the default SSLServerSocketFactory.</para>
   
         <programlisting>java.io.IOException: Can not create SSL Server Socket Factory due to the url to the key store not being set.</programlisting>
   
         <para>The default SSLServerSocketFactory is NOT being used (so custom
         configuration for the server socket factory) and the key store url has
         not been set.</para>
   
         <programlisting>java.lang.IllegalArgumentException: password can't be null</programlisting>
   
         <para>The default SSLServerSocketFactory is NOT being used (so custom
         configuration for the server socket factory) and the key store password
         has not been set.</para>
      </section>
    </section>

    <section>
      <title>Configuration by properties</title>

      <para>This section covers configuration properties by constant values
      and bean properties for individual classes. This will duplicate some of
      the configuration properties already covered and is just another view to
      some of the same information.</para>

      <bridgehead>org.jboss.remoting.InvokerLocator</bridgehead>

      <para><emphasis role="bold">SERVER_BIND_ADDRESS</emphasis> (actual value
      is 'jboss.bind.address') - indicates the system property key for bind
      address that should be used.</para>

      <para><emphasis role="bold">BIND_BY_HOST</emphasis> (actual value is
      'remoting.bind_by_host') - indicates the system property key for if the
      local bind address should be by host name (e.g.
      InetAddress.getLocalHost().getHostName()) or if should be by IP (e.g.
      InetAddress.getLocalHost().getHostAddress()). The default is 'True',
      meaning will will use local host name. This configuration only applies
      when the initial bind address is 0.0.0.0 (or InvokerLocator.ANY).</para>

      <para><emphasis role="bold">DATATYPE</emphasis> (actual value is
      'datatype') - indicates the marshalling datatype that should be used for
      a particular invoker. Each invoker has its own default marshaller and
      unmarshaller based on default datatype. For examle, the socket transport
      has a default datatype of 'serializable', which is has a default
      registry within the MarshalFactory to use
      org.jboss.remoting.marshal.serializable.SerializableMarshaller and
      org.jboss.remoting.marshal.serializable.SerializableUnMarshaller. The
      marshaller and unmarshaller used by an invoker can be overriden by
      setting the 'datatype' parameter within the LocatorInvoker. For example,
      could use a locator url of:</para>

      <programlisting>socket://myhost:6500/?datatype=test</programlisting>

      <para>which would cause the socket invoker to use the marshaller and
      unmarshaller registered with the MarshalFactory under the datatype
      'test'. Of course, this require that the marshaller and unmarshaller
      implementations to be used have already been registered with the
      MarshalFactory (otherwise will get an exception).</para>

      <para><emphasis role="bold">SERIALIZATIONTYPE</emphasis> (actual value
      is 'serializationtype') - indicates the serialization implementation to
      use. Currently, the only possible values are 'java' and 'jboss'. Java
      serialization is the default. Setting to 'jboss' will cause JBoss
      Serialization to be used. In implementation, this equates to the
      parameter that will be passed to the
      SerializationStreamFactory.getManagerInstance() method. This
      configuration can be set as an invoker locator url parameter (e.g.
      socket://myhost:5400/?serializationtype=jboss) or as an entry to the
      configuration Map passed when constructing a remoting client or
      server.</para>

      <para><emphasis role="bold">MARSHALLER</emphasis> (actual value is
      'marshaller') - used to indicate which marshaller implementation should
      be used by the invoker. This is an override for whatever the invoker's
      default implementation is. This can be set as a parameter of the invoker
      locator url (e.g.
      socket://myhost:6500/?marshaller=org.jboss.test.remoting.marshall.dynamic.remote.http.TestMarshaller).
      Using this configuration requires that the value be the fully qualified
      classname of the marshaller implementation to use (which must be on the
      classpath, have a void constructor, and implement the
      org.jboss.remoting.marshal.Marshaller interface).</para>

      <para><emphasis role="bold">UNMARSHALLER</emphasis> (actual value is
      'unmarshaller') - used to indicate which unmarshaller implementation
      should be used by the invoker. This is an override for whatever the
      invoker's default implementation is. This can be set as a parameter of
      the invoker locator url (e.g.
      socket://myhost:6500/?unmarshaller=org.jboss.test.remoting.marshall.dynamic.remote.http.TestUnMarshaller).
      Using this configuration requires that the value be the fully qualified
      classname of the unmarshaller implementation to use (which must be on
      the classpath, ahve a void constructor, and implement the
      org.jboss.remotng.marshal.UnMarshaller interface).</para>

      <para><emphasis role="bold">LOADER_PORT</emphasis> (actual value is
      'loaderport') - indicates the port number where the class loader server
      resides. This can be used when is possible that a client may not have
      particular classes locally and would want to load them from ther
      dynamically. This property can be set as a parameter to the invoker
      locator url. A clasic example of when this might be used would be in
      conjunction with using custom marshalling. For example, if have
      configured a server to use custom marshaller and unmarshaller that the
      client will not have access to, could create a invoker locator such
      as:</para>

      <programlisting>socket://myhost:6500/?datatype=test&amp;loaderport=6501&amp;
marshaller=org.jboss.test.remoting.marshall.dynamic.remote.http.TestMarshaller&amp;
unmarshaller=org.jboss.test.remoting.marshall.dynamic.remote.http.TestUnMarshaller</programlisting>

      <para>When the client invoker begins to make an invocation, will try to
      look up marshaller and unmarshaller based on type ('test' in this case)
      and when can not find a registry entry for it, will try to load the
      TestMarshaller and TestUnMarshaller from the classpath. When the classes
      can not be found locally, will make a call to the loader server (on port
      6501) to load the classes locally. Once they are retreived from the
      server, will be registered locally, so is a one time only event (as next
      time will be found in the registry).</para>

      <para>This can work for loading any remote server classes, but requires
      the loaderport be included in the invoker locator url.</para>

      <para><emphasis role="bold">BYVALUE</emphasis> (actual value is
      'byvalue') - indicates if when making local invocations (meaning client
      and server invoker exists within same jvm), the marshalling will be done
      by value, instead of the default, by reference. Using this
      configuration, the marshalling will actually perform a clone of the
      object instance (see
      org.jboss.remoting.serialization.SerializationManager.createMarshalledValueForClone()).
      Value for this property should be of type String and be either 'true' or
      'false'.</para>

      <para><emphasis role="bold">FORCE_REMOTE</emphasis> (actual value is
      'force_remote') - indicates if when making local invocations (meaning
      client and server invoker exists within same jvm), the remote invokers
      should be used instead of local invoker. Is equivalent to making
      invocations as though client and server were in different jvms). Value
      for this property should be of type String and be either 'true' or
      'false'.</para>

      <para><emphasis role="bold">CLIENT_LEASE</emphasis> (actual value is
      'leasing') - indicates if client should try to automatically establish a
      lease with the server. Is false by default. Value for this property
      should be of type String and be either 'true' or 'false'.</para>

      <para><emphasis role="bold">CLIENT_LEASE_PERIOD</emphasis> (actual value
      is 'lease_period') - defines what the client lease period should be in
      the case that server side leasing is turned on. Value for this parameter
      key should be the number of milliseconds to wait before each client
      lease renewal and must be greater than zero in order to be recognized.
      If this property is not set (and CLIENT_LEASE is), will use the lease
      period as specified by the server.</para>

      <para></para>

      <bridgehead>org.jboss.remoting.Client</bridgehead>

      <para><emphasis role="bold">RAW</emphasis> (actual value is
      'rawPayload') - key to use for the metadata Map passed when making a
      invoke() call and wish for the invocation payload to be sent as is and
      not wrapped within a remoting invocation request object. This should be
      used when want to make direct calls on systems outside of remoting (e.g.
      making a http POST request to a web service).</para>

      <para><emphasis role="bold">ENABLE_LEASE</emphasis> (actual value is
      'enableLease') - key for the configuration map passed to the Client
      constructor to indicate that client should make initial request to
      establish lease with server. The value for this should be either a
      String that java.lang.Boolean can evaluate or a java.lang.Boolean. By
      default, leasing is turned off, so this property would be used to turn
      on leasing for the client.</para>

      <para><emphasis role="bold">HANDSHAKE_COMPLETED_LISTENER</emphasis>
      (actual value is 'handshakeCompletedListener') - key for the
      configuration map passed to the Client constructor providing a ssl
      javax.net.ssl.HandshakeCompletedListener implementation, which will be
      called on when ssl handshake completed with server.</para>

      <para></para>

      <para>The following three configuration properties are only useful when
      using one of the following Client methods:</para>

      <programlisting>public void addListener(InvokerCallbackHandler callbackhandler, Map metadata, Object callbackHandlerObject) throws Throwable
public void addListener(InvokerCallbackHandler callbackhandler, Map metadata, Object callbackHandlerObject, boolean serverToClient) throws Throwable</programlisting>

      <para> <emphasis role="bold">CALLBACK_SERVER_PROTOCOL</emphasis> (actual
      value is 'callbackServerProtocol') - key for the configuration when
      adding a callback handler and internal callback server connector is
      created. The value should be the transport protocol to be used. By
      default will use the same protocol as being used by this client (e.g.
      http, socket, rmi, multiplex, etc.).</para>

      <para><emphasis role="bold">CALLBACK_SERVER_HOST</emphasis> (actual
      value is 'callbackServerHost') - key for the configuration when adding a
      callback handler and internal callback server connector is created. The
      value should be the host name to be used. By default will use the result
      of calling InetAddress.getLocalHost().getHostAddress().</para>

      <para><emphasis role="bold">CALLBACK_SERVER_PORT</emphasis> (actual
      value is 'callbackServerPort') - key for the configuration when adding a
      callback handler and internal callback server connector is created. The
      value should be the port to be used. By default will find a random
      unused port. </para>

      <para></para>

      <para><emphasis role="bold">Bean properties (meaning have
      getter/setter):</emphasis> <emphasis role="bold">SessionId</emphasis> -
      session id used when making invocations on server invokers. There is a
      default unique id automatically generated for each Client instance, so
      unless you have a good reason to set this, do not set this.</para>

      <para><emphasis role="bold">Subsystem</emphasis> - the subsystem being
      used when routing invocation requests on the server side. Specifing a
      subsystem is only needed when server has multiple handlers registered
      (which will each have their own associated subsystem). Best if specified
      using Client constructor.</para>

      <para><emphasis role="bold">MaxNumberOfThreads</emphasis> - the maximum
      number of threads to use within client pool for one way invocations on
      the client side (meaning oneway invocation is handled by thread in this
      pool and user's call returns immediately) Default value is
      MAX_NUM_ONEWAY_THREADS (whose value is 10).</para>

      <para><emphasis role="bold">OnewayThreadPool</emphasis> - the thread
      pool being used for making one way invocations on the client side. If
      one has not be specifically set via configuration or call to set it,
      will always return instance of
      org.jboss.util.threadpool.BasicThreadPool.</para>

      <para><emphasis role="bold">SocketFactory</emphasis> - instance of
      javax.net.SocketFactory, which can only be set on the Client before the
      connect() method has been called. Otherwise, a runtime exception will be
      thrown.</para>

      <para><emphasis role="bold">Marshaller</emphasis> - the marshaller
      implementation that should be used by the client invoker (transport).
      This overrides the client's default marshaller (or any set within
      configuration).</para>

      <para><emphasis role="bold">UnMarshaller</emphasis> - the unmarshaller
      implementation that should be used by the client invoker (transport).
      This overrides the client's default unmarshaller (or any set within
      configuration). </para>

      <para></para>

      <bridgehead>org.jboss.remoting.Remoting</bridgehead>

      <para><emphasis role="bold">CUSTOM_SERVER_SOCKET_FACTORY</emphasis>
      (actual value is 'customServerSocketFactory') - key for the
      configuration map passed to a Connector to indicate the server socket
      factory to be used. This will override the creation of any other socket
      factory. Value must be an instance of
      javax.net.ServerSocketFactory.</para>

      <para><emphasis role="bold">CUSTOM_SOCKET_FACTORY</emphasis> (actual
      value is 'customSocketFactory') - key for the configuration map passed
      to a Client to indicate the socket factory to be used. This will
      override the creation of any other socket factory. Value must be
      instance of javax.net.SocketFactory.</para>

      <para><emphasis role="bold">SOCKET_FACTORY_NAME</emphasis> (actual value
      is 'customSocketFactoryName') - key for the configuration map passed to
      a Client to indicate the classname of the socket factory to be used.
      Value should be fully qualified classname of class that is an instance
      of javax.net.SocketFactory and has a void constructor. This property
      will not be used if CUSTOM_SOCKET_FACTORY is also set. </para>

      <para></para>

      <bridgehead>org.jboss.remoting.ServerInvoker</bridgehead>

      <para><emphasis role="bold">MAX_NUM_ONEWAY_THREADS_KEY</emphasis>
      (actual value is 'maxNumThreadsOneway') - key for the maximum number of
      thread to be used in the thread pool for one way invocations (server
      side). This property is only used when the default oneway thread pool is
      used.</para>

      <para><emphasis role="bold">ONEWAY_THREAD_POOL_CLASS_KEY</emphasis>
      (actual value is 'onewayThreadPool') - key for setting the setting the
      oneway thread pool to use. The value used with this key will first be
      checked to see if is a JMX ObjectName and if so, try to look up
      associated mbean for the ObjectName given and cast to type
      org.jboss.util.threadpool.ThreadPoolMBean (via
      MBeanServerInvocationHandler.newProxyInstance()). If the value is not a
      JMX ObjectName, will assume is a fully qualified classname and load the
      coresponding class and create a new instance of it (which will require
      it to have a void constructor). The newly created instance will then be
      cast to type of org.jboss.util.threadpool.ThreadPool.</para>

      <para><emphasis role="bold">SERVER_BIND_ADDRESS_KEY</emphasis> (actual
      value is 'serverBindAddress') - key for setting the address the server
      invoker should bind to. The value can be either host name or IP.</para>

      <para><emphasis role="bold">CLIENT_CONNECT_ADDRESS_KEY</emphasis>
      (actual value is 'clientConnectAddress') - key for setting the addres
      the client invoker should connecto to. This should be used when client
      will be connecting to server from outside the server's network and the
      external address is different from that of the internal address the
      server invoker will bind to (e.g. using NAT to expose different external
      address). This will mostly be useful when client uses remoting detection
      to discover remoting servers. The value can be either host name or
      IP.</para>

      <para><emphasis role="bold">SERVER_BIND_PORT_KEY</emphasis> (actual
      value is 'serverBindPort') - key for setting the port the server invoker
      should bind to. If the value supplied is less than or equal to zero, the
      server invoker will randomly choose a free port to use.</para>

      <para><emphasis role="bold">CLIENT_CONNECT_PORT_KEY</emphasis> (actual
      value is 'clientConnectPort') - key for setting the port the client
      invoker should connect to. This should be used when client will be
      connecting to server from outside the server's network and the external
      port is different from that of the internal port the server invoker will
      bind to (e.g. using NAT to expose different port routing). This will be
      mostly useful when client uses remoting detection to discover remoting
      servers.</para>

      <para><emphasis role="bold">CLIENT_LEASE_PERIOD</emphasis> (actual value
      is 'clientLeasePeriod') - key used for setting the amount of time (in
      milliseconds) that a client should renew its lease. If this value is not
      set, the default of five seconds (see DEFAULT_CLIENT_LEASE_PERIOD), will
      be used. This value will also be what is given to the client when it
      initially querys server for leasing information.</para>

      <para><emphasis role="bold">TIMEOUT</emphasis> (actual value is
      'timeout') - key for setting the timeout value (in milliseconds) for
      socket connections.</para>

      <para><emphasis role="bold">SERVER_SOCKET_FACTORY</emphasis> (actual
      value is 'serverSocketFactory') - key for setting the value for the
      server socket factory to be used by the server invoker. The value can be
      either a JMX Object name, in which case will lookup the mbean and create
      a proxy to it with type of
      org.jboss.remoting.security.ServerSocketFactoryMBean (via
      MBeanServerInvocationHandler.newProxyInstance()). If not a JMX
      ObjectName, will assume is the fully qualified classname to the
      implementation to be used and will load the class, create a new instance
      of it (which requires it to have a void constructor). The instance will
      then be cast to type javax.net.ServerSocketFactory.</para>

      <para></para>

      <para><emphasis role="bold">Bean properties (meaning have
      getter/setter):</emphasis></para>

      <para><emphasis role="bold">ServerSocketFactory</emphasis> -
      implementation of javax.net.ServerSocketFactory to be used by the server
      invoker. This takes precedence over any other configuration for the
      server socket factory.</para>

      <para><emphasis role="bold">Timeout</emphasis> - timeout (in
      milliseconds) for socket connection. If set after create() method
      called, this value will override value set by TIMEOUT key.</para>

      <para><emphasis role="bold">LeasePeriod</emphasis> - the amount of time
      (in milliseconds) that a client should renew its lease. If this value is
      not set, the default of five seconds (see DEFAULT_CLIENT_LEASE_PERIOD),
      will be used. This value will also be what is given to the client when
      it initially querys server for leasing information. If set after
      create() method called, this value will override value set by
      CLIENT_LEASE_PERIOD key.</para>

      <para><emphasis role="bold">MaxNumberOfOnewayThreads</emphasis> - the
      maximum number of thread to be used in the thread pool for one way
      invocations (server side). This property is only used when the default
      oneway thread pool is used. If set after create() method called, this
      value will override value set by MAX_NUM_ONEWAY_THREADS_KEY key.</para>

      <para><emphasis role="bold">OnewayThreadPool</emphasis> - the oneway
      thread pool to use.</para>

      <para></para>

      <bridgehead>org.jboss.remoting.callback.CallbackPoller</bridgehead>

      <para><emphasis role="bold">CALLBACK_POLL_PERIOD</emphasis> (actual
      value is 'callbackPollPeriod') - key for setting the frequency (in
      milliseconds) in which Client's internal callback poller should poll
      server for waiting callbacks. This configuration is only necessary when
      using one of the following Client methods:</para>

      <programlisting>public void addListener(InvokerCallbackHandler callbackhandler, Map metadata, Object callbackHandlerObject) throws Throwable
public void addListener(InvokerCallbackHandler callbackhandler, Map metadata, Object callbackHandlerObject, boolean serverToClient) throws Throwable</programlisting>

      <para>and should be one of the entries in the metadata Map passed. This
      will also only apply when the underlying transport is uni-directional
      (e.g. socket, http, rmi). Bi-directional transports will not need to
      poll. If this property is not set, the default (see
      CallbackPoller.DEFAULT_POLL_PERIOD) value is five seconds. </para>

      <para></para>

      <bridgehead>org.jboss.remoting.callback.CallbackStore </bridgehead>

      <para><emphasis role="bold">FILE_PATH_KEY</emphasis> (actual value is
      'StoreFilePath') - key for setting which directory to write the callback
      objects. The default value is the property value of
      'jboss.server.data.dir' and if this is not set, then will be 'data'.
      Will then append 'remoting' and the callback client's session id. An
      example would be
      'data\remoting\5c4o05l-9jijyx-e5b6xyph-1-e5b6xyph-2'.</para>

      <para><emphasis role="bold">FILE_SUFFIX_KEY</emphasis> (actual value is
      'StoreFileSuffix') - key for setting the file suffix to use for the
      callback objects written to disk. The default value is ‘ser’. </para>

      <para></para>

      <bridgehead>org.jboss.remoting.callback.DefaultCallbackErrorHandler
      </bridgehead>

      <para><emphasis role="bold">CALLBACK_ERRORS_ALLOWED</emphasis> (actual
      value is 'callbackErrorsAllowed') - key for setting the number of
      callback exceptions will be allowed when calling on
      org.jboss.remoting.callback.InvokerCallbackHandler.handleCallback(Callback
      callback) before cleaning up the callback listener. This only applies to
      push callback. The default if this property is not set is five. </para>

      <para></para>

      <bridgehead>org.jboss.remoting.callback.ServerInvokerCallbackHandler</bridgehead>

      <para><emphasis role="bold">CALLBACK_STORE_KEY</emphasis> (actual value
      is 'callbackStore') - key for specifing the callback store to be used.
      The value can be either a JMX ObjectName or a fully qualified class
      name, either way, must implement org.jboss.remoting.SerializableStore.
      If using class name, the callback store implementation must have a void
      constructor. The default is to use the
      org.jboss.remoting.callback.NullCallbackStore.</para>

      <para><emphasis role="bold">CALLBACK_ERROR_HANDLER_KEY</emphasis>
      (actual value is 'callbackErrorHandler') - key for specifing the
      callback exception handler to be used. The value can be either a JMX
      ObjectName or a fully qualified class name, either way, must implement
      org.jboss.remoting.callback.CallbackErrorHandler. If using class name,
      the callback exception handler implementation must have a void
      constructor. The default is to use
      org.jboss.remoting.callback.DefaultCallbackErrorHandler.</para>

      <para><emphasis role="bold">CALLBACK_MEM_CEILING</emphasis> (actual
      value is 'callbackMemCeiling') - key for specifing the percentage of
      free memory available before callbacks will be persisted. If the memory
      heap allocated has reached its maximum value and the percent of free
      memory available is less than the callbackMemCeiling, this will trigger
      persisting of the callback message. The default value is 20. </para>

      <para></para>

      <bridgehead>org.jboss.remoting.detection.jndi.JNDIDetector</bridgehead>

      <para><emphasis role="bold">Bean properties (meaning have
      getter/setter):</emphasis> <emphasis
      role="bold">SubContextName</emphasis> - sub context name under which
      detection messages will be bound and looked up. </para>

      <para></para>

      <bridgehead>org.jboss.remoting.transport.http.HTTPMetadataConstants</bridgehead>

      <para>The following are keys to use to get corresponding values from the
      Map returned from call to
      org.jboss.remoting.InvocationRequest.getRequestPayload() within a
      org.jboss.remoting.ServerInvocationHandler implementation. For
      example:</para>

      <programlisting>   public Object invoke(InvocationRequest invocation) throws Throwable
   {
      Map headers = invocation.getRequestPayload();
</programlisting>

      <para>Where variable ‘headers’ will contain entries for the following
      keys.</para>

      <para><emphasis role="bold">METHODTYPE</emphasis> (actual value is
      ‘MethodType’) – key for getting the method type used by client in http
      request. This will be populated within the Map returned from call to
      org.jboss.remoting.InvocationRequest.getRequestPayload() within a
      org.jboss.remoting.ServerInvocationHandler implementation. For example:
      </para>

      <programlisting>   public Object invoke(InvocationRequest invocation) throws Throwable
   {
      Map headers = invocation.getRequestPayload();
      String methodType = (String) headers.get(HTTPMetadataConstants.METHODTYPE);
      if(methodType != null)
      {
         if(methodType.equals("GET"))
         …
</programlisting>

      <para> <emphasis role="bold">PATH</emphasis> (actual value is ‘Path”) –
      key for getting the path from the url request from the calling client.
      This will be populated within the Map returned from call to
      org.jboss.remoting.InvocationRequest.getRequestPayload() within a
      org.jboss.remoting.ServerInvocationHandler implementation. For example:
      </para>

      <programlisting>   public Object invoke(InvocationRequest invocation) throws Throwable
   {
      Map headers = invocation.getRequestPayload();
      String path = (String) headers.get(HTTPMetadataConstants.PATH);
      …
</programlisting>

      <para> <emphasis role="bold">HTTPVERSION</emphasis> (actual value is
      ‘HttpVersion’) – key for getting the HTTP version from the calling
      client request (e.g. HTTP/1.1). </para>

      <para></para>

      <para></para>

      <para><emphasis role="bold">RESPONSE_CODE</emphasis> (actual value is
      ‘ResponseCode’) – key for getting and setting the HTTP response code.
      Will be used as key to get the response code from metadata Map passed to
      the Client’s invoke() method after the invocation has been made. For
      example:</para>

      <programlisting>Map metadata = new HashMap();
Object response = remotingClient.invoke(myPayloadObject, metadata);
Integer responseCode = (Integer) metadata.get(HTTPMetadataConstants.RESPONSE_CODE);
</programlisting>

      <para>Will be used as key to put the response code in the return payload
      map from invocation handler. For example:</para>

      <programlisting>   public Object invoke(InvocationRequest invocation) throws Throwable
   {
      Map responseHeaders = invocation.getReturnPayload();
      responseHeaders.put(HTTPMetadataConstants.RESPONSE_CODE,  new Integer(202));
</programlisting>

      <para> <emphasis role="bold">RESPONSE_CODE_MESSAGE</emphasis> (actual
      value is 'ResponseCodeMessage') - key for getting and setting the HTTP
      response code message. Will be used as the key to get the response code
      message from metadata Map passed to the Client's invoke() method after
      the invocation has been made. For example:</para>

      <programlisting>Map metadata = new HashMap();
Object response = remotingClient.invoke(myPayloadObject, metadata);
String responseCodeMessage = (String) metadata.get(HTTPMetadataConstants.RESPONSE_CODE_MESSAGE);
</programlisting>

      <para>Will be used as key to put the response code message in the return
      payload map from invocation handler. For example:</para>

      <programlisting>   public Object invoke(InvocationRequest invocation) throws Throwable
   {
      Map responseHeaders = invocation.getReturnPayload();
      responseHeaders.put(HTTPMetadataConstants.RESPONSE_CODE_MESSAGE, "Custom response code and message from remoting server");
</programlisting>

      <para> <emphasis role="bold">NO_THROW_ON_ERROR</emphasis> (actual value
      is 'NoThrowOnError') - key indicating if http client invoker (for
      transports http, https, servlet, and sslservlet) should throw an
      exception if the server response code is equal to or greater than 400.
      Unless set to true, the client invoker will by default throw either the
      exception that originated on the server (if using remoting server) or
      throw a org.jboss.remoting.transport.http.WebServerError, whose message
      will be the error html returned from the web server.</para>

      <para></para>

      <para>For every http client request made from remoting client, a
      remoting version and remoting specific user agent will be set as a
      request property. The request property key for the remoting version will
      be 'JBoss-Remoting-Version' and the value will be set based on return
      from call to Version.getDefaultVersion(). The 'User-Agent' request
      property value will be set to the evaluation of '"JBossRemoting - " +
      Version.VERSION'.</para>

      <para></para>

      <bridgehead>org.jboss.remoting.transport.http.ssl.HTTPSClientInvoker</bridgehead>

      <para><emphasis role="bold">IGNORE_HTTPS_HOST</emphasis> (actual value
      is 'org.jboss.security.ignoreHttpsHost') - key indicating if the http
      client invoker (for transports https and sslservlet) should ignore host
      name verification (meaning will not check for URL's hostname and
      server's identification hostname mismatch during handshaking). By
      default, if this not set to true, standard hostname verification will be
      performed.</para>

      <para><emphasis role="bold">HOSTNAME_VERIFIER</emphasis> (actual value
      is 'hostnameVerifier') - key indicating the hostname verifier that
      should be used by the http client invoker. The value should be the fully
      qualified classname of class that implements
      javax.net.ssl.HostnameVerifier and has a void constructor.</para>

      <para></para>

      <bridgehead>org.jboss.remoting.transport.rmi.RMIServerInvoker</bridgehead>

      <para><emphasis role="bold">REGISTRY_PORT_KEY</emphasis> (actual value
      is 'registryPort') - the port on which to create the RMI registry. The
      default is 3455. This also needs to have the isParam attribute set to
      true. </para>

      <para></para>

      <bridgehead>org.jboss.remoting.transport.socket.MicroSocketClientInvoker
      </bridgehead>

      <para><emphasis role="bold">TCP_NODELAY_FLAG</emphasis> (actual value is
      'enableTcpNoDelay') - can be either true or false and will indicate if
      client socket should have TCP_NODELAY turned on or off. TCP_NODELAY is
      for a specific purpose; to disable the Nagle buffering algorithm. It
      should only be set for applications that send frequent small bursts of
      information without getting an immediate response; where timely delivery
      of data is required (the canonical example is mouse movements). The
      default is false.</para>

      <para><emphasis role="bold">MAX_POOL_SIZE_FLAG</emphasis> (actual value
      is 'clientMaxPoolSize') - the client side maximum number of threads. The
      default is 50.</para>

      <para><emphasis role="bold">CLIENT_SOCKET_CLASS_FLAG</emphasis> (actual
      value is 'clientSocketClass') - specifies the fully qualified class name
      for the custom SocketWrapper implementation to use on the client. Note,
      will need to make sure this is marked as a client parameter (using the
      'isParam' attribute). Making this change will not affect the
      marshaller/unmarshaller that is used, which may also be a requirement.
      </para>

      <para></para>

      <bridgehead>org.jboss.remoting.transport.socket.SocketServerInvoker
      </bridgehead>

      <para><emphasis role="bold">CHECK_CONNECTION_KEY</emphasis> (actual
      value is 'socket.check_connection') - key for indicating if socket
      invoker should continue to keep socket connection between client and
      server open after invocations by sending a ping on the connection before
      being re-used. The default for this is false.</para>

      <para><emphasis role="bold">SERVER_SOCKET_CLASS_FLAG</emphasis> (actual
      value is 'serverSocketClass') - specifies the fully qualified class name
      for the custom SocketWrapper implementation to use on the server.
      </para>
    </section>
  </chapter>

  <chapter>
    <title>Sending streams</title>

    <para>Remoting supports the sending of InputStreams. It is important to
    note that this feature DOES NOT copy the stream data directly from the
    client to the server, but is a true on demand stream. Although this is
    obviously slower than reading from a stream on the server that has been
    copied locally, it does allow for true streaming on the server. It also
    allows for better memory control by the user (versus the framework trying
    to copy a 3 Gig file into memory and getting out of memory errors).</para>

    <para>Use of this new feature is simple. From the client side, there is a
    method in org.jboss.remoting.Client with the signature:</para>

    <programlisting>public Object invoke(InputStream inputStream, Object param) throws Throwable
      </programlisting>

    <para>So from the client side, would just call invoke as done in the past,
    and pass the InputStream and the payload as the parameters. An example of
    the code from the client side would be (this is taken directly from
    org.jboss.test.remoting.stream.StreamingTestClient):</para>

    <programlisting>
         String param = "foobar";
         File testFile = new File(fileURL.getFile());
         ...
         Object ret = remotingClient.invoke(fileInput, param);
    </programlisting>

    <para>From the server side, will need to implement
    <code>org.jboss.remoting.stream.StreamInvocationHandler</code> instead of
    <code>org.jboss.remoting.ServerInvocationHandler</code> .
    StreamInvocationHandler extends ServerInvocationHandler, with the addition
    of one new method:</para>

    <programlisting>public Object handleStream(InputStream stream, Object param)</programlisting>

    <para>The stream passed to this method can be called on just as any
    regular local stream. Under the covers, the InputStream passed is really
    proxy to the real input stream that exists in the client's VM. Subsequent
    calls to the passed stream will actually be converted to calls on the real
    stream on the client via this proxy. If the client makes an invocation on
    the server passing an InputStream as the parameter and the server handler
    does not implement StreamInvocationhandler, an exception will be thrown to
    the client caller.</para>

    <para>It is VERY IMPORTANT that the StreamInvocationHandler implementation
    close the InputStream when it finished reading, as will close the real
    stream that lives within the client VM.</para>

    <section>
      <title>Configuration</title>

      <para>By default, the stream server which runs within the client JVM
      uses the following values for its locator uri:</para>

      <para>transport - socket</para>

      <para>host - tries to first get local host name and if that fails, the
      local ip (if that fails, localhost).</para>

      <para>port - 5405</para>

      <para>Currently, the only way to override these settings is to set the
      following system properties (either via JVM arguments or via
      <code>System.setProperty()</code> method):</para>

      <para>remoting.stream.transport - sets the transport type (rmi, http,
      socket, etc.)</para>

      <para>remoting.stream.host - host name or ip address to use</para>

      <para>remoting.stream.port - the port to listen on</para>

      <para>These properties are important because currently the only way for
      a target server to get the stream data from the stream server (running
      within the client JVM) is to have the server invoker make the invocation
      on a new connection back to the client (see issues below).</para>
    </section>

    <section>
      <title>Issues</title>

      <para>This is a first pass at the implementation and needs some work in
      regards to optimizations and configuration. In particular, there is a
      remoting server that is started to service requests from the stream
      proxy on the target server for data from the original stream. This
      raises an issue with the current transports, since the client will have
      to accept calls for the original stream on a different socket. This may
      be difficult when control over the client's environment (including
      firewalls) may not be available. A bi-directional transport, called
      multiplex, is being introduced as of 1.4.0 release which will allow
      calls from the server to go over the same socket connection established
      by the client to the server (JBREM-91). This will make communications
      back to client much simpler from this standpoint.</para>
    </section>
  </chapter>

  <chapter>
    <title>Serialization</title>

    <para> Serialization – how it works within remoting In general, remoting
    will rely on a factory to provide the serialization implementation, or
    <code>org.jboss.remoting.serialization.SerializationManager</code>, to be
    used when doing object serialization. This factory is
    <code>org.jboss.remoting.serialization.SerializationStreamFactory</code>
    and is a (as defined by its javadoc):</para>

    <literallayout>“factory is for defining the Object stream implemenations to be used along with creating those implemenations for use.  
The main function will be to return instance of ObjectOutput and ObjectInput.  By default, the implementations will be 
java.io.ObjectOutputStream and java.io.ObjectInputStream.”
</literallayout>

    <para>Currently there are only two different types of serialization
    implementations; ‘java’ and ‘jboss’. The ‘java’ type uses
    <code>org.jboss.remoting.serialization.impl.java.JavaSerializationManager</code>
    as the SerializationManager implementation and is backed by standard Java
    serialization provide by the JVM, which is the default. The ‘jboss’ type
    uses
    <code>org.jboss.remoting.serialization.impl.jboss.JBossSerializationManager</code>
    as the SerializationManger implementation and is backed by JBoss
    Serialization. </para>

    <para>JBoss Serialization is a new project under development to provide a
    more performant implementation of object serialization. It complies with
    java serialization standard with three exceptions:</para>

    <para>- SerialUID not needed</para>

    <para>- java.io.Serializable is not required</para>

    <para>- different protocol</para>

    <para>JBoss Serialization requires JDK 1.5</para>

    <para></para>

    <para>It is possible to override the default SerializationManger
    implementation to be used by setting the system property ‘SERIALIZATION’
    to the fully qualified name of the class to use (which will need to
    provide a void contructor). </para>
  </chapter>

  <chapter>
    <title>Connection Exception Listeners</title>

    <bridgehead>Client side</bridgehead>

    <para>It is possible to register a listener with the remoting client to
    receive callbacks when a connection failure to a remoting server is
    detected, even when the client is idle.</para>

    <para>The only requirement is to implement the
    <code>org.jboss.remoting.ConnectionListener</code> interface, which has
    only one method:</para>

    <programlisting>public void handleConnectionException(Throwable throwable, Client client)</programlisting>

    <para>Then call the <code>addConnectionListener(ConnectionListener
    listener)</code> method on the Client class and pass your listener
    instance. Can also call <code>addConnectionListener(ConnectionListener
    listener, int pingPeriod)</code> if want to specify how frequently wish to
    ping server.</para>

    <para>Currently, the Client will use the
    <code>org.jboss.remoting.ConnectionValidator</code> class to handle the
    detection of connection failures. This is done by pinging the server
    periodically (defaults to every 2 seconds). If there is a failure during
    this ping, the exception and the Client will be passed to the
    listener.</para>

    <bridgehead>Server side</bridgehead>

    <para>A remoting server also has the capability to detect when a client is
    no longer available. This is done by estabilishing a lease with the
    remoting clients that connect to a server.</para>

    <para>To turn on server side connection failure detection of remoting
    clients, will need to satisfy two criteria. The first is that the client
    lease period is set and is a value greater than 0. The value is
    represented in milliseconds. The client lease period can be set by either
    the 'clientLeasePeriod' attribute within the Connector configuration or by
    calling the:<programlisting>public void setLeasePeriod(long leasePeriodValue)</programlisting>method
    within Connector. The second criterion is that an implementation of the
    <code>org.jboss.remoting.ConnectionListener</code> interface is added as a
    connection listener to the Connector, via the method:<programlisting>public void addConnectionListener(ConnectionListener listener)</programlisting>Note,
    there is no way to set the connection listener via xml based configuration
    for the Connector. Once both criteria are met, the remoting server will
    turn on client leasing.</para>

    <para>The ConnectionListener will be notified of both client failures and
    client disconnects via the handleConnectionException() method. If the
    client failed, meaning its lease was not renewed within configured time
    period, the first parameter to the handleConnectionException() method will
    be null. If the client disconnected in a regular manner, the first
    parameter to the handleConnectionException() method will be of type
    ClientDisconnectedException (which indicates a normal termination). Note,
    the client's lease will be renewed on the server with any and every
    invocation made on the server from the client, whether it be a normal
    invocation or a ping from the client internally.</para>

    <para>One the client side, there is no API or configuration changes
    needed. When the client initially connects to the server, it will check to
    see if client leasing is turned on by the server. If it is, it will
    internally start pinging periodically to the server to maintain the lease.
    When the client disconnects, it will internally send message to the server
    to stop monitoring lease for this client. Therefore, it is <emphasis
    role="bold">IMPORTANT</emphasis> that disconnect is called on the client
    when done using it. Otherwise, the client will continue to make its ping
    call on the server to keep its lease current.</para>

    <para>The client can also provide extra metadata the will be communicated
    to the connection listener in case of failure by supplying a metadata Map
    to the Client constructor. This map will be included in the Client
    instance passed to the connection listener (via the
    handleConnectionException() method) via the Client's getConfiguration()
    method.</para>

    <para>For examples of how to use server side connection listeners,
    reference org.jboss.test.remoting.lease.LeaseTestServer and
    org.jboss.test.remoting.lease.LeaseTestClient.</para>
  </chapter>

  <chapter>
    <title>Transporters - beaming POJOs</title>

    <para>There are many ways in which to expose a remote interface to a java
    object. Some require a complex framework API based on a standard
    specification and some require new technologies like annotations and AOP.
    Each of these have their own benefits. JBoss Remoting transporters provide
    the same behavior via a simple API without the need for any of the newer
    technologies.</para>

    <para>When boiled down, transporters take a plain old java object (POJO)
    and expose a remote proxy to it via JBoss Remoting. Dynamic proxies and
    reflection are used to make the typed method calls on that target POJO.
    Since JBoss Remoting is used, can select from a number of different
    network transports (i.e. rmi, http, socket, multiplex, etc.), including
    support for SSL. Even clustering features can be included. See the
    transporter samples in the next chapter for detailed examples of how to
    set up use of a transporter.</para>
  </chapter>

  <chapter>
    <title>How to use it - sample code</title>

    <para>Sample code demonstrating different remoting features can be found
    in the examples directory. They can be compiled and run manually via your
    IDE or via an ant build file found in the examples directory. There are
    many sets of sample code, each with their own package. Within most of
    these packages, there will be a server and a client class that will need
    to be executed</para>

    <section>
      <title>Simple invocation</title>

      <para>The simple invocation sample (found in the
      org.jboss.remoting.samples.simple package), has two classes;
      SimpleClient and SimpleServer. It demonstrates making a simple
      invocation from a remoting client to a remoting server. The SimpleClient
      class will create an InvokerLocator object from a simple url-like string
      that identifies the remoting server to call upon (which will be
      socket://localhost:5400 by default). Then the SimpleClient will create a
      remoting Client class, passing the newly created InvokerLocator. Next
      the Client will be called to make an invocation on the remoting server,
      passing the request payload object (which is a String with the value of
      "Do something"). The server will return a response from this call which
      is printed to standard output.</para>

      <para>Within the SimpleServer, a remoting server is created and started.
      This is done by first creating an InvokerLocator, just like was done in
      the SimpleClient. Then constructing a Connector, passing the
      InvokerLocator. Next, need to call create() on the Connector to
      initialize all the resources, such as the remoting server invoker. Once
      created, need to create the invocation handler. The invocation handler
      is the class that the remoting server will pass client requests on to.
      The invocation handler in this sample simply returns the simple String
      "This is the return to SampleInvocationHandler invocation". Once
      created, the handler is added to the Connector. Finally, the Connector
      is started and will start listening for incoming client requests.</para>

      <para>To run this example, can compile both the SimpleClient and
      SimpleServer class, then first run the SimpleServer and then the
      SimpleClient. Or can go to the examples directory and run the ant target
      'run-simple-server' and then in another console window run the ant
      target 'run-simple-client'. For example:</para>

      <para><programlisting>ant run-simple-server</programlisting>ant
      then:</para>

      <para><programlisting>ant run-simple-client</programlisting>The output
      when running the SimpleClient should look like:</para>

      <programlisting>Calling remoting server with locator uri of: socket://localhost:5400
Invoking server with request of 'Do something'
Invocation response: This is the return to SampleInvocationHandler invocation</programlisting>

      <para>The output when running the SimpleServer should look like:</para>

      <programlisting>Starting remoting server with locator uri of: socket://localhost:5400
Invocation request is: Do something
Returning response of: This is the return to SampleInvocationHandler invocation</programlisting>

      <para>Note: will have to manually shut down the SimpleServer once
      started.</para>
    </section>

    <section>
      <title>HTTP invocation</title>

      <para>This http invocation sample (found in the
      org.jboss.remoting.samples.http package), demonstrates how the http
      invoker can be used for a variety of http based invocations. This time,
      will start with the server side. The SimpleServer class is much like the
      one from the previous simple invocation example, except that instead of
      using the 'socket' transport, will be using the 'http' transport. Also,
      instead of using the SampleInvocationHandler class as the handler, will
      be using the WebInvocationHandler (code shown below).</para>

      <programlisting>public class <emphasis role="bold">WebInvocationHandler</emphasis> implements <emphasis
          role="bold">ServerInvocationHandler</emphasis>
{
   // Pre-defined returns to be sent back to client based on type of request.
   public static final String RESPONSE_VALUE = "This is the return to simple text based http invocation.";
   public static final ComplexObject OBJECT_RESPONSE_VALUE = new ComplexObject(5, "dub", false);
   public static final String HTML_PAGE_RESPONSE = "&lt;html&gt;&lt;head&gt;&lt;title&gt;Test HTML page&lt;/title&gt;&lt;/head&gt;&lt;body&gt;" +
                                                   "&lt;h1&gt;HTTP/Servlet Test HTML page&lt;/h1&gt;&lt;p&gt;This is a simple page served for test." +
                                                   "&lt;p&gt;Should show up in browser or via invoker client&lt;/body&gt;&lt;/html&gt;";

   // Different request types that client may make
   public static final String NULL_RETURN_PARAM = "return_null";
   public static final String OBJECT_RETURN_PARAM = "return_object";
   public static final String STRING_RETURN_PARAM = "return_string";


   /**
    * called to handle a specific invocation
    *
    * @param invocation
    * @return
    * @throws Throwable
    */
   <emphasis role="bold">public Object invoke(InvocationRequest invocation) throws Throwable
   {
      // Print out the invocation request
      System.out.println("Invocation request from client is: " + invocation.getParameter());
      if(NULL_RETURN_PARAM.equals(invocation.getParameter()))
      {
         return null;
      }
      else if(invocation.getParameter() instanceof ComplexObject)
      {
            return OBJECT_RESPONSE_VALUE;
      }
      else if(STRING_RETURN_PARAM.equals(invocation.getParameter()))
      {
         Map responseMetadata = invocation.getReturnPayload();
         responseMetadata.put(HTTPMetadataConstants.RESPONSE_CODE,  new Integer(207));
         responseMetadata.put(HTTPMetadataConstants.RESPONSE_CODE_MESSAGE, "Custom response code and message from remoting server");
         // Just going to return static string as this is just simple example code.
         return RESPONSE_VALUE;
      }
      else
      {
         return HTML_PAGE_RESPONSE;
      }</emphasis>
   }
</programlisting>

      <para>The most interesting part of the WebInvocationHandler is its
      invoke() method implementation. First it will check to see what the
      request parameter was from the InvocationRequest and based on what the
      value is, will return different responses. The first check is to see if
      the client passed a request to return a null value. The second will
      check to see if the request parameter from the client was of type
      ComplexObject. If so, return the pre-built ComplexObject that was
      created as a static variable.</para>

      <para>After that, will check to see if the request parameter was for
      returning a simple String. Notice in this block, will set the desired
      response code and message to be returned to the client. In this case,
      are setting the response code to be returned to 207 and the response
      message to "Custom response code and message from remoting server".
      These are non-standard code and message, but can be anything
      desired.</para>

      <para>Last, if have not found a matching invocation request parameter,
      will just return some simple html.</para>

      <para>Now onto the client side for making the calls to this handler,
      which can be found in SimpleClient (code shown below).</para>

      <programlisting>public class <emphasis role="bold">SimpleClient</emphasis>
{
   // Default locator values
   private static String transport = "<emphasis role="bold">http</emphasis>";
   private static String host = "localhost";
   private static int port = 5400;

   public void makeInvocation(String locatorURI) throws Throwable
   {
      // create InvokerLocator with the url type string
      // indicating the target remoting server to call upon.
      InvokerLocator locator = new InvokerLocator(locatorURI);
      System.out.println("Calling remoting server with locator uri of: " + locatorURI);

      Client remotingClient = new Client(locator);

      // make invocation on remoting server and send complex data object
      // by default, the remoting http client invoker will use method type of POST,
      // which is needed when ever sending objects to the server.  So no metadata map needs
      // to be passed to the invoke() method.
      <emphasis role="bold">Object response = remotingClient.invoke(new ComplexObject(2, "foo", true), null);</emphasis>

      System.out.println("\nResponse from remoting http server when making http POST request and sending a complex data object:\n" + response);


      <emphasis role="bold">Map metadata = new HashMap();</emphasis>
      // set the metadata so remoting client knows to use http GET method type
      <emphasis role="bold">metadata.put("TYPE", "GET");</emphasis>
      // not actually sending any data to the remoting server, just want to get its response
      <emphasis role="bold">response = remotingClient.invoke((Object) null, metadata);</emphasis>

      System.out.println("\nResponse from remoting http server when making GET request:\n" + response);

      // now set type back to POST and send a plain text based request
      <emphasis role="bold">metadata.put("TYPE", "POST");</emphasis>
      <emphasis role="bold">response = remotingClient.invoke(WebInvocationHandler.STRING_RETURN_PARAM, metadata);</emphasis>

      System.out.println("\nResponse from remoting http server when making http POST request and sending a text based request:\n" + response);

      // notice are getting custom response code and message set by web invocation handler
      <emphasis role="bold">Integer responseCode = (Integer) metadata.get(HTTPMetadataConstants.RESPONSE_CODE);
      String responseMessage = (String) metadata.get(HTTPMetadataConstants.RESPONSE_CODE_MESSAGE);</emphasis>
      System.out.println("Response code from server: " + responseCode);
      System.out.println("Response message from server: " + responseMessage);

   }
</programlisting>

      <para>This SimpleClient, like the one before in the simple invocation
      example, starts off by creating an InvokerLocator and remoting Client
      instance, except is using http transport instead of socket. The first
      invocation made is to send a newly constructed ComplexObject. If
      remember from the WebInvocationHandler above, will expect this
      invocation to return a different ComplexObject, which can be seen in the
      following system output line.</para>

      <para>The next invocation to be made is a simple http GET request. To do
      this, must first let the remoting client know that the method type needs
      to be changed from the default, which is POST, to be GET. Then make the
      invocation with a null payload (since not wanting to send any data, just
      get data in response) and the metadata map just populated with the GET
      type. This invocation request will return a response of html.</para>

      <para>Then, will change back to being a POST type request and will pass
      a simple String as the payload to the invocation request. This will
      return a simple String as the response from the WebInvocationHandler.
      Afterward, will see the specific response code and message printed to
      standard output, as well as the exception itself.</para>

      <para>To run this example, can compile all the classes in the package,
      then first run the SimpleServer and then the SimpleClient. Or can go to
      the examples directory and run the ant target 'run-http-server' and then
      in another console window run the ant target 'run-http-client'. For
      example:</para>

      <programlisting>ant run-http-server</programlisting>

      <para>and then:</para>

      <programlisting>ant run-http-client</programlisting>

      <para>The output when running the SimpleClient should look like:</para>

      <programlisting>Response from remoting http server when making http POST request and sending a complex data object:
ComplexObject (i = 5, s = dub, b = false, bytes.length = 0)

Response from remoting http server when making GET request:
&lt;html&gt;&lt;head&gt;&lt;title&gt;Test HTML page&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;h1&gt;HTTP/Servlet Test HTML page&lt;/h1&gt;&lt;p&gt;This is a simple page served for test.&lt;p&gt;Should show up in browser or via invoker client&lt;/body&gt;&lt;/html&gt;

Response from remoting http server when making http POST request and sending a text based request:
This is the return to simple text based http invocation.
Response code from server: 207
Response message from server: Custom response code and message from remoting server</programlisting>

      <para>Notice that the first response is the ComplexObject from the
      static variable returned within WebInvocationHandler. The next response
      is html and then simple text from the WebInvocationHandler. Can see the
      specific response code and message set in the
      WebInvocationHandler.</para>

      <para>The output from the SimpleServer should look like:</para>

      <programlisting>Starting remoting server with locator uri of: http://localhost:5400
Jan 26, 2006 11:39:53 PM org.apache.coyote.http11.Http11BaseProtocol init
INFO: Initializing Coyote HTTP/1.1 on http-127.0.0.1-5400
Jan 26, 2006 11:39:53 PM org.apache.coyote.http11.Http11BaseProtocol start
INFO: Starting Coyote HTTP/1.1 on http-127.0.0.1-5400
Invocation request from client is: ComplexObject (i = 2, s = foo, b = true, bytes.length = 0)
Invocation request from client is: null
Invocation request from client is: return_string</programlisting>

      <para>First the information for the http server invoker is written,
      which includes the locator uri used to start the server and the output
      from starting the Tomcat connector. Then will see the invocation
      parameter passed for each client request.</para>

      <para>Since the SimpleServer should still be running, can open a web
      browser and enter the locator uri, http://localhost:5400. This should
      cause the browser to render the html returned from the
      WebInvocationHandler.</para>
    </section>

    <section>
      <title>Oneway invocation</title>

      <para>The oneway invocation sample (found in the
      org.jboss.remoting.samples.oneway package) is very similar to the simple
      invocation example, except in this sample, the client will make
      asynchronous invocations on the server.</para>

      <para>The OnewayClient class sets up the remoting client as in the
      simple invocation sample, but instead of using the invoke() method, it
      uses the invokeOneway() method on the Client class. There are two basic
      modes when making a oneway invocation in remoting. The first is to have
      the calling thread to be the one that makes the actual call to the
      server. This allows the caller to ensure that the invocation request at
      least made it to the server. Once the server receives the invocation
      request, the call will return (and the request will be processed by a
      separate worker thread on the server). The other mode, which is
      demonstrated in the second call to invokeOneway, allows for the calling
      thread to return immediately and a worker thread on the client side will
      make the actual invocation on the server. This is faster of the two
      modes, but if there is a problem making the request on the server, the
      original caller will be unaware.</para>

      <para>The OnewayServer is exactly the same as the SimpleServer from the
      previous example, with the exception that invocation handler returns
      null (since even if did return a response, would not be delivered to the
      original caller).</para>

      <para>To run this example, can compile both the OnewayClient and
      OnewayServer class, then run the OnewayServer and then the OnewayClient.
      Or can go to the examples directory and run the ant target
      'run-oneway-server' and then in another console window run the ant
      target 'run-oneway-client'. For example:</para>

      <programlisting>ant run-oneway-server</programlisting>

      <para>and then:</para>

      <programlisting>ant run-oneway-client</programlisting>

      <para>The output when running the OnewayClient should look like:</para>

      <programlisting>Calling remoting server with locator uri of: socket://localhost:5400
Making oneway invocation with payload of 'Oneway call 1.'
Making oneway invocation with payload of 'Oneway call 2.'</programlisting>

      <para>The output when running the OnewayServer should look like:</para>

      <programlisting>Starting remoting server with locator uri of: socket://localhost:5400
Invocation request is: Oneway call 1.
Invocation request is: Oneway call 2.</programlisting>

      <para>Note: will have to manually shut down the OnewayServer once
      started.</para>

      <para>Although this example only demonstrates making one way
      invocations, could include this with callbacks (see further down) to
      have asynchronous invocations with callbacks to verify was
      processed.</para>
    </section>

    <section>
      <title>Discovery and invocation</title>

      <para>The discovery sample (found in the
      org.jboss.remoting.samples.detection package) is similar to the simple
      invocation example in that it makes a simple invocation from the client
      to the server. However, in this example, instead of explicitly
      specifying the invoker locator to use for the target remoting server, it
      is discovered dynamically during runtime. This example is composed of
      two classes; SimpleDetectorClient and SimpleDetectorServer.</para>

      <para>The SimpleDetectorClient starts off by setting up the remoting
      detector. Detection on the client side requires a few components; a JMX
      MBeanServer, one or more Detectors, and a NetworkRegistry. The Detectors
      will listen for detection messages from remoting servers and then add
      the information for the detected servers to the NetworkRegistry. They
      use JMX to lookup and call on the NetworkRegistry. The NetworkRegistry
      uses JMX Notifications to emit changes in network topology (remoting
      servers being added or removed).</para>

      <para>In this particular example, the SimpleDetectorClient is registered
      with the NetworkRegistry as a notification listener. When it receives
      notifications from the NetworkRegistry (via the handleNotification()
      method), it will check to see if the notification is for adding or
      removing a remoting server. If it is for adding a remoting server, the
      SimpleDetectorClient will get the array of InvokerLocators from the
      NetworkNotification and make a remote call for each. If the notification
      is for removing a remoting server, the SimpleDetectorClient will simply
      print out a message saying which server has been removed.</para>

      <para>The biggest change between the SimpleDetectorServer and the
      SimpleServer from the first sample is that have added a method,
      setupDetector(), to create and start a remoting Detector. On the server
      side, only two components are needed for detection; the Detector and a
      JMX MBeanServer. As for the setup of the Connector, it is exactly the
      same as before. Notice that even though we have added a Detector on the
      server side, the Connector is not directly aware of either Detector or
      the MBeanServer, so no code changes for the Connector setup is
      required.</para>

      <para>To run this example, can compile both the SimpleDetectorClient and
      SimpleDetectorServer class, then run the SimpleDetectorServer and then
      the SimpleDetectorClient. Or can go to the examples directory and run
      the ant target 'run-detector-server' and then in another window run the
      ant target 'run-detector-client'. For example:</para>

      <programlisting>ant run-detector-server</programlisting>

      <para>and then:</para>

      <programlisting>ant run-detector-client</programlisting>

      <para>The initial output when running the SimpleDetectorClient should
      look like:</para>

      <programlisting>ri Jan 13 09:36:50 EST 2006: [CLIENT]: Starting JBoss/Remoting client... to stop this client, kill it manually via Control-C
Fri Jan 13 09:36:50 EST 2006: [CLIENT]: NetworkRegistry has been created
Fri Jan 13 09:36:50 EST 2006: [CLIENT]: NetworkRegistry has added the client as a listener
Fri Jan 13 09:36:50 EST 2006: [CLIENT]: MulticastDetector has been created and is listening for new NetworkRegistries to come online
Fri Jan 13 09:36:50 EST 2006: [CLIENT]: GOT A NETWORK-REGISTRY NOTIFICATION: jboss.network.server.added
Fri Jan 13 09:36:50 EST 2006: [CLIENT]: New server(s) have been detected - getting locators and sending welcome messages
Fri Jan 13 09:36:50 EST 2006: [CLIENT]: Sending welcome message to remoting server with locator uri of: socket://127.0.0.1:5400/
Fri Jan 13 09:36:50 EST 2006: [CLIENT]: The newly discovered server sent this response to our welcome message: Received your welcome message.  Thank you!</programlisting>

      <para>The output when running the SimpleDetectorServer should look
      like:</para>

      <programlisting>Fri Jan 13 09:36:46 EST 2006: [SERVER]: Starting JBoss/Remoting server... to stop this server, kill it manually via Control-C
Fri Jan 13 09:36:46 EST 2006: [SERVER]: This server's endpoint will be: socket://localhost:5400
Fri Jan 13 09:36:46 EST 2006: [SERVER]: MulticastDetector has been created and is listening for new NetworkRegistries to come online
Fri Jan 13 09:36:46 EST 2006: [SERVER]: Starting remoting server with locator uri of: socket://localhost:5400
Fri Jan 13 09:36:46 EST 2006: [SERVER]: Added our invocation handler; we are now ready to begin accepting messages from clients
Fri Jan 13 09:36:50 EST 2006: [SERVER]: RECEIVED A CLIENT MESSAGE: Welcome Aboard!
Fri Jan 13 09:36:50 EST 2006: [SERVER]: Returning the following message back to the client: Received your welcome message.  Thank you!</programlisting>

      <para>At this point, try stopping the SimpleDetectorServer (notice that
      the SimpleDetectorClient should still be running). After a few seconds,
      the client detector should detect that the server is no longer available
      and will see something like the following appended in the
      SimpleDetectorClient console window:</para>

      <programlisting>Fri Jan 13 09:37:04 EST 2006: [CLIENT]: GOT A NETWORK-REGISTRY NOTIFICATION: jboss.network.server.removed
Fri Jan 13 09:37:04 EST 2006: [CLIENT]: It has been detected that a server has gone down with a locator of: InvokerLocator [socket://127.0.0.1:5400/]</programlisting>
    </section>

    <section>
      <title>Callbacks</title>

      <para>The callback sample (found in the
      org.jboss.remoting.samples.callback package) illustrates how to perform
      callbacks from a remoting server to a remoting client. This example is
      composed of two classes; CallbackClient and CallbackServer.</para>

      <para>Within remoting, there are two approaches in which a callback can
      be received. The first is to actively ask for callback messages from the
      remoting server, which is called a pull callback (since are pulling the
      callbacks from the server). The second is to have the server send the
      callbacks to the client as they are generated, which is called a push
      callback. This sample demonstrates how to do both pull and push
      callbacks.</para>

      <para>Looking at the CallbackClient class, will see that the first thing
      done is to create a remoting Client, which is done in the same manner as
      previous examples. Next, we'll perform a pull callback, which requires
      the creation of a CallbackHandler. The CallbackHandler, which implements
      the InvokerCallbackHandler interface, is what is called upon with a
      Callback object when a callback is received. The Callback object
      contains information such as the callback message (in Object form), the
      server locator from where the callback originally came from, and a
      handle object which can help to identify callback context (similar to
      the handle object within a JMX Notification). Once created, the
      CallbackHandler is then registered as a listener within the Client. This
      will cause the client to make a call to the server to notify the server
      it has a callback listener (more on this below in the server section).
      Although the CallbackHandler is not called upon directly when doing pull
      callbacks, it is needed as an identifier for the callbacks.</para>

      <para>Then the client will wait a few seconds, make a simple invocation
      on the server, and then call on the remoting Client instance to get any
      callbacks that may be available for our CallbackHandler. This will
      return a list of callbacks, if any exist. The list will be iterated and
      each callback will be printed to standard output. Finally, the callback
      handler will be removed as a listener from the remoting Client (which in
      turns removes it from the remoting server).</para>

      <para>After performing a pull callback, will perform a push callback.
      This is a little more involved as requires creating a callback server to
      which the remoting target server can callback on when it generates a
      callback message. To do this, will need to create a remoting Connector,
      just as have seen in previous examples. For this particular example, we
      use the same locator url as our target remoting server, but increment
      the port to listen on by one. Will also notice that use the
      SampleInvocationHandler hander from the CallbackServer (more in this in
      a minute). After creating our callback server, a CallbackHandler and
      callback handle object is created. Next, remoting Client is called to
      add our callback listener. Here we pass not only the CallbackHandler,
      but the InvokerLocator for the callback server (so the target server
      will know where to deliver callback messages to), and the callback
      handle object (which will be included in all the callback messages
      delivered for this particular callback listener).</para>

      <para>Then the client will wait a few seconds, to allow the target
      server time to generate and deliver callback messages. After that, we
      remove the callback listener and clean up our callback server.</para>

      <para>The CallbackServer is pretty much the same as the previous samples
      in setting up the remoting server, via the Connector. The biggest change
      resides in the ServerInvocationHandler implementation,
      SampleInvocationHandler (which is an inner class to CallbackServer). The
      first thing to notice is now have a variable called listeners, which is
      a List to hold any callback listeners that get registered. Also, in the
      constructor of the SampleInvocationHandler, we set up a new thread to
      run in the background. This thread, executing the run() method in
      SampleInvocationHandler, will continually loop looking to see if the
      shouldGenerateCallbacks has been set. If it has been, will create a
      Callback object and loop through its list of listeners and tell each
      listener to handle the newly created callback. Have also added
      implementation to the addListener() and removeListener() methods where
      will either add or remove specified callback listener from the internal
      callback listener list and set the shouldGenerateCallbacks flag
      accordingly. The invoke() method remains the same as in previous
      samples.</para>

      <para>To run this example, can compile both the CallbackClient and
      CallbackServer class, then run the CallbackServer and then the
      CallbackClient. Or can go to the examples directory and run the ant
      target 'run-callback-server' and then in another window run the ant
      target 'run-callback-client. For example:</para>

      <programlisting>ant run-callback-server</programlisting>

      <para>and then:</para>

      <programlisting>ant run-callback-client</programlisting>

      <para>The output in the CallbackClient console window should look
      like:</para>

      <programlisting>Calling remoting server with locator uri of: socket://localhost:5400
Invocation response: This is the return to SampleInvocationHandler invocation
Pull Callback value = Callback 1: This is the payload of callback invocation.
Pull Callback value = Callback 2: This is the payload of callback invocation.
Starting remoting server with locator uri of: InvokerLocator [socket://127.0.0.1:5401/]
Received push callback.
Received callback value of: Callback 3: This is the payload of callback invocation.
Received callback handle object of: myCallbackHandleObject
Received callback server invoker of: InvokerLocator [socket://127.0.0.1:5400/]
Received push callback.
Received callback value of: Callback 4: This is the payload of callback invocation.
Received callback handle object of: myCallbackHandleObject
Received callback server invoker of: InvokerLocator [socket://127.0.0.1:5400/]</programlisting>

      <para>This output shows that client first pulled two callbacks generated
      from the server. Then, after creating and registering our second
      callback handler and a callback server, two callbacks were received from
      the target server.</para>

      <para>The output in the CallbackServer console window should look
      like:</para>

      <programlisting>Starting remoting server with locator uri of: socket://localhost:5400
Adding callback listener.
Invocation request is: Do something
Removing callback listener.
Adding callback listener.
Removing callback listener. </programlisting>

      <para>This output shows two distinct callback handlers being added and
      removed (with an invocation request being received after the first was
      added).</para>

      <para>There are a few important points to mention about this example.
      First, notice that in the client, the same callback handle object in the
      push callbacks was received as was registered with the callback
      listener. However, there was no special code required to facilitate this
      within the SampleInvocationHandler. This is handled within remoting
      automatically. Also notice when the callback server was created within
      the client, no special coding was required to register the callback
      handler with it, both were simply passed to the remoting Client instance
      when registering the callback listener and was handled
      internally.</para>
    </section>

    <section>
      <title>Streaming</title>

      <para>The streaning sample (found in the
      org.jboss.remoting.samples.stream package) illustrates how a
      java.io.InputStream can be sent from a client and read on demand from a
      server. This example is composed of two classes: StreamingClient and
      StreamingServer.</para>

      <para>Unlike the previous examples that sent plain old java objects as
      the payload, this example will be sending a java.io.FileInputStream as
      the payload to the server. This is a special case because streams can
      not be serialized. One approach to this might be to write out the
      contents of a stream to a byte buffer and send the whole data content to
      the server. However, this approach can be dangerous because if the data
      content of the stream is large, such as an 800MB file, would run the
      risk of causing an out of memory error (since are loading all 800MB into
      memory). Another approach, which is used by JBossRemoting, is to create
      a proxy to the original stream. This proxy can then be called upon for
      reading, same as the original stream. When this happens, the proxy will
      call back the original stream for the requested data.</para>

      <para>Looking at the StreamingClient, the remoting Client is created as
      in previous samples. Next, will create a java.io.FileInputStream to the
      sample.txt file on disk (which is in the same directory as the test
      classes). Finally, will call the remoting Client to do its invocation,
      passing the new FileInputStream and the name of the file. The second
      parameter could be of any Object type and is meant to supply some
      meaningful context to the server in regards to the stream being passed,
      such as the file name to use when writing to disk on the server side.
      The response from the server, in this example, is the size of the file
      it wrote to disk.</para>

      <para>The StreamingServer sets up the remoting server as was done in
      previous examples. However, instead of using an implementation of the
      ServerInvocationHandler class as the server handler, an implementation
      of the StreamInvocationHandler (which extends the
      ServerInvocationHandler) is used. The StreamInvocationHandler includes
      an extra method called handleStream() especially for processing requests
      with a stream as the payload. In this example, the class implementing
      the StreamInvocationHandler is the TestStreamInvocationHandler class,
      which is an inner class to the StreamingServer. The handleStream()
      method within the TestStreamInvocationHandler will use the stream passed
      to it to write out its contents to a file on disk, as specified by the
      second parameter passed to the handleStream() method. Upon writing out
      the file to disk, the handleStream() method will return to the client
      caller the size of the file.</para>

      <para>To run this example, can compile both the StreamingClient and
      StreamingServer class, then run the StreamingServer and then the
      StreamingClient. Or can go to the examples directory and run the ant
      target 'run-stream-server' and then in another window run the ant target
      'run-stream-client'. For example:</para>

      <programlisting>ant run-stream-server</programlisting>

      <para>and then:</para>

      <programlisting>ant run-stream-client</programlisting>

      <para>The output in the StreamingClient console window should look
      like:</para>

      <programlisting>Calling on remoting server with locator uri of: socket://localhost:5400
Sending input stream for file sample.txt to server.
Size of file sample.txt is 987
Server returned 987 as the size of the file read.</programlisting>

      <para>The output in the StreamingServer console window should look
      like:</para>

      <programlisting>Starting remoting server with locator uri of: socket://localhost:5400
Received input stream from client to write out to file server_sample.txt
Read stream of size 987.  Now writing to server_sample.txt
New file server_sample.txt has been written out to C:\tmp\JBossRemoting_1_4_0_final\examples\server_sample.txt</programlisting>

      <para>After running this example, there should be a newly created
      server_sample.txt file in the root examples directory. The contents of
      the file should look exactly like the contents of the sample.txt file
      located in the examples\org\jboss\remoting\samples\stream
      directory.</para>
    </section>

    <section>
      <title>JBoss Serialization</title>

      <para>The serialization sample (found in the
      org.jboss.remoting.samples.serialization package) illustrates how JBoss
      Serialization can be used in place of the standard java serialization to
      allow for sending of invocation payload objects that do not implement
      the java.io.Serializable interface. This example is composed of three
      classes: SerializationClient, SerializationServer, and
      NonSerializablePayload.</para>

      <para>This example is exactly like the one from the simple example with
      two differences. The first difference is the use of JBoss Serialization
      to convert object instances to binary data format for wire transfer.
      This is accomplished by adding an extra parameter (serializationtype) to
      the locator url with a value of 'jboss'. Is important to note that use
      of JBoss Serialization requires JDK 1.5, so this example will need to be
      run using JDK 1.5. The second difference is instead of sending and
      receiving a simple String type for the remote invocation payload, will
      be sending and receiving an instance of the NonSerializablePayload
      class.</para>

      <para>There are a few important points to notice with the
      NonSerializablePayload class. The first is that it does NOT implement
      the java.io.Serializable interface. The second is that it has a void
      parameter constructor. This is a requirement of JBoss Serialization for
      object instances that do not implement the Serializable interface.
      However, this void parameter constructor can be private, as in the case
      of NonSerializablePayload, as to not change the external API of the
      class.</para>

      <para>To run this example, can compile both the SerializationClient and
      SerializationServer class, then run the SerializationServer and then the
      SerializationClient. Or can go to the examples directory and run the ant
      target 'run-serialization-server' and then in another window run the ant
      target 'run-serialization-client'. For example:</para>

      <programlisting>ant run-serialization-server</programlisting>

      <para>and then:</para>

      <programlisting>ant run-serialization-client</programlisting>

      <para>The output in the SerializationClient console window should look
      like:</para>

      <programlisting>Calling remoting server with locator uri of: socket://localhost:5400/?serializationtype=jboss
Invoking server with request of 'NonSerializablePayload - name: foo, id: 1'
Invocation response: NonSerializablePayload - name: bar, id: 2</programlisting>

      <para>The output in the SerializationServer console window should look
      like:</para>

      <programlisting>Starting remoting server with locator uri of: socket://localhost:5400/?serializationtype=jboss
Invocation request is: NonSerializablePayload - name: foo, id: 1
Returning response of: NonSerializablePayload - name: bar, id: 2</programlisting>

      <para>Note: will have to manually shut down the SerializationServer once
      started.</para>
    </section>

    <section>
      <title>Transporters</title>

      <para>The transporter sample spans several examples showing different
      ways to use the transporter. Each specific example is within its own
      package under the org.jboss.remoting.samples.transporter package. Since
      each of the transporter examples includes common objects, as well as
      client and server classes, the common objects will be found under the
      main transporter sub-package and the client and server classes in their
      respective sub-packages (named client and server).</para>

      <section>
        <title>Transporter sample - basic</title>

        <para>The basic transporter example (found in
        org.jboss.remoting.samples.transporter.basic package) illustrates how
        to build a simple transporter for making remote invocations on plain
        old java objects.</para>

        <para>In this first, basic transporter example, will be using a few
        domain objects; <code>Customer</code> and Address, which are just data
        objects.</para>

        <programlisting>public class <emphasis role="bold">Customer</emphasis> implements Serializable
{
   private String firstName = null;
   private String lastName = null;
   private Address addr = null;
   private int customerId = -1;

   public String getFirstName()
   {
      return firstName;
   }

   public void setFirstName(String firstName)
   {
      this.firstName = firstName;
   }

   public String getLastName()
   {
      return lastName;
   }

   public void setLastName(String lastName)
   {
      this.lastName = lastName;
   }

   public Address getAddr()
   {
      return addr;
   }

   public void setAddr(Address addr)
   {
      this.addr = addr;
   }

   public int getCustomerId()
   {
      return customerId;
   }

   public void setCustomerId(int customerId)
   {
      this.customerId = customerId;
   }

   public String toString()
   {
      StringBuffer buffer = new StringBuffer();
      buffer.append("\nCustomer:\n");
      buffer.append("customer id: " + customerId + "\n");
      buffer.append("first name: " + firstName + "\n");
      buffer.append("last name: " + lastName + "\n");
      buffer.append("street: " + addr.getStreet() + "\n");
      buffer.append("city: " + addr.getCity() + "\n");
      buffer.append("state: " + addr.getState() + "\n");
      buffer.append("zip: " + addr.getZip() + "\n");

      return buffer.toString();
   }
}</programlisting>

        <programlisting>public class <emphasis role="bold">Address</emphasis> implements Serializable
{
   private String street = null;
   private String city = null;
   private String state = null;
   private int zip = -1;

   public String getStreet()
   {
      return street;
   }

   public void setStreet(String street)
   {
      this.street = street;
   }

   public String getCity()
   {
      return city;
   }

   public void setCity(String city)
   {
      this.city = city;
   }

   public String getState()
   {
      return state;
   }

   public void setState(String state)
   {
      this.state = state;
   }

   public int getZip()
   {
      return zip;
   }

   public void setZip(int zip)
   {
      this.zip = zip;
   }
}</programlisting>

        <para>Next comes the POJO that we want to expose a remote proxy for,
        which is <code>CustomerProcessorImpl</code> class. This implementation
        has one method to process a <code>Customer</code> object. It also
        implements the <code>CustomerProcessor</code> interface.</para>

        <programlisting>public class <emphasis role="bold">CustomerProcessorImpl</emphasis> implements <emphasis
            role="bold">CustomerProcessor</emphasis>
{
   /**
    * Takes the customer passed, and if not null and customer id
    * is less than 0, will create a new random id and set it.
    * The customer object returned will be the modified customer
    * object passed.
    *
    * @param customer
    * @return
    */
   public Customer processCustomer(Customer customer)
   {
      if(customer != null &amp;&amp; customer.getCustomerId() &lt; 0)
      {
         customer.setCustomerId(new Random().nextInt(1000));
      }
      System.out.println("processed customer with new id of " + customer.getCustomerId());
      return customer;
   }
}</programlisting>

        <programlisting>public interface <emphasis role="bold">CustomerProcessor</emphasis>
{
   /**
    * Process a customer object.  Implementors
    * should ensure that the customer object
    * passed as parameter should have its internal
    * state changed somehow and returned.
    *
    * @param customer
    * @return
    */
   public Customer processCustomer(Customer customer);
}</programlisting>

        <para>So far, nothing special, just plain old java objects. Next need
        to create the server component that will listen for remote request to
        invoke on the target POJO. This is where the transporter comes
        in.</para>

        <programlisting>public class <emphasis role="bold">Server</emphasis>
{
   private String locatorURI = "socket://localhost:5400";
   private TransporterServer server = null;

   public void start() throws Exception
   {
      server = <emphasis role="bold">TransporterServer.createTransporterServer(locatorURI, new CustomerProcessorImpl())</emphasis>;
   }

   public void stop()
   {
      if(server != null)
      {
         server.stop();
      }
   }

   public static void main(String[] args)
   {
      Server server = new Server();
      try
      {
         server.start();

         Thread.currentThread().sleep(60000);

      }
      catch(Exception e)
      {
         e.printStackTrace();
      }
      finally
      {
         server.stop();
      }
   }
}</programlisting>

        <para>The <code>Server</code> class is a pretty simple one. It calls
        the <code>TransporterServer</code> factory method to create the server
        component for the <code>CustomerProcessorImpl</code> instance using
        the specified remoting locator information.</para>

        <para>The <code>TransporterServer</code> returned from the
        <code>createTransporterServer() </code>call will be a running instance
        of a remoting server using the <literal>socket</literal> transport
        that is bound to <literal>localhost</literal> and listening for remote
        requests on port <literal>5400</literal>. The requests that come in
        will be forwarded to the remoting handler which will convert them into
        direct method calls on the target POJO,
        <code>CustomerProcessorImpl</code> in this case, using
        reflection.</para>

        <para>The <code>TransporterServer</code> has a <code>start()</code>
        and <code>stop()</code> method exposed to control when to start and
        stop the running of the remoting server. The <code>start()</code>
        method is called automatically within the
        <code>createTransporterServer()</code> method, so is ready to receive
        requests upon the return of this method. The <code>stop()</code>
        method, however, needs to be called explicitly when no longer wish to
        receive remote calls on the target POJO.</para>

        <para>Next up is the client side. This is represented by the
        <code>Client</code> class.</para>

        <programlisting>public class <emphasis role="bold">Client</emphasis>
{
   private String locatorURI = "socket://localhost:5400";

   public void makeClientCall() throws Exception
   {
      Customer customer = createCustomer();

      <emphasis role="bold">CustomerProcessor customerProcessor = (CustomerProcessor) TransporterClient.createTransporterClient(locatorURI, CustomerProcessor.class);</emphasis>

      System.out.println("Customer to be processed: " + customer);
      <emphasis role="bold">Customer processedCustomer = customerProcessor.processCustomer(customer);</emphasis>
      System.out.println("Customer is now: " + processedCustomer);

      <emphasis role="bold">TransporterClient.destroyTransporterClient(customerProcessor);</emphasis>
   }

   private Customer createCustomer()
   {
      Customer cust = new Customer();
      cust.setFirstName("Bob");
      cust.setLastName("Smith");
      Address addr = new Address();
      addr.setStreet("101 Oak Street");
      addr.setCity("Atlanata");
      addr.setState("GA");
      addr.setZip(30249);
      cust.setAddr(addr);

      return cust;
   }

   public static void main(String[] args)
   {
      Client client = new Client();
      try
      {
         client.makeClientCall();
      }
      catch(Exception e)
      {
         e.printStackTrace();
      }
   }
}</programlisting>

        <para>The <code>Client</code> class is also pretty simple. It creates
        a new <code>Customer</code> object instance, creates the remote proxy
        to the <code>CustomerProcessor</code>, and then calls on the
        <code>CustomerProcessor</code> to process its new
        <code>Customer</code> instance.</para>

        <para>To get the remote proxy for the <code>CustomerProcessor</code>,
        all that is required is to call the <code>TransporterClient</code>'s
        method <code>createTransporterClient()</code> method and pass the
        locator uri and the type of the remote proxy (and explicitly cast the
        return to that type). This will create a dynamic proxy for the
        specified type, <code>CustomerProcessor</code> in this case, which is
        backed by a remoting client which in turn makes the calls to the
        remote POJO's remoting server. Once the call to
        <code>createTransportClient()</code> has returned, the remoting client
        has already made its connection to the remoting server and is ready to
        make calls (will throw an exception if it could not connect to the
        specified remoting server).</para>

        <para>When finished making calls on the remote POJO proxy, will need
        to explicitly destroy the client by calling
        <code>destroyTransporterClient()</code> and pass the remote proxy
        instance. This allows the remoting client to disconnect from the
        POJO's remoting server and clean up any network resources previously
        used.</para>

        <para>To run this example, can run the Server and then the Client. Or
        can go to the examples directory and run the ant target
        'run-transporter-basic-server' and then in another window run the ant
        target 'run-transporter-basic-client'. For example:</para>

        <programlisting>ant run-transporter-basic-server</programlisting>

        <para>and then:</para>

        <programlisting>ant run-transporter-basic-client</programlisting>

        <para>The output from the Client console should be similar to:</para>

        <programlisting>Customer to be processed:
Customer:
customer id: -1
first name: Bob
last name: Smith
street: 101 Oak Street
city: Atlanata
state: GA
zip: 30249

Customer is now:
Customer:
customer id: 204
first name: Bob
last name: Smith
street: 101 Oak Street
city: Atlanata
state: GA
zip: 30249

</programlisting>

        <para>and the output from the Server class should be similar
        to:</para>

        <programlisting>processed customer with new id of 204</programlisting>

        <para>The output shows that the <code>Customer</code> instance created
        on the client was sent to the server where it was processed (by
        setting the customer id to 204) and returned to the client (and
        printed out showing that the customer id was set to 204).</para>
      </section>

      <section>
        <title>Transporter sample - JBoss serialization</title>

        <para>The transporter serialization example (found in
        org.jboss.remoting.samples.transporter.serialization package) is very
        similar to the previous basic example, except in this one, the domain
        objects being sent over the wire will NOT be Serializable. This is
        accomplished via the use of JBoss Serialization. This can be useful
        when don't know which domain objects you may be using in remote calls
        or if adding ability for remote calls on legacy code.</para>

        <para>To start, there are a few more domain objects:
        <code>Order</code>, <code>OrderProcessor</code>, and
        <code>OrderProcessorImpl</code>. These will use some of the domain
        objects from the previous example as well, such as
        <code>Customer</code>.</para>

        <programlisting>public class <emphasis role="bold">Order</emphasis>
{
   private int orderId = -1;
   private boolean isProcessed = false;
   private Customer customer = null;
   private List items = null;


   public int getOrderId()
   {
      return orderId;
   }

   public void setOrderId(int orderId)
   {
      this.orderId = orderId;
   }

   public boolean isProcessed()
   {
      return isProcessed;
   }

   public void setProcessed(boolean processed)
   {
      isProcessed = processed;
   }

   public Customer getCustomer()
   {
      return customer;
   }

   public void setCustomer(Customer customer)
   {
      this.customer = customer;
   }

   public List getItems()
   {
      return items;
   }

   public void setItems(List items)
   {
      this.items = items;
   }

   public String toString()
   {
      StringBuffer buffer = new StringBuffer();
      buffer.append("\nOrder:\n");
      buffer.append("\nIs processed: " + isProcessed);
      buffer.append("\nOrder id: " + orderId);
      buffer.append(customer.toString());

      buffer.append("\nItems ordered:");
      Iterator itr = items.iterator();
      while(itr.hasNext())
      {
         buffer.append("\n" + itr.next().toString());
      }

      return buffer.toString();
   }
}</programlisting>

        <programlisting>public class <emphasis role="bold">OrderProcessorImpl</emphasis> implements <emphasis
            role="bold">OrderProcessor</emphasis>
{
   private CustomerProcessor customerProcessor = null;

   public OrderProcessorImpl()
   {
      customerProcessor = new CustomerProcessorImpl();
   }

   public Order processOrder(Order order)
   {
      System.out.println("Incoming order to process from customer.\n" + order.getCustomer());

      // has this customer been processed?
      if(order.getCustomer().getCustomerId() &lt; 0)
      {
         order.setCustomer(customerProcessor.processCustomer(order.getCustomer()));
      }

      List items = order.getItems();
      System.out.println("Items ordered:");
      Iterator itr = items.iterator();
      while(itr.hasNext())
      {
         System.out.println(itr.next());
      }

      order.setOrderId(new Random().nextInt(1000));
      order.setProcessed(true);

      System.out.println("Order processed.  Order id now: " + order.getOrderId());
      return order;
   }
}</programlisting>

        <programlisting>public interface OrderProcessor
{
   public Order processOrder(Order order);
}</programlisting>

        <para>The <code>OrderProcessorImpl</code> will take orders, via the
        <code>processOrder() </code>method, check that the customer for the
        order has been processed, and if not have the customer processor
        process the new customer. Then will place the order, which means will
        just set the order id and processed attribute to true.</para>

        <para>The most important point to this example is that the
        <code>Order</code> class does NOT implement
        <code>java.io.Serializable</code>.</para>

        <para>Now onto the <code>Server</code> class. This is just like the
        previous <code>Server</code> class in the basic example with one main
        difference: the <code>locatorURI</code> value.</para>

        <programlisting>public class <emphasis role="bold">Server</emphasis>
{
   private String locatorURI = "socket://localhost:5400/?<emphasis role="bold">serializationtype=jboss</emphasis>";
   private TransporterServer server = null;

   public void start() throws Exception
   {
      server = TransporterServer.createTransporterServer(locatorURI, new OrderProcessorImpl());
   }

   public void stop()
   {
      if(server != null)
      {
         server.stop();
      }
   }

   public static void main(String[] args)
   {
      Server server = new Server();
      try
      {
         server.start();

         Thread.currentThread().sleep(60000);

      }
      catch(Exception e)
      {
         e.printStackTrace();
      }
      finally
      {
         server.stop();
      }
   }
}</programlisting>

        <para>The addition of <literal>serializationtype=jboss</literal> tells
        the remoting framework to use JBoss Serialization in place of the
        standard java serialization.</para>

        <para>On the client side, there is the <code>Client</code> class, just
        as in the previous basic example.</para>

        <programlisting>public class <emphasis role="bold">Client</emphasis>
{
   private String locatorURI = "socket://localhost:5400/?<emphasis role="bold">serializationtype=jboss</emphasis>";

   public void makeClientCall() throws Exception
   {
      Order order = createOrder();

      OrderProcessor orderProcessor = (OrderProcessor) TransporterClient.createTransporterClient(locatorURI, OrderProcessor.class);

      System.out.println("Order to be processed: " + order);
      Order changedOrder = orderProcessor.processOrder(order);
      System.out.println("Order now processed " + changedOrder);

      TransporterClient.destroyTransporterClient(orderProcessor);

   }

   private Order createOrder()
   {
      Order order = new Order();
      Customer customer = createCustomer();
      order.setCustomer(customer);

      List items = new ArrayList();
      items.add("Xbox 360");
      items.add("Wireless controller");
      items.add("Ghost Recon 3");

      order.setItems(items);

      return order;
   }

   private Customer createCustomer()
   {
      Customer cust = new Customer();
      cust.setFirstName("Bob");
      cust.setLastName("Smith");
      Address addr = new Address();
      addr.setStreet("101 Oak Street");
      addr.setCity("Atlanata");
      addr.setState("GA");
      addr.setZip(30249);
      cust.setAddr(addr);

      return cust;
   }

   public static void main(String[] args)
   {
      Client client = new Client();
      try
      {
         client.makeClientCall();
      }
      catch(Exception e)
      {
         e.printStackTrace();
      }
   }
}</programlisting>

        <para>Again, the biggest difference to note is that have added
        <literal>serializationtype=jboss</literal> to the locator uri.</para>

        <para>Note: Running this example requires JDK 1.5.</para>

        <para>To run this example, can run the Server and then the Client. Or
        can go to the examples directory and run the ant target 'ant
        run-transporter-serialization-server' and then in another window run
        the ant target 'ant run-transporter-serialization-client'. For
        example:</para>

        <programlisting>ant run-transporter-serialization-server</programlisting>

        <para>and then:</para>

        <programlisting>ant run-transporter-serialization-client</programlisting>

        <para>When the server and client are run the output for the
        <code>Client</code> class is:</para>

        <programlisting>Order to be processed:
Order:

Is processed: false
Order id: -1
Customer:
customer id: -1
first name: Bob
last name: Smith
street: 101 Oak Street
city: Atlanata
state: GA
zip: 30249

Items ordered:
Xbox 360
Wireless controller
Ghost Recon 3
Order now processed
Order:

Is processed: true
Order id: 221
Customer:
customer id: 861
first name: Bob
last name: Smith
street: 101 Oak Street
city: Atlanata
state: GA
zip: 30249

Items ordered:
Xbox 360
Wireless controller
Ghost Recon 3
</programlisting>

        <para>The client output shows the printout of the newly created order
        before calling the <code>OrderProcessor</code> and then the processed
        order afterwards. Noticed that the processed order has its customer's
        id set, its order id set and the processed attribute is set to
        true.</para>

        <para>And the output from the <code>Server</code> is:</para>

        <programlisting>Incoming order to process from customer.

Customer:
customer id: -1
first name: Bob
last name: Smith
street: 101 Oak Street
city: Atlanata
state: GA
zip: 30249

processed customer with new id of 861
Items ordered:
Xbox 360
Wireless controller
Ghost Recon 3
Order processed.  Order id now: 221
</programlisting>

        <para>The server output shows the printout of the customer before
        being processed and then the order while being processed.</para>
      </section>

      <section>
        <title>Transporter sample - clustered</title>

        <para>In the previous examples, there has been one and only one target
        POJO to make calls upon. If that target POJO was not available, the
        client call would fail. In the transporter clustered example (found in
        org.jboss.remoting.samples.transporter.clustered package), will show
        how to use the transporter in clustered mode so that if one target
        POJO becomes unavailable, the client call can be seamlessly failed
        over to another available target POJO on the network, regardless of
        network transport type.</para>

        <para>This example uses the domain objects from the first, basic
        example, so only need to cover the client and server code. For this
        example, there are three different server classes. The first class is
        the <code>SocketServer</code> class, which is the exact same as the
        <code>Server</code> class in the basic example, except for the call to
        the <code>TransportServer</code>'s <code>createTransportServer()
        </code>method.</para>

        <programlisting>public class <emphasis role="bold">SocketServer</emphasis>
{
   public static String locatorURI = "socket://localhost:5400";
   private TransporterServer server = null;

   public void start() throws Exception
   {
      server = <emphasis role="bold">TransporterServer.createTransporterServer(getLocatorURI(), new CustomerProcessorImpl(),
                                                         CustomerProcessor.class.getName(), true)</emphasis>;
   }

   protected String getLocatorURI()
   {
      return locatorURI;
   }

   public void stop()
   {
      if(server != null)
      {
         server.stop();
      }
   }

   public static void main(String[] args)
   {
      SocketServer server = new SocketServer();
      try
      {
         server.start();

         Thread.currentThread().sleep(60000);

      }
      catch(Exception e)
      {
         e.printStackTrace();
      }
      finally
      {
         server.stop();
      }
   }
}</programlisting>

        <para>Notice that are now calling on the <code>TransportServer</code>
        to create a server with the locator uri and target POJO
        (<code>CustomerProcessorImpl</code>) as before, but have also added
        the interface type of the target POJO (<code>CustomerProcessor</code>)
        and that want clustering turned on (via the last
        <literal>true</literal> parameter).</para>

        <para>The interface type of the target POJO is needed because this
        will be used as the subsystem within the remoting server for the
        target POJO. The subsystem value will be what the client uses to
        determine if discovered remoting server is for the target POJO they
        are looking for.</para>

        <sidebar>
          <para>The transporter uses the MulticastDetector from JBoss Remoting
          for automatic discovery when in clustered mode. The actual detection
          of remote servers that come online can take up to a few seconds once
          started. There is a JNDI based detector provided within JBoss
          Remoting, but has not been integrated within the transporters
          yet.</para>
        </sidebar>

        <para>The second server class is the <code>RMIServer</code> class. The
        <code>RMIServer</code> class extends the <code>SocketServer</code>
        class and uses a different locator uri specify <literal>rmi</literal>
        as the transport protocol and a different port
        (<literal>5500</literal>).</para>

        <programlisting>public class <emphasis role="bold">RMIServer</emphasis> extends <emphasis
            role="bold">SocketServer</emphasis>
{
   private String localLocatorURI = "r<emphasis role="bold">mi://localhost:5500</emphasis>";

   protected String getLocatorURI()
   {
      return localLocatorURI;
   }

   public static void main(String[] args)
   {
      SocketServer server = new RMIServer();
      try
      {
         server.start();

         Thread.currentThread().sleep(60000);

      }
      catch(Exception e)
      {
         e.printStackTrace();
      }
      finally
      {
         server.stop();
      }
   }
}</programlisting>

        <para>The last server class is the <code>HTTPServer</code> class. The
        <code>HTTPServer</code> class also extends the
        <code>SocketServer</code> class and specifies <literal>http</literal>
        as the transport protocol and <literal>5600</literal> as the port to
        listen for requests on.</para>

        <programlisting>public class <emphasis role="bold">HTTPServer</emphasis> extends <emphasis
            role="bold">SocketServer</emphasis>
{
   private String localLocatorURI = "<emphasis role="bold">http://localhost:5600</emphasis>";

   protected String getLocatorURI()
   {
      return localLocatorURI;
   }

   public static void main(String[] args)
   {
      SocketServer server = new HTTPServer();
      try
      {
         server.start();

         Thread.currentThread().sleep(60000);

      }
      catch(Exception e)
      {
         e.printStackTrace();
      }
      finally
      {
         server.stop();
      }
   }
}</programlisting>

        <para>On the client side, there is only the <code>Client</code> class.
        This class is very similar to the one from the basic example. The main
        exceptions are (1) the addition of a <code>TransporterClient</code>
        call to create a transporter client and (2) the fact that it
        continually loops, making calls on its <code>customerProcessor</code>
        variable to process customers. This is done so that when we run the
        client, we can kill the different servers and see that the client
        continues to loop making its calls without any exceptions or
        errors.</para>

        <programlisting>public class <emphasis role="bold">Client</emphasis>
{
   <emphasis role="bold">private String locatorURI = SocketServer.locatorURI;</emphasis>

   private CustomerProcessor customerProcessor = null;

   public void makeClientCall() throws Exception
   {
      Customer customer = createCustomer();

      System.out.println("Customer to be processed: " + customer);
      <emphasis role="bold">Customer processedCustomer = customerProcessor.processCustomer(customer);</emphasis>
      System.out.println("Customer is now: " + processedCustomer);

      //TransporterClient.destroyTransporterClient(customerProcessor);
   }

   public void getCustomerProcessor() throws Exception
   {
      customerProcessor = (CustomerProcessor) <emphasis role="bold">TransporterClient.createTransporterClient(locatorURI, CustomerProcessor.class, true)</emphasis>;
   }

   private Customer createCustomer()
   {
      Customer cust = new Customer();
      cust.setFirstName("Bob");
      cust.setLastName("Smith");
      Address addr = new Address();
      addr.setStreet("101 Oak Street");
      addr.setCity("Atlanata");
      addr.setState("GA");
      addr.setZip(30249);
      cust.setAddr(addr);

      return cust;
   }

   public static void main(String[] args)
   {
      Client client = new Client();
      try
      {
<emphasis role="bold">         client.getCustomerProcessor();
         while(true)
         {
            try
            {
               client.makeClientCall();
               Thread.currentThread().sleep(5000);
            }
            catch(Exception e)
            {
               e.printStackTrace();
            }
         }
</emphasis>      }
      catch(Exception e)
      {
         e.printStackTrace();
      }
   }
}</programlisting>

        <para>The first item of note is that the locator uri from the
        <code>SocketServer</code> class is being used. Technically, this is
        not required as once the clustered <code>TransporterClient</code> is
        started, it will start to discover the remoting servers that exist on
        the network. However, this process can take several seconds to occur,
        so unless it is known that no calls will be made on the remote proxy
        right away, it is best to bootstrap with a known target server.</para>

        <para>Can also see that in the <code>main()</code> method, the first
        call on the Client instance is to <code>getCustomerProcessor()</code>.
        This method will call the <code>TransporterClient</code>'s
        <code>createTransporterClient()</code> method and passes the locator
        uri for the target POJO server, the type of POJO's remote proxy, and
        that clustering should be enabled.</para>

        <para>After getting the customer processor remote proxy, will
        continually loop making calls using the remote proxy (via the
        <code>processCustomer()</code> method on the
        <code>customerProcessor</code> variable).</para>

        <para>To run this example, all the servers need to be started (by
        running the <code>SocketServer</code>, <code>RMIServer</code>, and
        <code>HTTPServer</code> classes). Then run the Client class. This can
        be done via ant targets as well. So for example, could open four
        console windows and enter the ant targets as follows:</para>

        <programlisting>ant run-transporter-clustered-socket-server</programlisting>

        <programlisting>ant run-transporter-clustered-http-server</programlisting>

        <programlisting>ant run-transporter-clustered-rmi-server</programlisting>

        <programlisting>ant run-transporter-clustered-client</programlisting>

        <para>Once the client starts running, should start to see output
        logged to the <code>SocketServer</code>, since this is the one used to
        bootstrap. This output would look like:</para>

        <programlisting>processed customer with new id of 378
processed customer with new id of 487
processed customer with new id of 980</programlisting>

        <para>Once the <code>SocketServer</code> instance has received a few
        calls, kill this instance. The next time the client makes a call on
        its remote proxy, which happens every five seconds, it should fail
        over to another one of the servers (and will see similar output on
        that server instance). After that server has received a few calls,
        kill it and should see it fail over once again to the last server
        instance that is still running. Then, if kill that server instance,
        will see a CannotConnectException and stack trace similar to the
        following:</para>

        <programlisting><emphasis role="bold">...
org.jboss.remoting.CannotConnectException</emphasis>: Can not connect http client invoker.
 at org.jboss.remoting.transport.http.HTTPClientInvoker.useHttpURLConnection(HTTPClientInvoker.java:147)
 at org.jboss.remoting.transport.http.HTTPClientInvoker.transport(HTTPClientInvoker.java:56)
 at org.jboss.remoting.RemoteClientInvoker.invoke(RemoteClientInvoker.java:112)
 at org.jboss.remoting.Client.invoke(Client.java:226)
 at org.jboss.remoting.Client.invoke(Client.java:189)
 at org.jboss.remoting.Client.invoke(Client.java:174)
 at org.jboss.remoting.transporter.TransporterClient.invoke(TransporterClient.java:219)
 at $Proxy0.processCustomer(Unknown Source)
 at org.jboss.remoting.samples.transporter3.client.Client.makeClientCall(Client.java:29)
 at org.jboss.remoting.samples.transporter3.client.Client.main(Client.java:64)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:585)
 at com.intellij.rt.execution.application.AppMain.main(AppMain.java:86)
Caused by: java.net.ConnectException: Connection refused: connect
 at java.net.PlainSocketImpl.socketConnect(Native Method)
 at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
 at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
 at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
 at java.net.Socket.connect(Socket.java:507)
 at java.net.Socket.connect(Socket.java:457)
 at sun.net.NetworkClient.doConnect(NetworkClient.java:157)
 at sun.net.www.http.HttpClient.openServer(HttpClient.java:365)
 at sun.net.www.http.HttpClient.openServer(HttpClient.java:477)
 at sun.net.www.http.HttpClient.&lt;init&gt;(HttpClient.java:214)
 at sun.net.www.http.HttpClient.New(HttpClient.java:287)
 at sun.net.www.http.HttpClient.New(HttpClient.java:299)
 at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:792)
 at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:744)
 at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:669)
 at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:836)
 at org.jboss.remoting.transport.http.HTTPClientInvoker.useHttpURLConnection(HTTPClientInvoker.java:117)
 ... 14 more</programlisting>

        <para>since there are no target servers left to make calls on. Notice
        that earlier in the client output there were no errors while was
        failing over to the different servers as they were being
        killed.</para>

        <para>Because the CannotConnectException is being caught within the
        while loop, the client will continue to try calling the remote proxy
        and getting this exception. Now re-run any of the previously killed
        servers and will see that the client will discover that server
        instance and begin to successfully call on that server. The output
        should look something like:</para>

        <programlisting>...
 at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:669)
 at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:836)
 at org.jboss.remoting.transport.http.HTTPClientInvoker.useHttpURLConnection(HTTPClientInvoker.java:117)
 ... 14 more

Customer to be processed:
Customer:
customer id: -1
first name: Bob
last name: Smith
street: 101 Oak Stree
city: Atlanata
state: null
zip: 30249

Customer is now:
Customer:
customer id: 633
first name: Bob
last name: Smith
street: 101 Oak Stree
city: Atlanata
state: null
zip: 30249

...</programlisting>

        <sidebar>
          <para>As demonstrated in this example, fail over can occur across
          any of the JBoss Remoting transports. Clustered transporters is also
          supported using JBoss Serialization, which was introduced in the
          previous example.</para>

          <para>It is important to understand that in the context of
          transporters, clustering means invocation fail over. The JBoss
          Remoting transporters themselves do not handle any form of state
          replication. If this feature were needed, could use JBoss Cache to
          store the target POJO instances so that when their state changed,
          that change would be replicated to the other target POJO instances
          running in other processes.</para>
        </sidebar>
      </section>

      <section>
        <title>Transporter sample -complex</title>

        <para>The complex transporter example (found in
        org.jboss.remoting.samples.transporter.complex package) is based off a
        test case a user, Milt Grinberg, provided (thanks Milt). The example
        is similar to the previous examples, except in this case involves
        matching Doctors and Patients using the ProviderInterface and provides
        a more complex sample in which to demonstrate how to use
        transporters.</para>

        <para>This example requires JDK 1.5 to run, since is using JBoss
        Serialization (and non-serialized data objects). To run this example,
        run the Server class and then the Client class. This can be done via
        ant targets 'run-transporter-complex-server' and then
        'run-transporter-complex-server' as well. For example:</para>

        <programlisting>ant run-transporter-complex-server</programlisting>

        <para>and then:</para>

        <programlisting>ant run-transporter-complex-client</programlisting>

        <para>The output for the client should look similar to:</para>

        <programlisting>*** Have a new patient that needs a doctor.  The patient is:

Patient:
   Name: Bill Gates
   Ailment - Type: financial, Description: Money coming out the wazoo.

*** Looking for doctor that can help our patient...

*** Found doctor for our patient.  Doctor found is:
Doctor:
   Name: Andy Jones
   Specialty: financial
   Patients:

Patient:
   Name: Larry Ellison
   Ailment - Type: null, Description: null
   Doctor - Name: Andy Jones

Patient:
   Name: Steve Jobs
   Ailment - Type: null, Description: null
   Doctor - Name: Andy Jones

Patient:
   Name: Bill Gates
   Ailment - Type: financial, Description: Money coming out the wazoo.

*** Set doctor as patient's doctor.  Patient info is now:

Patient:
   Name: Bill Gates
   Ailment - Type: financial, Description: Money coming out the wazoo.
   Doctor - Name: Andy Jones

*** Have a new patient that we need to find a doctor for (remember, the previous one retired and there are no others)
*** Could not find doctor for patient.  This is an expected exception when there are not doctors available.
org.jboss.remoting.samples.transporter.complex.NoDoctorAvailableException: No doctor available for ailment 'financial'
 at org.jboss.remoting.RemoteClientInvoker.invoke(RemoteClientInvoker.java:183)
 at org.jboss.remoting.Client.invoke(Client.java:325)
 at org.jboss.remoting.Client.invoke(Client.java:288)
 at org.jboss.remoting.Client.invoke(Client.java:273)
 at org.jboss.remoting.transporter.TransporterClient.invoke(TransporterClient.java:237)
 at $Proxy0.findDoctor(Unknown Source)
 at org.jboss.remoting.samples.transporter.complex.client.Client.makeClientCall(Client.java:72)
 at org.jboss.remoting.samples.transporter.complex.client.Client.main(Client.java:90)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:585)
 at com.intellij.rt.execution.application.AppMain.main(AppMain.java:86)
</programlisting>

        <para>From the output see the creation of a new patient, Bill Gates,
        and the attempt to find a doctor that specializes in his ailment. For
        Mr. Gates, we were able to find a doctor, Andy Jones, and can see that
        he has been added to the list of Dr. Jones' patients. Then we have Dr.
        Jones retire. Then we create a new patient and try to find an
        available doctor for the same ailment. Since Dr. Jones has retired,
        and there are no other doctors that specialize in that particular
        ailment, an exception is thrown. This is as expected.</para>
      </section>
    </section>

    <section>
      <title id="section-multiplex-invokers"
      xreflabel="Multiplex invokers">Multiplex invokers</title>

      <para>This section illustrates the construction of multiplex invoker
      groups described in the section <xref linkend="section:multiplex" />.
      The directory</para>

      <blockquote>
        <para><code>examples/org/jboss/remoting/samples/multiplex/invoker</code></para>
      </blockquote>

      <para>contains a server class,
      <classname>MultiplexInvokerServer</classname>, which is suitable for use
      with any of the client classes described below. It may be run in an IDE
      or from the command line using ant target
      <code>run-multiplex-server</code> from the <code>build.xml</code> file
      found in the <code>examples</code> directory. The server will stay
      alive, processing invocation requests as they are presented, until it
      has sent two push callbacks to however many listeners are registered, at
      which time it will shut itself down.</para>

      <para>The sample clients are as follows. Each sample client
      <emphasis>&lt;client&gt;</emphasis> may be run in an IDE or by using the
      ant target <code>run-</code><emphasis>&lt;client&gt;</emphasis> (e.g.,
      <code>run-Client2Server1</code>).</para>

      <itemizedlist>
        <listitem>
          <para><classname>Client2Server1</classname>: A
          <classname>MultiplexClientInvoker</classname> starts according to
          client rule 2, after which a
          <classname>MultiplexServerInvoker</classname> is started according
          to server rule 1. Note that the <classname>Client</classname> and
          <classname>Connector</classname> are passed matching
          <emphasis>clientMultiplexId</emphasis> and
          <emphasis>serverMultiplexId</emphasis> parameters,
          respectively.</para>
        </listitem>

        <listitem>
          <para><classname>Client2Server2</classname>: A
          <classname>MultiplexClientInvoker</classname> starts according to
          client rule 2, after which a
          <classname>MultiplexServerInvoker</classname> is started according
          to server rule 2. Note that no
          <emphasis>clientMultiplexId</emphasis> is passed to the
          <classname>Client</classname> and no
          <emphasis>serverMultiplexId</emphasis> parameter is passed to the
          <classname>Connector</classname> in this example.</para>
        </listitem>

        <listitem>
          <para><classname>Client3Server1</classname>: A
          <classname>MultiplexClientInvoker</classname> is created, and,
          lacking binding information, finds itself governed by client rule 3.
          Subsequently, a <classname>MultiplexServerInvoker</classname> is
          started according to server rule 1, providing the binding
          information which allows the
          <classname>MultiplexClientInvoker</classname> to start. Note that
          the <classname>Client</classname> and
          <classname>Connector</classname> are passed matching
          <emphasis>clientMultiplexId</emphasis> and
          <emphasis>serverMultiplexId</emphasis> parameters,
          respectively.</para>
        </listitem>

        <listitem>
          <para><classname>Server2Client1</classname>: A
          <classname>MultiplexServerInvoker</classname> starts according to
          server rule 2, after which a
          <classname>MultiplexClientInvoker</classname> is started according
          to client rule 1. Note that the <classname>Connector</classname> and
          <classname>Client</classname> are passed matching
          <emphasis>serverMultiplexId</emphasis> and
          <emphasis>clientMultiplexId</emphasis> parameters,
          respectively.</para>
        </listitem>

        <listitem>
          <para><classname>Server2Client2</classname>: A
          <classname>MultiplexServerInvoker</classname> starts according to
          server rule 2, after which a
          <classname>MultiplexClientInvoker</classname> is started according
          to client rule 2. Note that no
          <emphasis>serverMultiplexId</emphasis> is passed to the
          <classname>Connector</classname> and no
          <emphasis>clientMultiplexId</emphasis> parameter is passed to the
          <classname>Client</classname> in this example.</para>
        </listitem>

        <listitem>
          <para><classname>Server3Client1</classname>: A
          <classname>MultiplexServerInvoker</classname> is created, and,
          lacking connect information, finds itself governed by server rule 3.
          Subsequently, a <classname>MultiplexClientInvoker</classname> is
          started according to client rule 1, providing the connect
          information which allows the
          <classname>MultiplexServerInvoker</classname> to start. Note that
          the <classname>Connector</classname> and
          <classname>Client</classname> are passed matching
          <emphasis>serverMultiplexId</emphasis> and
          <emphasis>clientMultiplexId</emphasis> parameters,
          respectively.</para>
        </listitem>
      </itemizedlist>

      <para>For variety, the examples in which the client invoker starts first
      use the configuration <classname>Map</classname> to pass invoker group
      parameters, and the examples in which the server invoker starts first
      pass parameters in the <classname>InvokerLocator</classname>.</para>
    </section>
  </chapter>

  <chapter>
    <title>Client programming model</title>

    <para>The approach taken for the programming model on the client side is
    one based on a session based model. This means that it is expected that
    once a Client is created for a particular target server, it will be used
    exclusively to make calls on that server. This expectation dictates some
    of the behavior of the remoting client.</para>

    <para>For example, if create a Client on the client side to make server
    invocations, including adding callback listeners, will have to use that
    same instance of Client to remove the callback listeners. This is because
    the Client creates a unique session id that it passes within the calls to
    the server. This id is used as part of the key for registering callback
    listeners on the server. If create a new Client instance and attempt to
    remove the callback listeners, a new session id will be passed to the
    server invoker, who will not recognize the callback listener to be
    removed.</para>

    <para>See test case
    <code>org.jboss.test.remoting.callback.push.MultipleCallbackServersTestCase</code>
    .</para>
  </chapter>

  <chapter>
    <title>Compatibility and versioning</title>

    <para>As of JBossRemoting 2.0.0 versioning has been added to guarantee
    compatibility between different versions. This is accomplished by changing
    serialization formats for certain classes and by using wire versioing. By
    wire versioning, mean that the version used by a client and server will be
    sent on the wire so that the other side will be able to adjust
    accordingly. This will be automatic for JBossRemoting 2.0.0 and later
    versions. However, since versioning was not introduced until the 2.0.0
    release, if need to have a 1.4.x version of remoting communicate to a
    later version, will need to set a system property on the 2.0.0 version so
    that knows to use the older wire protocol version. The system property to
    set is 'jboss.remoting.pre_2_0_compatible' and should be set to true.
    There are a few minor features that will not be fully compatible between
    1.4.x release and 2.0.0, which are listed in the release notes.</para>
  </chapter>

  <chapter>
    <title>Getting the JBossRemoting source and building</title>

    <para>The JBossRemoting source code resides in the JBoss CVS repository
    under the CVS module JBossRemoting. To check out the source using the
    anonymous account, use the following command:</para>

    <programlisting>cvs -d:pserver:anonymous@anoncvs.forge.jboss.com:/cvsroot/jboss checkout JBossRemoting</programlisting>

    <para>To check out the source using a committer user id, use the
    following:</para>

    <programlisting>cvs -d:ext:username@cvs.forge.jboss.com:/cvsroot/jboss checkout JBossRemoting</programlisting>

    <para>This should checkout the entire remoting project, including doc,
    tests, libs, etc.</para>

    <para>See <!--<link linkend="???">http://www.jboss.org/wiki/Wiki.jsp?page=CVSRepository</link>-->
    <ulink url="http://www.jboss.org/wiki/Wiki.jsp?page=CVSRepository">
    http://www.jboss.org/wiki/Wiki.jsp?page=CVSRepository </ulink> for more
    information on how to access the JBoss CVS repository.</para>

    <para>The build process for JBossRemoting is based on a standard ant build
    file (build.xml). The version of ant that is supported is ant 1.6.2, but
    should work with earlier versions as there are no special ant features
    being used.</para>

    <para>The main ant build targets are as follows:</para>

    <para><emphasis role="bold">compile</emphasis> - compiles all the core
    JBossRemoting classes.</para>

    <para><emphasis role="bold">jars</emphasis> - creates the
    jboss-remoting.jar file from the compiled classes</para>

    <para><emphasis role="bold">javadoc</emphasis> - creates the javadoc html
    files for JBossRemoting</para>

    <para><emphasis role="bold">tests.compile</emphasis> - compiles the
    JBossRemoting test files</para>

    <para><emphasis role="bold">tests.jars</emphasis> - creates the
    jboss-remoting-tests.jar and jboss-remoting-loading-tests.jar
    files.</para>

    <para><emphasis role="bold">tests.quick</emphasis> - runs the functional
    unit tests for JBossRemoting.</para>

    <para><emphasis role="bold">tests</emphasis> - runs all the tests for
    JBossRemoting, including functional and performance tests for all the
    different transports.</para>

    <para><emphasis role="bold">clean</emphasis> - removes all the build
    artifacts and directories.</para>

    <para><emphasis role="bold">most</emphasis> - calls clean then jars
    targets.</para>

    <para><emphasis role="bold">dist</emphasis> - builds the full
    JBossRemoting distribution including running the full test suite.</para>

    <para><emphasis role="bold">dist.quick</emphasis> - builds the full
    JBossRemoting distribution, but does not run the test suite.</para>

    <para>The root directory for all build output is the output directory.
    Under this directory will be:</para>

    <para><literal>classes</literal> - compiled core classes
    <literal></literal></para>

    <para><literal>etc</literal> - deployment and JMX XMBean xml files
    <literal></literal></para>

    <para><literal>lib</literal> - all the jars and war file produced by the
    build <literal></literal></para>

    <para><literal>tests</literal> - contains the compiled test classes and
    test results</para>

    <para>For most development, the most target can be used. Please run the
    tests.quick target before checking anything in to ensure that code changes
    did not break any previously functioning test.</para>
  </chapter>

  <chapter>
    <title>Known issues</title>

    <para>All of the known issues and road map can be found on our bug
    tracking system, Jira, at <!--<link linkend="???">http://jira.jboss.com/jira/secure/BrowseProject.jspa?id=10031</link>-->
    <ulink
    url="http://jira.jboss.com/jira/secure/BrowseProject.jspa?id=10031">
    http://jira.jboss.com/jira/secure/BrowseProject.jspa?id=10031 </ulink>
    (require member plus registration, which is free). If you find more,
    please post them to Jira. If you have questions post them to the JBoss
    Remoting users forum <!--<link linkend="???">http://www.jboss.com/index.html?module=bb&amp;op=viewforum&amp;f=222</link>-->
    (<ulink
    url="http://www.jboss.com/index.html?module=bb&amp;op=viewforum&amp;f=222">
    http://www.jboss.com/index.html?module=bb&amp;op=viewforum&amp;f=222
    </ulink>).</para>
  </chapter>

  <chapter>
    <title>Future plans</title>

    <para>Full road map for JBossRemoting can be found at <!--<link linkend="???">
                http://jira.jboss.com/jira/browse/JBREM?report=com.atlassian.jira.plugin.system.project:roadmap-panel
             </link>--> <ulink
    url="http://jira.jboss.com/jira/browse/JBREM?report=com.atlassian.jira.plugin.system.project:roadmap-panel">
    http://jira.jboss.com/jira/browse/JBREM?report=com.atlassian.jira.plugin.system.project:roadmap-panel
    </ulink>.</para>

    <para>If you have questions, comments, bugs, fixes, contributions, or
    flames, please post them to the JBoss Remoting users forum <!--<link linkend="???">http://www.jboss.com/index.html?module=bb&amp;op=viewforum&amp;f=222</link>-->
    (<ulink
    url="http://www.jboss.com/index.html?module=bb&amp;op=viewforum&amp;f=222">
    http://www.jboss.com/index.html?module=bb&amp;op=viewforum&amp;f=222
    </ulink>). You can also find more information about JBoss Remoting on our
    <!--<link linkend="???">http://www.jboss.org/wiki/Wiki.jsp?page=Remoting</link>-->
    wiki (<ulink url="http://www.jboss.org/wiki/Wiki.jsp?page=Remoting">
    http://www.jboss.org/wiki/Wiki.jsp?page=Remoting </ulink> ). The wiki will
    usually contain the latest updates to doc and features that did not make
    into previous release.</para>
  </chapter>

  <chapter>
    <title>Release Notes</title>

    <bridgehead>API incompatabilities between JBossRemoting 1.0.2 and
    1.2.X</bridgehead>

    <para>The following public API for JBossRemoting was changed in release
    1.2.0 which will make it incompatible with previous versions:</para>

    <para>- Removed ClientInvokerAdapter and dependent classes</para>

    <para>- Callback related classes moved to new remoting callback
    package</para>

    <para>- InvokerCallbackHandler accepts Callback type as parameter instead
    of InvocationRequest</para>

    <para></para>

    <para>Release Notes - JBoss Remoting - Version 1.4.1 final</para>

    <para>** Feature Request</para>

    <para>* [JBREM-310] - Ability to turn connection checking off</para>

    <para>* [JBREM-325] - move IMarshalledValue from jboss-commons to
    jboss-remoting.jar</para>

    <para>** Bug</para>

    <para>* [JBREM-313] - client lease does not work if client and server in
    same VM (using local invoker)</para>

    <para>* [JBREM-317] - HTTPClientInvoker conect sends gratuitous
    POST</para>

    <para>* [JBREM-341] - Client ping interval must be lease than lease
    period</para>

    <para>* [JBREM-343] - Exceptions on connection closing</para>

    <para>* [JBREM-345] - problem using client address and port</para>

    <para>* [JBREM-346] - fix ConcurrentModificationException in cleanup of
    MultiplexServerInvoker</para>

    <para>* [JBREM-350] - ConcurrentModificationException in
    InvokerRegistry</para>

    <para>* [JBREM-361] - Race condition in invoking on Client</para>

    <para>** Task</para>

    <para>* [JBREM-2] - sample-bindings.xml does not have entry for
    remoting</para>

    <para>* [JBREM-220] - clean up remoting wiki</para>

    <para>* [JBREM-316] - Maintain tomcat originated code under the ASF
    license.</para>

    <para>* [JBREM-319] - ability to inject socket factory by classname or
    instance in all remoting transports</para>

    <para>* [JBREM-323] - client lease config changes</para>

    <para>* [JBREM-329] - create global transport config for timeout</para>

    <para>* [JBREM-330] - create socket server factory based off of
    configuration properties</para>

    <para>* [JBREM-335] - Client.invoke() should pass configuration map to
    InvokerRegistry.createClientInvoker().</para>

    <para>* [JBREM-336] - InvokerRegistry doesn't purge InvokerLocators from
    static Set registeredLocators.</para>

    <para>* [JBREM-337] - PortUtil.findFreePort() should return ports only
    between 1024 and 65535.</para>

    <para>* [JBREM-342] - Thread usage for timers and lease
    functionality</para>

    <para>* [JBREM-354] - ServerInvokerCallbackHandler should make its
    subsystem accessible.</para>

    <para>* [JBREM-356] - ServerInvoker should destroy its callback
    handlers.</para>

    <para>* [JBREM-359] - MultiplexInvokerConfigTestCase should execute
    MultiplexInvokerConfigTestServer instead of
    MultiplexInvokerTestServer.</para>

    <para></para>

    <para>Release Notes - JBoss Remoting - Version 1.4.0 final</para>

    <para>** Feature Request</para>

    <para>* [JBREM-91] - UIL2 type transport (duplex calling of same
    socket)</para>

    <para>* [JBREM-117] - clean up callback client after several failures
    delivering callbacks</para>

    <para>* [JBREM-138] - HTTP/Servlet invokers require content length to be
    set</para>

    <para>* [JBREM-229] - Remove dependency on ThreadLocal for
    SerializationManagers and pluggable serialization</para>

    <para>* [JBREM-233] - Server side exception listeners for client
    connections</para>

    <para>* [JBREM-257] - Append client stack trace to thrown remote
    exception</para>

    <para>* [JBREM-261] - Integration with IMarshalledValue from
    JBossCommons</para>

    <para>* [JBREM-278] - remoting detection needs ability to accept detection
    of server invoker running locally</para>

    <para>* [JBREM-280] - no way to add path to invoker uri when using complex
    configuration</para>

    <para>** Bug</para>

    <para>* [JBREM-41] - problem using localhost/127.0.0.1</para>

    <para>* [JBREM-115] - http server invoker does not wait to finish
    processing on stop</para>

    <para>* [JBREM-223] - Broken Pipe if client don't do any calls before the
    timeout value</para>

    <para>* [JBREM-224] - java.net.SocketTimeoutException when socket timeout
    on the keep alive</para>

    <para>* [JBREM-231] - bug in invoker locator when there are no params
    (NPE)</para>

    <para>* [JBREM-234] - StreamCorruptedException in DTM testcase</para>

    <para>* [JBREM-240] - TestUtil does not always give free port for
    server</para>

    <para>* [JBREM-243] - socket client invoker sharing pooled
    connections</para>

    <para>* [JBREM-250] - InvokerLocator doesn't support URL in IPv6 format
    (ex: socket://3000::117:5400/)</para>

    <para>* [JBREM-251] - transporter passes method signature based on
    concrete object and not the parameter type</para>

    <para>* [JBREM-256] - NullPointer in
    MarshallerLoaderHandler.java:69</para>

    <para>* [JBREM-259] - Unmarshalling of server response is not using
    caller's classloader</para>

    <para>* [JBREM-271] - http client invoker needs to explicitly set the
    content type if not provided</para>

    <para>* [JBREM-277] - error shutting down coyote invoker when using APR
    protocol</para>

    <para>* [JBREM-281] - getting random port for connectors is not
    reliable</para>

    <para>* [JBREM-282] - ServletServerInvoker not working with depployed for
    use as ejb invoker</para>

    <para>* [JBREM-286] - Socket server does not clean up server threads on
    shutdown</para>

    <para>* [JBREM-289] - PortUtil only checking for free ports on
    localhost</para>

    <para>** Task</para>

    <para>* [JBREM-7] - Add more tests for local invoker</para>

    <para>* [JBREM-121] - improve connection failure callback</para>

    <para>* [JBREM-126] - add tests for client vs. server address
    bindings</para>

    <para>* [JBREM-195] - Performance optimization</para>

    <para>* [JBREM-199] - remoting clients required to include
    servlet-api.jar</para>

    <para>* [JBREM-207] - clean up build file</para>

    <para>* [JBREM-214] - multiplex performance tests getting out of memory
    error</para>

    <para>* [JBREM-215] - re-write http transport/handler documentation</para>

    <para>* [JBREM-216] - Need to add new samples to example build in
    distro</para>

    <para>* [JBREM-217] - create samples documentation</para>

    <para>* [JBREM-219] - move remoting site to jboss labs</para>

    <para>* [JBREM-226] - Release JBoss Remoting 1.4.0 final</para>

    <para>* [JBREM-230] - create interface for marshallers to implement for
    swapping out serialization impl</para>

    <para>* [JBREM-235] - add new header to source files</para>

    <para>* [JBREM-239] - Update the LGPL headers</para>

    <para>* [JBREM-242] - Subclass multiplex invoker from socket
    invoker.</para>

    <para>* [JBREM-249] - http invoker (tomcat connector) documentation</para>

    <para>* [JBREM-253] - Convert http server invoker implementation to use
    tomcat connector and protocols</para>

    <para>* [JBREM-255] - HTTPClientInvoker not setting response code or
    message</para>

    <para>* [JBREM-275] - fix package error in examle-service.xml</para>

    <para>* [JBREM-276] - transporter does not throw original exception from
    server implementation</para>

    <para>* [JBREM-279] - socket server invoker spits out error messages on
    shutdown when is not needed</para>

    <para>* [JBREM-287] - need to complete javadoc for all user
    classes/interfaces</para>

    <para>* [JBREM-288] - update example-service.xml with new
    configurations</para>

    <para>** Reactor Event</para>

    <para>* [JBREM-241] - Refactor SocketServerInvoker so that can be
    subclassed by MultiplexServerInvoker</para>

    <para></para>

    <para>Release Notes - JBoss Remoting - Version 1.4.0 beta</para>

    <para></para>

    <para>** Feature Request</para>

    <para>* [JBREM-28] - Marshaller for non serializable objects</para>

    <para>* [JBREM-40] - Compression marshaller/unmarshaller</para>

    <para>* [JBREM-120] - config for using hostname in locator url instead of
    ip</para>

    <para>* [JBREM-140] - can not set response headers from invocation
    handlers</para>

    <para>* [JBREM-148] - support pluggable object serialization
    packages</para>

    <para>* [JBREM-175] - Remove Dependencies to Server Classes from
    UnifiedInvoker</para>

    <para>* [JBREM-180] - add plugable serialization</para>

    <para>* [JBREM-187] - Better HTTP 1.1 stack support for HTTP
    invoker</para>

    <para>* [JBREM-201] - Remove dependency from JBossSerialization</para>

    <para></para>

    <para>** Bug</para>

    <para>* [JBREM-127] - RMI Invoker will not bind to specified
    address</para>

    <para>* [JBREM-192] - distro contains samples in src and examples
    directory</para>

    <para>* [JBREM-193] - HTTPClientInvoker doesn't call getErrorStream() on
    HttpURLConnection when an error response code is returned</para>

    <para>* [JBREM-194] - multiplex performance tests hang</para>

    <para>* [JBREM-202] - getUnmarshaller always calls Class.forName operation
    for creating Unmarshallers</para>

    <para>* [JBREM-203] - rmi server invoker hangs if custom
    unmarshaller</para>

    <para>* [JBREM-205] - Spurious java.net.SocketException: Connection reset
    error logging</para>

    <para>* [JBREM-210] - InvokerLocator should be insensitive to parameter
    order</para>

    <para></para>

    <para>** Task</para>

    <para>* [JBREM-9] - Fix performance tests</para>

    <para>* [JBREM-33] - Add GET support within HTTP server invoker</para>

    <para>* [JBREM-145] - convert user guide from MS word doc to
    docbook</para>

    <para>* [JBREM-182] - Socket timeout too short (and better error
    message)</para>

    <para>* [JBREM-183] - keep alive support for http invoker</para>

    <para>* [JBREM-196] - reducde the number of retries for socket client
    invoker</para>

    <para>* [JBREM-204] - create complex remoting example using dynamic proxy
    to endpoint</para>

    <para>* [JBREM-212] - create transporter implementation</para>

    <para>* [JBREM-213] - allow config of ignoring https host validation (ssl)
    via metadata</para>

    <para></para>

    <para></para>

    <para>** Patch</para>

    <para>* [JBREM-152] - NullPointerException in SocketServerInvoker.stop()
    at line 185.</para>

    <para>* [JBREM-153] - LocalClientInvoker's outlive their useful lifetime,
    causing anomalous behavior</para>

    <para></para>

    <para>Release Notes - JBoss Remoting - Version 1.2.1 final</para>

    <para>** Feature Request</para>

    <para>* [JBREM-161] - Upgrade JRunit to Beta 2</para>

    <para>** Bug</para>

    <para>* [JBREM-147] - Invalid reuse of target location</para>

    <para>* [JBREM-163] - NPE in Mutlicast Detector</para>

    <para>* [JBREM-164] - HTTP Invoker unable to send large amounts of
    data</para>

    <para>* [JBREM-176] - Correct inheritance structure for detectors</para>

    <para>* [JBREM-177] - configuration attribute spelled incorrectly in
    ServerInvokerMBean</para>

    <para>* [JBREM-178] - SocketServerInvoker hanging on Linux</para>

    <para>* [JBREM-179] - socket timeout not being set properly</para>

    <para>** Task</para>

    <para>* [JBREM-156] - Better exception handling within socket server
    invoker</para>

    <para>* [JBREM-158] - Clean up test cases</para>

    <para>* [JBREM-162] - add version to the remoting jar</para>

    <para>Release Notes - JBoss Remoting - Version 1.2.0 final</para>

    <para>** Feature Request</para>

    <para>* [JBREM-8] - Ability to stream files via remoting</para>

    <para>* [JBREM-22] - Manipulation of the client proxy interceptor
    stack</para>

    <para>* [JBREM-24] - Allow for specific network interface bindings</para>

    <para>* [JBREM-27] - Support for HTTP/HTTPS proxy</para>

    <para>* [JBREM-35] - Servlet Invoker - counterpart to HTTP Invoker (runs
    within web container)</para>

    <para>* [JBREM-43] - custom socket factories</para>

    <para>* [JBREM-46] - Connection failure callback</para>

    <para>* [JBREM-87] - Add handler metadata to detection messages</para>

    <para>* [JBREM-93] - Callback handler returning a generic Object</para>

    <para>* [JBREM-94] - callback server specific implementation</para>

    <para>* [JBREM-109] - Add support for JaasSecurityDomain within SSL
    support</para>

    <para>* [JBREM-122] - need log4j.xml in examples</para>

    <para>** Bug</para>

    <para>* [JBREM-58] - Bug with multiple callback handler registered with
    same server</para>

    <para>* [JBREM-64] - Need MarshalFactory to produce new instance per get
    request</para>

    <para>* [JBREM-84] - Duplicate Connector shutdown using same server
    invoker</para>

    <para>* [JBREM-92] - in-VM push callbacks don't work</para>

    <para>* [JBREM-97] - Won't compile under JDK 1.5</para>

    <para>* [JBREM-108] - can not set bind address and port for rmi and
    http(s)</para>

    <para>* [JBREM-114] - getting callbacks for a callback handler always
    returns null</para>

    <para>* [JBREM-125] - can not configure transport, port, or host for the
    stream server</para>

    <para>* [JBREM-131] - invoker registry not update if server invoker
    changes locator</para>

    <para>* [JBREM-134] - can not remove callback listeners from multiple
    callback servers</para>

    <para>* [JBREM-137] - Invalid RemoteClientInvoker reference maintained by
    InvokerRegistry after invoker disconnect()</para>

    <para>* [JBREM-141] - bug connecting client invoker when client detects
    that previously used one is disconnected</para>

    <para>* [JBREM-143] - NetworkRegistry should not be required for detector
    to run on server side</para>

    <para>** Task</para>

    <para>* [JBREM-11] - Create seperate JBoss Remoting module in CVS</para>

    <para>* [JBREM-20] - break out remoting into two seperate projects</para>

    <para>* [JBREM-34] - Need to add configuration properties for HTTP server
    invoker</para>

    <para>* [JBREM-39] - start connector on new thread</para>

    <para>* [JBREM-55] - Clean up Callback implementation</para>

    <para>* [JBREM-57] - Remove use of InvokerRequest in favor of Callback
    object</para>

    <para>* [JBREM-62] - update UnifiedInvoker to use remote marshall
    loading</para>

    <para>* [JBREM-67] - Add ability to set ThreadPool via
    configuration</para>

    <para>* [JBREM-98] - remove isDebugEnabled() within code as is now
    depricated</para>

    <para>* [JBREM-101] - Fix serialization versioning between releases of
    remoting</para>

    <para>* [JBREM-104] - Release JBossRemoting 1.1.0</para>

    <para>* [JBREM-110] - create jboss-remoting-client.jar</para>

    <para>* [JBREM-113] - Convert remote tests to use JRunit instead of
    distributed test framework</para>

    <para>* [JBREM-123] - update detection samples</para>

    <para>* [JBREM-128] - standardize address and port binding configuration
    for all transports</para>

    <para>* [JBREM-130] - updated wiki for checkout and build</para>

    <para>* [JBREM-132] - write test case for JBREM-131</para>

    <para>* [JBREM-133] - Document use of Client (as a session object)</para>

    <para>* [JBREM-135] - Remove ClientInvokerAdapter</para>

    <para>** Reactor Event</para>

    <para>* [JBREM-65] - move callback specific classes into new callback
    package</para>

    <para>* [JBREM-111] - pass socket's output/inputstream directly to
    marshaller/unmarshaller</para>

    <para>Release Notes - JBoss Remoting - Version 1.0.2 final</para>

    <para>** Bug</para>

    <para>* [JBREM-36] - performance tests fail for http transports</para>

    <para>* [JBREM-66] - Race condition on startup</para>

    <para>* [JBREM-82] - Bad warning in Connector.</para>

    <para>* [JBREM-88] - HTTP invoker only binds to localhost</para>

    <para>* [JBREM-89] - HTTPUnMarshaller finishing read early</para>

    <para>* [JBREM-90] - HTTP header values not being picked up on the http
    invoker server</para>

    <para>** Task</para>

    <para>* [JBREM-70] - Clean up build.xml. Fix .classpath and .project for
    eclipse</para>

    <para>* [JBREM-83] - Updated Invocation marshalling to support standard
    payloads</para>

    <para>Release Notes - JBoss Remoting - Version 1.0.1 final</para>

    <para>** Feature Request</para>

    <para>* [JBREM-54] - Need access to HTTP response headers</para>

    <para>** Bug</para>

    <para>* [JBREM-1] - Thread.currentThread().getContextClassLoader() is
    wrong</para>

    <para>* [JBREM-31] - Exception handling in http server invoker</para>

    <para>* [JBREM-32] - HTTP Invoker - check for threading issues</para>

    <para>* [JBREM-50] - Need ability to set socket timeout on socket client
    invoker</para>

    <para>* [JBREM-59] - Pull callback collection is unbounded - possible Out
    of Memory</para>

    <para>* [JBREM-60] - Incorrect usage of debug level logging</para>

    <para>* [JBREM-61] - Possible RMI exception semantic regression</para>

    <para>** Task</para>

    <para>* [JBREM-15] - merge UnifiedInvoker from remoting branch</para>

    <para>* [JBREM-30] - Better integration for registering invokers with
    MBeanServe</para>

    <para>* [JBREM-37] - backport to 4.0 branch before 1.0.1 final
    release</para>

    <para>* [JBREM-56] - Add Callback object instead of using
    InvokerRequest</para>

    <para>** Reactor Event</para>

    <para>* [JBREM-51] - defining marshaller on remoting client</para>

    <para></para>

    <para>Release Notes - JBoss Remoting - Version 1.0.1 beta</para>

    <para></para>

    <para>** Bug</para>

    <para>* [JBREM-19] - Try to reconnect on connection failure within socket
    invoker</para>

    <para>* [JBREM-25] - Deadlock in InvokerRegistry</para>

    <para></para>

    <para>** Feature Request</para>

    <para>* [JBREM-12] - Support for call by value</para>

    <para>* [JBREM-26] - Ability to use MBeans as handlers</para>

    <para></para>

    <para>** Task</para>

    <para>* [JBREM-3] - Fix Asyn invokers - currently not operable</para>

    <para>* [JBREM-4] - Added test for throwing exception on server
    side</para>

    <para>* [JBREM-5] - Socket invokers needs to be fixed</para>

    <para>* [JBREM-16] - Finish HTTP Invoker</para>

    <para>* [JBREM-17] - Add CannotConnectException to all transports</para>

    <para>* [JBREM-18] - Backport remoting from HEAD to 4.0 branch</para>

    <para></para>

    <para></para>

    <para>** Reactor Event</para>

    <para>* [JBREM-23] - Refactor Connector so can configure transports</para>

    <para>* [JBREM-29] - Over load invoke() method in Client so metadata not
    required</para>

    <para></para>
  </chapter>
</book>