public NodeInstance readNodeInstance(
      MarshallerReaderContext context,
      NodeInstanceContainer nodeInstanceContainer,
      WorkflowProcessInstance processInstance)
      throws IOException {
    JBPMMessages.ProcessInstance.NodeInstance _node =
        (JBPMMessages.ProcessInstance.NodeInstance) context.parameterObject;

    NodeInstanceImpl nodeInstance = readNodeInstanceContent(_node, context, processInstance);

    nodeInstance.setNodeId(_node.getNodeId());
    nodeInstance.setNodeInstanceContainer(nodeInstanceContainer);
    nodeInstance.setProcessInstance(
        (org.jbpm.workflow.instance.WorkflowProcessInstance) processInstance);
    nodeInstance.setId(_node.getId());

    switch (_node.getContent().getType()) {
      case COMPOSITE_CONTEXT_NODE:
      case DYNAMIC_NODE:
        if (_node.getContent().getComposite().getVariableCount() > 0) {
          Context variableScope =
              ((org.jbpm.process.core.Process)
                      ((org.jbpm.process.instance.ProcessInstance) processInstance).getProcess())
                  .getDefaultContext(VariableScope.VARIABLE_SCOPE);
          VariableScopeInstance variableScopeInstance =
              (VariableScopeInstance)
                  ((CompositeContextNodeInstance) nodeInstance).getContextInstance(variableScope);
          for (JBPMMessages.Variable _variable :
              _node.getContent().getComposite().getVariableList()) {
            try {
              Object _value = ProtobufProcessMarshaller.unmarshallVariableValue(context, _variable);
              variableScopeInstance.internalSetVariable(_variable.getName(), _value);
            } catch (ClassNotFoundException e) {
              throw new IllegalArgumentException(
                  "Could not reload variable " + _variable.getName());
            }
          }
        }
        for (JBPMMessages.ProcessInstance.NodeInstance _instance :
            _node.getContent().getComposite().getNodeInstanceList()) {
          context.parameterObject = _instance;
          readNodeInstance(context, (CompositeContextNodeInstance) nodeInstance, processInstance);
        }

        for (JBPMMessages.ProcessInstance.ExclusiveGroupInstance _excl :
            _node.getContent().getComposite().getExclusiveGroupList()) {
          ExclusiveGroupInstance exclusiveGroupInstance = new ExclusiveGroupInstance();
          ((org.jbpm.process.instance.ProcessInstance) processInstance)
              .addContextInstance(ExclusiveGroup.EXCLUSIVE_GROUP, exclusiveGroupInstance);
          for (Long nodeInstanceId : _excl.getGroupNodeInstanceIdList()) {
            NodeInstance groupNodeInstance = processInstance.getNodeInstance(nodeInstanceId);
            if (groupNodeInstance == null) {
              throw new IllegalArgumentException(
                  "Could not find node instance when deserializing exclusive group instance: "
                      + nodeInstanceId);
            }
            exclusiveGroupInstance.addNodeInstance(groupNodeInstance);
          }
        }
        break;
      case FOR_EACH_NODE:
        for (JBPMMessages.ProcessInstance.NodeInstance _instance :
            _node.getContent().getForEach().getNodeInstanceList()) {
          context.parameterObject = _instance;
          readNodeInstance(context, (ForEachNodeInstance) nodeInstance, processInstance);
        }
        break;
      case EVENT_SUBPROCESS_NODE:
        for (JBPMMessages.ProcessInstance.NodeInstance _instance :
            _node.getContent().getComposite().getNodeInstanceList()) {
          context.parameterObject = _instance;
          readNodeInstance(context, (EventSubProcessNodeInstance) nodeInstance, processInstance);
        }
        break;
      default:
        // do nothing
    }

    return nodeInstance;
  }
  @Test
  public void testPersistenceVariables()
      throws NamingException, NotSupportedException, SystemException, IllegalStateException,
          RollbackException, HeuristicMixedException, HeuristicRollbackException {
    MyEntity myEntity = new MyEntity("This is a test Entity with annotation in fields");
    MyEntityMethods myEntityMethods =
        new MyEntityMethods("This is a test Entity with annotations in methods");
    MyEntityOnlyFields myEntityOnlyFields =
        new MyEntityOnlyFields(
            "This is a test Entity with annotations in fields and without accesors methods");
    MyVariableSerializable myVariableSerializable =
        new MyVariableSerializable("This is a test SerializableObject");
    EntityManager em = ((EntityManagerFactory) ctx.getBean("myEmf")).createEntityManager();

    em.getTransaction().begin();
    em.persist(myEntity);
    em.persist(myEntityMethods);
    em.persist(myEntityOnlyFields);
    em.getTransaction().commit();
    em.close();

    log.info("---> get bean jpaSingleSessionCommandService");
    StatefulKnowledgeSession service =
        (StatefulKnowledgeSession) ctx.getBean("jpaSingleSessionCommandService");

    int sessionId = service.getId();
    log.info("---> created SingleSessionCommandService id: " + sessionId);

    log.info("### Starting process ###");
    Map<String, Object> parameters = new HashMap<String, Object>();
    parameters.put("x", "SomeString");
    parameters.put("y", myEntity);
    parameters.put("m", myEntityMethods);
    parameters.put("f", myEntityOnlyFields);
    parameters.put("z", myVariableSerializable);
    WorkflowProcessInstance processInstance =
        (WorkflowProcessInstance) service.startProcess("com.sample.ruleflow", parameters);
    log.info("Started process instance {}", processInstance.getId());

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

    EntityManagerFactory emf = (EntityManagerFactory) ctx.getBean("myEmf");

    //        List< ? > result = emf.createEntityManager().createQuery( "select i from
    // VariableInstanceInfo i" ).getResultList();
    //        assertEquals( 5,
    //                      result.size() );
    log.info("### Retrieving process instance ###");

    /*        Environment env = KnowledgeBaseFactory.newEnvironment();
            env.set( EnvironmentName.ENTITY_MANAGER_FACTORY,
                     emf );
            env.set( EnvironmentName.TRANSACTION_MANAGER,
                     ctx.getBean( "txManager" ) );
            env.set( EnvironmentName.OBJECT_MARSHALLING_STRATEGIES,
                     new ObjectMarshallingStrategy[]{
                                                                      //  new JPAPlaceholderResolverStrategy(env),
                                                                      new SerializablePlaceholderResolverStrategy( ClassObjectMarshallingStrategyAcceptor.DEFAULT )
                                                                    } );
    */
    final Environment env = (Environment) ctx.getBean("env2");
    KnowledgeStoreService kstore = (KnowledgeStoreService) ctx.getBean("kstore1");
    KnowledgeBase kbase1 = (KnowledgeBase) ctx.getBean("kbase1");
    service = kstore.loadStatefulKnowledgeSession(sessionId, kbase1, null, env);

    processInstance = (WorkflowProcessInstance) service.getProcessInstance(processInstance.getId());
    assertNotNull(processInstance);

    assertNotNull(processInstance);
    assertEquals("SomeString", processInstance.getVariable("x"));
    assertEquals(
        "This is a test Entity with annotation in fields",
        ((MyEntity) processInstance.getVariable("y")).getTest());
    assertEquals(
        "This is a test Entity with annotations in methods",
        ((MyEntityMethods) processInstance.getVariable("m")).getTest());
    assertEquals(
        "This is a test Entity with annotations in fields and without accesors methods",
        ((MyEntityOnlyFields) processInstance.getVariable("f")).test);
    assertEquals(
        "This is a test SerializableObject",
        ((MyVariableSerializable) processInstance.getVariable("z")).getText());
    assertNull(processInstance.getVariable("a"));
    assertNull(processInstance.getVariable("b"));
    assertNull(processInstance.getVariable("c"));

    service.dispose();
  }