public StatefulKnowledgeSession newWorkingMemory() {
    if (this.kagent != null) {
      // if we have an agent always get the rulebase from there
      this.kBase = (InternalKnowledgeBase) this.kagent.getKnowledgeBase();
    }
    this.kBase.readLock();
    try {
      StatefulKnowledgeSession ksession =
          (StatefulKnowledgeSession)
              wmFactory.createWorkingMemory(
                  this.kBase.nextWorkingMemoryCounter(),
                  this.kBase,
                  (SessionConfiguration) this.conf,
                  this.environment);
      StatefulKnowledgeSessionImpl ksessionImpl = (StatefulKnowledgeSessionImpl) ksession;

      // we don't pass the mapped listener wrappers to the session constructor anymore,
      // because they would be ignored anyway, since the wm already contains those listeners

      ((Globals) ksessionImpl.getGlobalResolver()).setDelegate(this.sessionGlobals);

      // copy over the default generated listeners that are used for internal stuff once
      registerSystemListeners(ksessionImpl);
      registerCustomListeners();

      ksessionImpl.setAgendaEventSupport(this.agendaEventSupport);
      ksessionImpl.setRuleRuntimeEventSupport(this.ruleRuntimeEventSupport);
      InternalProcessRuntime processRuntime = ksessionImpl.internalGetProcessRuntime();
      if (processRuntime != null) {
        processRuntime.setProcessEventSupport(this.processEventSupport);
      }

      for (Map.Entry<String, Channel> entry : this.channels.entrySet()) {
        ksession.registerChannel(entry.getKey(), entry.getValue());
      }

      return ksession;
    } finally {
      this.kBase.readUnlock();
    }
  }