docs: @Override
      synchronized public JmsJcaSession createSession(boolean transacted)
                      throws ResourceException, IllegalStateException, SIException,
                      SIErrorException {
  
          if (TraceComponent.isAnyTracingEnabled() && TRACE.isEntryEnabled()) {
              SibTr.entry(this, TRACE, "createSession", new Object[] { Boolean
                              .valueOf(transacted) });
          }
  
          JmsJcaSessionImpl session;
  
          if (connectionClosed) {
              throw new IllegalStateException(NLS.getFormattedMessage(
                                                                      ("ILLEGAL_STATE_CWSJR1085"),
                                                                      new Object[] { "createSession" }, null));
          }
  
          // If the firstSessionCached is true and the thread it was created on is different
          // to the current thread this method is called on then change the cached boolean
          // and delete the session as we don't want access to it
          // PK57931 also remove the cached session if the current tx is different to the one 
          // at session create time.
          // If we are not running in was the blow away the cached connection too.
          if (firstSessionCached &&
              ((!(Thread.currentThread().equals(_connectionCreateThread) && isCurrentUOW(_connectionCreateUOW)))
              || (!isRunningInWAS())))
          {
              if (TraceComponent.isAnyTracingEnabled() && TRACE.isDebugEnabled())
                  SibTr.debug(TRACE, "clearing first session");
              firstSessionCached = false;
              _connectionCreateUOW = null;
              _connectionCreateThread = null;
              //remove the session
              //it should be the only one in the set, but check first
              if (_sessions.size() == 1)
              {
                  final Iterator iterator = _sessions.iterator();
                  final Object object = iterator.next();
                  if (!(object instanceof JmsJcaSessionImpl)) {
                      throw new ResourceAdapterInternalException(NLS
                                      .getFormattedMessage(("EXCEPTION_RECEIVED_CWSJR1083"),
                                                           new Object[] { "createSession",
                                                                         object.getClass().getName(),
                                                                         getClass().getName() }, null));
                  }
                  session = (JmsJcaSessionImpl) object;
                  session.close(false);
  
                  _sessions.clear();
              }
              else
              {
                  throw new ResourceAdapterInternalException(NLS
                                  .getFormattedMessage(("EXCEPTION_RECEIVED_CWSJR1082"),
                                                       new Object[] { "createSession",
                                                                     "" + _sessions.size() }, null));
              }
          }
  
          // If this is the first call to this method we can return the session
          // that was created before (which should be the only session in the
          // set). We should also be on the same thread as we have reset the cached value
          // above if we weren't
          if (firstSessionCached)
          {
              if (TraceComponent.isAnyTracingEnabled() && TRACE.isDebugEnabled()) {
                  SibTr.debug(
                              TRACE,
                              "Using the first session that was created as part of the createConnection process");
              }
  
              if (_sessions.size() != 1) {
                  throw new ResourceAdapterInternalException(NLS
                                  .getFormattedMessage(("EXCEPTION_RECEIVED_CWSJR1082"),
                                                       new Object[] { "createSession",
                                                                     "" + _sessions.size() }, null));
              }
  
              final Iterator iterator = _sessions.iterator();
              final Object object = iterator.next();
              if (!(object instanceof JmsJcaSessionImpl)) {
                  throw new ResourceAdapterInternalException(NLS
                                  .getFormattedMessage(("EXCEPTION_RECEIVED_CWSJR1083"),
                                                       new Object[] { "createSession",
                                                                     object.getClass().getName(),
                                                                     getClass().getName() }, null));
              }
              firstSessionCached = false;
              _connectionCreateUOW = null;
              _connectionCreateThread = null;
              session = (JmsJcaSessionImpl) object;
  
          } else {
  
              // We have already returned the initial session so we should create
              // a new session here.
              if (TraceComponent.isAnyTracingEnabled() && TRACE.isDebugEnabled()) {
                  SibTr
                                  .debug(this, TRACE,
                                         "We have already used the first session... creating a new one");
              }
  
              // Feature 169626.14
              if (_connectionFactory.isManaged()) {
  
                  // True if we aren using container managed authentication
                  boolean containerAuth = false;
  
                  // The containter managed authentication alias (only relevant if containerAuth is true)
                  String containerAlias = null;
  
                  try
                  {
  
                      ConnectionManager cm = _connectionFactory.getConnectionManager();
  
                      // Obtain authentication data in case an exception is thrown. This data is then used to give a more 
                      // meaningful error message. The information is obtained now as it may be altered later on. This is 
                      // only valid when running inside WAS.
                      if (isRunningInWAS())
                      {
  
                          if (cm instanceof com.ibm.ws.jca.adapter.WSConnectionManager)
                          {
  
                              ResourceRefInfo info = ((com.ibm.ws.jca.adapter.WSConnectionManager) cm).getResourceRefInfo();
                              containerAuth = info.getAuth() == com.ibm.ws.javaee.dd.common.ResourceRef.AUTH_CONTAINER;
                              for (Property loginConfigProp : info.getLoginPropertyList())
                                  if ("DefaultPrincipalMapping".equals(loginConfigProp.getName()))
                                      containerAlias = loginConfigProp.getValue();
                          }
                      }
  
                      final Object object = cm.allocateConnection(
                                                                  _connectionFactory
                                                                                  .getManagedConnectionFactory(),
                                                                  _requestInfo);
  
                      if (!(object instanceof JmsJcaSessionImpl)) {
  
                          throw new ResourceAdapterInternalException(NLS
                                          .getFormattedMessage(
                                                               ("EXCEPTION_RECEIVED_CWSJR1084"),
                                                               new Object[] {
                                                                             "createSession",
                                                                             object.getClass().getName(),
                                                                             JmsJcaSessionImpl.class
                                                                                             .getName() }, null));
  
                      }
  
                      session = (JmsJcaSessionImpl) object;
  
                  } catch (final ResourceException exception)
                  {
  
                      FFDCFilter.processException(exception, CLASS_NAME
                                                             + ".createSession", FFDC_PROBE_1, this);
  
                      Throwable cause = exception.getCause();
  
                      // This section will look at the cause of an exception thrown while creating a connection. If the cause
                      // is a security based exeption (SIAuthenticationException or SINotAuthorizedException) then a new 
                      // exception is created to supply the user with more information.
  
                      // pnickoll: We would like to pass the "cause" as a linked exception to the following exceptions
                      if (isRunningInWAS())
                      {
                          if (cause instanceof SIAuthenticationException)
                          {
                              SIAuthenticationException authentEx = null;
                              if (containerAuth)
                              {
                                  if (containerAlias != null && !containerAlias.isEmpty()) {
                                      authentEx = new SIAuthenticationException(NLS.getFormattedMessage("CONTAINER_AUTHENTICATION_EXCEPTION_1073",
                                                                                                        new Object[] { containerAlias, }, null));
                                  } else {
                                      authentEx = new SIAuthenticationException(NLS.getString("AUTHENTICATION_EXCEPTION_1077"));
                                  }
                              }
                              else
                              {
                                  authentEx = new SIAuthenticationException(NLS.getFormattedMessage("APPLICATION_AUTHENTICATION_EXCEPTION_1074",
                                                                                                    new Object[] { _connectionFactory.getUserName() }, null));
                              }
  
                              throw authentEx;
                          }
                          else if (cause instanceof SINotAuthorizedException)
                          {
                              if (containerAuth)
                              {
                                  if (containerAlias == null)
                                  {
                                      throw new SINotAuthorizedException(NLS.getString("CONTAINER_AUTHORIZATION_EXCEPTION_1075"));
                                  }
                              }
                              else
                              {
                                  String userName = _connectionFactory.getUserName();
                                  if ((userName == null) || ("".equals(userName)))
                                  {
                                      throw new SINotAuthorizedException(NLS.getString("CONTAINER_AUTHORIZATION_EXCEPTION_1076"));
                                  }
                              }
                          }
                      }
  
                      if (cause instanceof SIException)
                      {
                          throw (SIException) cause;
                      }
                      else if (cause instanceof SIErrorException)
                      {
                          throw (SIErrorException) cause;
                      }
  
                      throw exception;
                  }
  
                  // The coreConnection could have been recreated during allocateConnection
                  // if we had to create a new ManagedConnection. So reset the coreConnection
                  // for this JmsJcaConnection if the two are different. Different means that
                  // one is not Equivalent to the other which means different userid or different
                  // physical connection
                  SICoreConnection managedConnectionsCoreConnection = session.getManagedConnection().getCoreConnection();
                  if (!managedConnectionsCoreConnection.isEquivalentTo(_coreConnection))
                  {
                      if (TraceComponent.isAnyTracingEnabled() && TRACE.isDebugEnabled()) {
                          SibTr.debug(this, TRACE, "New ManagedConnections coreConnection is not equivalent to our _coreConnection");
                      }
                      try
                      {
                          // We are closing the connection here for completeness. The fact that createSession
                          // has driven us to determine that clonedconnection from this _coreConnection is now
                          // closed will typically mean all conversations on the physcial connection are closed.
                          // To stop a possible issue with this _coreConnection not being closed we will call
                          // close now just before we overwrite it below. From the javadoc of close, calling close
                          // on a already closed connection should have not effect, but we will catch all exceptions
                          // to be safe.
                          _coreConnection.close(false);
                      } catch (Exception e)
                      {
                          // No FFDC needed
                          if (TraceComponent.isAnyTracingEnabled() && TRACE.isDebugEnabled()) {
                              SibTr.debug(this, TRACE, "Exception caught while closing _coreConnection that we are replacing: " + e);
                          }
                      }
  
                      // clone the connection so that the JMSJcaConnection object uses a different
                      // conversation to the mangedConnection, this is so the managedConnection can
                      // control close/destroy etc without impacting the conversation doing the 
                      // jms connection/session work.
                      _coreConnection = managedConnectionsCoreConnection.cloneConnection();
                      // Now reset the SIcoreConnection in the requestInfo to later calls to
                      //  createSession will pass in the new coreConnection to base further
                      //  clones on.
                      _requestInfo.setSICoreConnection(_coreConnection);
                  }
              }
              else
              {
                  session = new JmsJcaSessionImpl();
              }
  
              session.setParentConnection(this);
              _sessions.add(session);
  
          }
  
          session.setTransacted(transacted);
  
          if (TraceComponent.isAnyTracingEnabled() && TRACE.isEntryEnabled()) {
              SibTr.exit(this, TRACE, "createSession", session);
          }
  
          return session;
  
      }