@Test
  public void testPersistenceSubProcess() {
    KieSession service = (KieSession) ctx.getBean("jpaSingleSessionCommandService2");

    int sessionId = service.getId();

    RuleFlowProcessInstance processInstance =
        (RuleFlowProcessInstance) service.startProcess("org.drools.test.ProcessSubProcess");
    log.info("Started process instance {}", processInstance.getId());
    long processInstanceId = processInstance.getId();

    TestWorkItemHandler handler = TestWorkItemHandler.getInstance();
    WorkItem workItem = handler.getWorkItem();
    assertNotNull(workItem);
    service.dispose();

    final Environment env = (Environment) ctx.getBean("env");
    /*Environment env = KnowledgeBaseFactory.newEnvironment();
    env.set( EnvironmentName.ENTITY_MANAGER_FACTORY,
             ctx.getBean( "myEmf" ) );
    env.set( EnvironmentName.TRANSACTION_MANAGER,
             ctx.getBean( "txManager" ) );
    */
    KieStoreServices kstore = (KieStoreServices) ctx.getBean("kstore1");
    KieBase kbase1 = (KieBase) ctx.getBean("kb_persistence");
    service = kstore.loadKieSession(sessionId, kbase1, null, env);

    processInstance = (RuleFlowProcessInstance) service.getProcessInstance(processInstanceId);
    assertNotNull(processInstance);

    Collection<NodeInstance> nodeInstances = processInstance.getNodeInstances();
    assertEquals(1, nodeInstances.size());
    SubProcessNodeInstance subProcessNodeInstance =
        (SubProcessNodeInstance) nodeInstances.iterator().next();
    long subProcessInstanceId = subProcessNodeInstance.getProcessInstanceId();
    RuleFlowProcessInstance subProcessInstance =
        (RuleFlowProcessInstance) service.getProcessInstance(subProcessInstanceId);
    assertNotNull(subProcessInstance);
    service.dispose();

    service = kstore.loadKieSession(sessionId, kbase1, null, env);
    service.getWorkItemManager().completeWorkItem(workItem.getId(), null);
    service.dispose();

    service = kstore.loadKieSession(sessionId, kbase1, null, env);
    subProcessInstance = (RuleFlowProcessInstance) service.getProcessInstance(subProcessInstanceId);
    assertNull(subProcessInstance);

    processInstance = (RuleFlowProcessInstance) service.getProcessInstance(processInstanceId);
    assertNull(processInstance);
    service.dispose();
  }
  @Test
  public void testPersistenceSubProcess() {
    setUp();

    Properties properties = new Properties();
    properties.setProperty("drools.commandService", SingleSessionCommandService.class.getName());
    properties.setProperty(
        "drools.processInstanceManagerFactory", JPAProcessInstanceManagerFactory.class.getName());
    properties.setProperty(
        "drools.workItemManagerFactory", JPAWorkItemManagerFactory.class.getName());
    properties.setProperty(
        "drools.processSignalManagerFactory", JPASignalManagerFactory.class.getName());
    properties.setProperty("drools.timerService", JpaJDKTimerService.class.getName());
    SessionConfiguration config = new SessionConfiguration(properties);

    RuleBase ruleBase = RuleBaseFactory.newRuleBase();
    Package pkg = getProcessSubProcess();
    ruleBase.addPackage(pkg);

    SingleSessionCommandService service = new SingleSessionCommandService(ruleBase, config, env);
    int sessionId = service.getSessionId();
    StartProcessCommand startProcessCommand = new StartProcessCommand();
    startProcessCommand.setProcessId("org.drools.test.TestProcess");
    RuleFlowProcessInstance processInstance =
        (RuleFlowProcessInstance) service.execute(startProcessCommand);
    System.out.println("Started process instance " + processInstance.getId());
    long processInstanceId = processInstance.getId();

    TestWorkItemHandler handler = TestWorkItemHandler.getInstance();
    WorkItem workItem = handler.getWorkItem();
    assertNotNull(workItem);
    service.dispose();

    service = new SingleSessionCommandService(sessionId, ruleBase, config, env);
    GetProcessInstanceCommand getProcessInstanceCommand = new GetProcessInstanceCommand();
    getProcessInstanceCommand.setProcessInstanceId(processInstanceId);
    processInstance = (RuleFlowProcessInstance) service.execute(getProcessInstanceCommand);
    assertNotNull(processInstance);

    Collection<NodeInstance> nodeInstances = processInstance.getNodeInstances();
    assertEquals(1, nodeInstances.size());
    SubProcessNodeInstance subProcessNodeInstance =
        (SubProcessNodeInstance) nodeInstances.iterator().next();
    long subProcessInstanceId = subProcessNodeInstance.getProcessInstanceId();
    getProcessInstanceCommand = new GetProcessInstanceCommand();
    getProcessInstanceCommand.setProcessInstanceId(subProcessInstanceId);
    RuleFlowProcessInstance subProcessInstance =
        (RuleFlowProcessInstance) service.execute(getProcessInstanceCommand);
    assertNotNull(subProcessInstance);
    service.dispose();

    service = new SingleSessionCommandService(sessionId, ruleBase, config, env);
    CompleteWorkItemCommand completeWorkItemCommand = new CompleteWorkItemCommand();
    completeWorkItemCommand.setWorkItemId(workItem.getId());
    service.execute(completeWorkItemCommand);
    service.dispose();

    service = new SingleSessionCommandService(sessionId, ruleBase, config, env);
    getProcessInstanceCommand = new GetProcessInstanceCommand();
    getProcessInstanceCommand.setProcessInstanceId(subProcessInstanceId);
    subProcessInstance = (RuleFlowProcessInstance) service.execute(getProcessInstanceCommand);
    assertNull(subProcessInstance);

    getProcessInstanceCommand = new GetProcessInstanceCommand();
    getProcessInstanceCommand.setProcessInstanceId(processInstanceId);
    processInstance = (RuleFlowProcessInstance) service.execute(getProcessInstanceCommand);
    assertNull(processInstance);
    service.dispose();
  }
  protected NodeInstanceImpl readNodeInstanceContent(
      JBPMMessages.ProcessInstance.NodeInstance _node,
      MarshallerReaderContext context,
      WorkflowProcessInstance processInstance)
      throws IOException {
    NodeInstanceImpl nodeInstance = null;
    NodeInstanceContent _content = _node.getContent();
    switch (_content.getType()) {
      case RULE_SET_NODE:
        nodeInstance = new RuleSetNodeInstance();
        ((RuleSetNodeInstance) nodeInstance)
            .setRuleFlowGroup(_content.getRuleSet().getRuleFlowGroup());
        if (_content.getRuleSet().getTimerInstanceIdCount() > 0) {
          List<Long> timerInstances = new ArrayList<Long>();
          for (Long _timerId : _content.getRuleSet().getTimerInstanceIdList()) {
            timerInstances.add(_timerId);
          }
          ((RuleSetNodeInstance) nodeInstance).internalSetTimerInstances(timerInstances);
        }

        if (_content.getRuleSet().getMapEntryCount() > 0) {
          Map<String, FactHandle> factInfo = new HashMap<String, FactHandle>();

          for (TextMapEntry entry : _content.getRuleSet().getMapEntryList()) {
            factInfo.put(entry.getName(), new DefaultFactHandle(entry.getValue()));
          }

          ((RuleSetNodeInstance) nodeInstance).setFactHandles(factInfo);
        }
        break;
      case HUMAN_TASK_NODE:
        nodeInstance = new HumanTaskNodeInstance();
        ((HumanTaskNodeInstance) nodeInstance)
            .internalSetWorkItemId(_content.getHumanTask().getWorkItemId());
        if (_content.getHumanTask().getTimerInstanceIdCount() > 0) {
          List<Long> timerInstances = new ArrayList<Long>();
          for (Long _timerId : _content.getHumanTask().getTimerInstanceIdList()) {
            timerInstances.add(_timerId);
          }
          ((HumanTaskNodeInstance) nodeInstance).internalSetTimerInstances(timerInstances);
        }
        break;
      case WORK_ITEM_NODE:
        nodeInstance = new WorkItemNodeInstance();
        ((WorkItemNodeInstance) nodeInstance)
            .internalSetWorkItemId(_content.getWorkItem().getWorkItemId());
        if (_content.getWorkItem().getTimerInstanceIdCount() > 0) {
          List<Long> timerInstances = new ArrayList<Long>();
          for (Long _timerId : _content.getWorkItem().getTimerInstanceIdList()) {
            timerInstances.add(_timerId);
          }
          ((WorkItemNodeInstance) nodeInstance).internalSetTimerInstances(timerInstances);
        }
        break;
      case SUBPROCESS_NODE:
        nodeInstance = new SubProcessNodeInstance();
        ((SubProcessNodeInstance) nodeInstance)
            .internalSetProcessInstanceId(_content.getSubProcess().getProcessInstanceId());
        if (_content.getSubProcess().getTimerInstanceIdCount() > 0) {
          List<Long> timerInstances = new ArrayList<Long>();
          for (Long _timerId : _content.getSubProcess().getTimerInstanceIdList()) {
            timerInstances.add(_timerId);
          }
          ((SubProcessNodeInstance) nodeInstance).internalSetTimerInstances(timerInstances);
        }
        break;
      case MILESTONE_NODE:
        nodeInstance = new MilestoneNodeInstance();
        if (_content.getMilestone().getTimerInstanceIdCount() > 0) {
          List<Long> timerInstances = new ArrayList<Long>();
          for (Long _timerId : _content.getMilestone().getTimerInstanceIdList()) {
            timerInstances.add(_timerId);
          }
          ((MilestoneNodeInstance) nodeInstance).internalSetTimerInstances(timerInstances);
        }
        break;
      case TIMER_NODE:
        nodeInstance = new TimerNodeInstance();
        ((TimerNodeInstance) nodeInstance).internalSetTimerId(_content.getTimer().getTimerId());
        break;
      case EVENT_NODE:
        nodeInstance = new EventNodeInstance();
        break;
      case JOIN_NODE:
        nodeInstance = new JoinInstance();
        if (_content.getJoin().getTriggerCount() > 0) {
          Map<Long, Integer> triggers = new HashMap<Long, Integer>();
          for (JBPMMessages.ProcessInstance.NodeInstanceContent.JoinNode.JoinTrigger _join :
              _content.getJoin().getTriggerList()) {
            triggers.put(_join.getNodeId(), _join.getCounter());
          }
          ((JoinInstance) nodeInstance).internalSetTriggers(triggers);
        }
        break;
      case COMPOSITE_CONTEXT_NODE:
        nodeInstance = new CompositeContextNodeInstance();

        if (_content.getComposite().getTimerInstanceIdCount() > 0) {
          List<Long> timerInstances = new ArrayList<Long>();
          for (Long _timerId : _content.getComposite().getTimerInstanceIdList()) {
            timerInstances.add(_timerId);
          }
          ((CompositeContextNodeInstance) nodeInstance).internalSetTimerInstances(timerInstances);
        }
        break;
      case FOR_EACH_NODE:
        nodeInstance = new ForEachNodeInstance();
        break;
      case DYNAMIC_NODE:
        nodeInstance = new DynamicNodeInstance();
        if (_content.getComposite().getTimerInstanceIdCount() > 0) {
          List<Long> timerInstances = new ArrayList<Long>();
          for (Long _timerId : _content.getComposite().getTimerInstanceIdList()) {
            timerInstances.add(_timerId);
          }
          ((CompositeContextNodeInstance) nodeInstance).internalSetTimerInstances(timerInstances);
        }
        break;
      case STATE_NODE:
        nodeInstance = new StateNodeInstance();
        if (_content.getState().getTimerInstanceIdCount() > 0) {
          List<Long> timerInstances = new ArrayList<Long>();
          for (Long _timerId : _content.getState().getTimerInstanceIdList()) {
            timerInstances.add(_timerId);
          }
          ((CompositeContextNodeInstance) nodeInstance).internalSetTimerInstances(timerInstances);
        }
        break;
      case EVENT_SUBPROCESS_NODE:
        nodeInstance = new EventSubProcessNodeInstance();

        if (_content.getComposite().getTimerInstanceIdCount() > 0) {
          List<Long> timerInstances = new ArrayList<Long>();
          for (Long _timerId : _content.getComposite().getTimerInstanceIdList()) {
            timerInstances.add(_timerId);
          }
          ((CompositeContextNodeInstance) nodeInstance).internalSetTimerInstances(timerInstances);
        }
        break;
      default:
        throw new IllegalArgumentException("Unknown node type: " + _content.getType());
    }
    return nodeInstance;
  }