public SingleSessionCommandService(
      Integer sessionId, KnowledgeBase kbase, KnowledgeSessionConfiguration conf, Environment env) {
    if (conf == null) {
      conf = new SessionConfiguration();
    }

    this.env = env;

    checkEnvironment(this.env);

    initTransactionManager(this.env);

    // Open the entity manager before the transaction begins.
    PersistenceContext persistenceContext = jpm.getApplicationScopedPersistenceContext();

    boolean transactionOwner = false;
    try {
      transactionOwner = txm.begin();

      registerRollbackSync();

      persistenceContext.joinTransaction();
      initKsession(sessionId, kbase, conf, persistenceContext);

      txm.commit(transactionOwner);
    } catch (RuntimeException re) {
      rollbackTransaction(re, transactionOwner);
      throw re;
    } catch (Exception t1) {
      rollbackTransaction(t1, transactionOwner);
      throw new RuntimeException("Wrapped exception see cause", t1);
    }
  }
  public synchronized <T> T execute(Command<T> command) {
    // Open the entity manager before the transaction begins.
    PersistenceContext persistenceContext = this.jpm.getApplicationScopedPersistenceContext();

    boolean transactionOwner = false;
    try {
      transactionOwner = txm.begin();

      persistenceContext.joinTransaction();
      initKsession(
          this.sessionInfo.getId(),
          this.marshallingHelper.getKbase(),
          this.marshallingHelper.getConf(),
          persistenceContext);

      this.jpm.beginCommandScopedEntityManager();

      registerRollbackSync();

      T result = null;
      if (!(command instanceof DisposeCommand)) {
        result = commandService.execute((GenericCommand<T>) command);
      }

      txm.commit(transactionOwner);

      return result;

    } catch (RuntimeException re) {
      rollbackTransaction(re, transactionOwner);
      throw re;
    } catch (Exception t1) {
      rollbackTransaction(t1, transactionOwner);
      throw new RuntimeException("Wrapped exception see cause", t1);
    } finally {
      if (command instanceof DisposeCommand) {
        commandService.execute((GenericCommand<T>) command);
        this.jpm.dispose();
      }
    }
  }
  public SingleSessionCommandService(
      KnowledgeBase kbase, KnowledgeSessionConfiguration conf, Environment env) {
    if (conf == null) {
      conf = new SessionConfiguration();
    }
    this.env = env;

    checkEnvironment(this.env);

    this.sessionInfo = new SessionInfo();

    initTransactionManager(this.env);

    // create session but bypass command service
    this.ksession = kbase.newStatefulKnowledgeSession(conf, this.env);

    this.kContext = new FixedKnowledgeCommandContext(null, null, null, this.ksession, null);

    this.commandService = new DefaultCommandService(kContext);

    ((AcceptsTimerJobFactoryManager) ((InternalKnowledgeRuntime) ksession).getTimerService())
        .getTimerJobFactoryManager()
        .setCommandService(this);

    this.marshallingHelper = new SessionMarshallingHelper(this.ksession, conf);
    MarshallingConfigurationImpl config =
        (MarshallingConfigurationImpl)
            ((DefaultMarshaller) this.marshallingHelper.getMarshaller())
                .getMarshallingConfiguration();
    config.setMarshallProcessInstances(false);
    config.setMarshallWorkItems(false);

    this.sessionInfo.setJPASessionMashallingHelper(this.marshallingHelper);
    ((InternalKnowledgeRuntime) this.ksession)
        .setEndOperationListener(new EndOperationListenerImpl(this.sessionInfo));

    // Use the App scoped EntityManager if the user has provided it, and it is open.
    // - open the entity manager before the transaction begins.
    PersistenceContext persistenceContext = jpm.getApplicationScopedPersistenceContext();

    boolean transactionOwner = false;
    try {
      transactionOwner = txm.begin();

      registerRollbackSync();

      persistenceContext.joinTransaction();
      persistenceContext.persist(this.sessionInfo);

      txm.commit(transactionOwner);
    } catch (RuntimeException re) {
      rollbackTransaction(re, transactionOwner);
      throw re;
    } catch (Exception t1) {
      rollbackTransaction(t1, transactionOwner);
      throw new RuntimeException("Wrapped exception see cause", t1);
    }

    // update the session id to be the same as the session info id
    ((InternalKnowledgeRuntime) ksession).setId(this.sessionInfo.getId());
  }