docs: public Conversation connect(InetSocketAddress remoteHost,
                                  ConversationReceiveListener receiveListener,
                                  String chainName,
                                  Conversation.ConversationType conversationType)
                      throws SIResourceException
      {
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
              SibTr.entry(this, tc, "connect", new Object[] { remoteHost, receiveListener, chainName, conversationType });
  
          EndPointDescriptor testEndPoint = new HostPortEndPointDescriptor(remoteHost, chainName, conversationType);
          ConnectionDataGroup connGroup;
  
          // Take the monitor of the end point to group map.  This allows us to select or
          // create a new group, safe in the knowledge that no-one else can add a duplicate
          // or remove the group we are interested in.
          synchronized (endPointToGroupMap)
          {
              // See if there is already a connection group for the end point we are interested
              // in, if not create one and add it to the map.
              connGroup = endPointToGroupMap.get(testEndPoint);
  
              // Contemplate issuing a warning if the chain is SSL enabled, we are running in
              // the client container, and the SSL properties file is not available.
              framework.warnIfSSLAndPropertiesFileMissing(chainName);
  
              if (connGroup == null)
              {
                  NetworkConnectionFactory virtualConnectionFactory;
                  try
                  {
                      NetworkTransportFactory transportFactory = framework.getNetworkTransportFactory();
                      virtualConnectionFactory = transportFactory.getOutboundNetworkConnectionFactoryByName(chainName);
  
                      if (virtualConnectionFactory == null)
                      {
                          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                              SibTr.debug(this, tc, "Unknown chain name: " + chainName);
                          throw new SIErrorException(nls.getFormattedMessage("OUTCONNTRACKER_INTERNAL_SICJ0064", null, "OUTCONNTRACKER_INTERNAL_SICJ0064")); // D226223
                      }
  
                      // How often should we heartbeat?
                      // Currently in liberty we dont have an option to configure heartbeat interval and timout 
                      // Hence hard coding to default
                      int heartbeatInterval = JFapChannelConstants.DEFAULT_HEARTBEAT_INTERVAL;
                      int heartbeatTimeout = JFapChannelConstants.DEFAULT_HEARTBEAT_TIMEOUT;
  
                      connGroup = new ConnectionDataGroup(this,
                                      virtualConnectionFactory,
                                      testEndPoint,
                                      conversationsPerConnection,
                                      heartbeatInterval,
                                      heartbeatTimeout);
                      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                          SibTr.debug(this, tc, "created new connection data group: " + connGroup);
                      endPointToGroupMap.put(testEndPoint, connGroup);
                  } catch (FrameworkException frameworkException)
                  {
                      // No FFDC code needed
                      if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled())
                          SibTr.exception(this, tc, frameworkException);
                      throw new SIErrorException(nls.getFormattedMessage("OUTCONNTRACKER_INTERNAL_SICJ0064", null, "OUTCONNTRACKER_INTERNAL_SICJ0064"), frameworkException); // D226223
                  }
              }
  
              // Notify the connection group of our intention to make a connection at some point in
              // the future.  This mechanism is used to prevent an "empty" group from being
              // closed in the interval between us releasing the lock on the endpoint->group map
              // and actually making the connect attempt.  The motivation behind this is to avoid
              // holding the endpoint->group map monitor for the (potentially very long) duration
              // of an connect attempt.
              connGroup.connectionPending();
          }
  
          // Attempt to establish a new conversation.
          Conversation retConversation = connGroup.connect(remoteHost,
                                                           chainName,
                                                           receiveListener,
                                                           conversationType);
  
          if (retConversation != null)
              retConversation.setConversationType(conversationType);
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
              SibTr.exit(this, tc, "connect", retConversation);
          return retConversation;
      }