11 Replies Latest reply on Oct 24, 2007 12:45 PM by Meghana Joglekar

    bpws.getVariableData as predicate is not supported?

    Meghana Joglekar Novice

      JBPM throws following exception while evaluating expression using bpws.getVariableData in predicate -

      2007-09-10 11:24:13,233 DEBUG [org.jbpm.bpel.graph.basic.assign.FromVariable] evaluating query '/ns9:GetItemsByQueryResponse/ns9:return[bpws:getVariableData("index")]/ns9:genericItem/ns9:itemID' for 'Token(/primary)'
      2007-09-10 11:24:13,264 DEBUG [org.jbpm.bpel.graph.scope.FaultActionHandler] handling fault exception: org.jbpm.bpel.graph.exe.ScopeInstance@13fb60f[name=global,token=/,state=ScopeState[performingPrimaryActivity=0],id=0]
      org.jbpm.bpel.graph.exe.BpelFaultException: org.jbpm.bpel.graph.exe.FaultInstance@82bb3d[name={http://schemas.xmlsoap.org/ws/2004/03/business-process/}subLanguageExecutionFault,id=0]
       at org.jbpm.bpel.sublang.xpath.XPathQueryEvaluator.evaluate(XPathQueryEvaluator.java:62)
       at org.jbpm.bpel.graph.basic.assign.FromVariable.extract(FromVariable.java:65)
      


      It seems queries can be 'GetVariableDataFunction' or 'Pure XPath'...but I thought this would be a common case where inside while loop user would want to iterate over one record at a time.

      Are there plans to support this? Shall I enter JIRA issue?

      Thank you,
      Meghana.

        • 1. Re: bpws.getVariableData as predicate is not supported?
          Alejandro Guizar Master

          In early committee drafts of BPEL 2, the variable variant of from-spec and to-spec did not allow access to the variables or the BPEL functions. This is the currently implemented behavior.

          The BPEL 2 standard (i.e. final version) does allow access to the variables and the functions. Since BPEL 1.1 does not specify the XPath evaluation context, either behavior is valid.

          If you'd like, file a Jira issue for changing the behavior of the variable variant of from-spec and to-spec to adhere to the BPEL 2 standard. This is relatively easy to do and will possibly be included in jBPM BPEL 1.1.GA.

          • 2. Re: bpws.getVariableData as predicate is not supported?
            Meghana Joglekar Novice

            Thank you for your reply.

            I will file JIRA issue for this. However we need to support this for our current BPEL process. Is there a workaround that you can suggest?

            Thanks,
            Meghana

            • 3. Re: bpws.getVariableData as predicate is not supported?
              Meghana Joglekar Novice

              Hello Alex,

              I modified query.functions.xml to resemble expressions.functions.xml.

              <?xml version="1.0" encoding="UTF-8"?>
              <functionContext class="org.jaxen.XPathFunctionContext"
               xmlns:bpel11="http://schemas.xmlsoap.org/ws/2003/03/business-process/"
               xmlns:bpel2="http://schemas.xmlsoap.org/ws/2004/03/business-process/">
               <function name="bpel11:getVariableData" class="org.jbpm.bpel.sublang.xpath.GetVariableDataFunction" />
               <function name="bpel11:getVariableProperty" class="org.jbpm.bpel.sublang.xpath.GetVariablePropertyFunction" />
               <function name="bpel2:getVariableProperty" class="org.jbpm.bpel.sublang.xpath.GetVariablePropertyFunction" />
              </functionContext>


              But my 'getVariableData' still does not get resolved :( I thought jaxen would take care of it once the functions are registered but the problem is when it gets to 'GetVariableDataFunction', it loses the context. In that class, I see this code -
              // find variable definition
               String variableName = StringFunction.evaluate(variableArg, nav);
               ScopeVariableContext variableContext = (ScopeVariableContext) context.getContextSupport()
               .getVariableContext();
               VariableDefinition variable = variableContext.getVariableDefinition(variableName);
              


              But in my case, the context is SimpleVariableContext and it is empty. How do I pass on the correct context? Does that mean XPathQueryEvaluator's overridden 'getContext' method does not provide back correct context to Jaxen?

              I would really appreciate if you can assist me here a little. This is a showstopper for us.

              I am interested in fixing this asap and providing it back to JBPM community. I don't know the process but I think this is a basic functionality inside while loop so other users can benefit from it as well.

              Thanks,
              Meghana


              • 4. Re: bpws.getVariableData as predicate is not supported?
                Meghana Joglekar Novice

                Here is what I had to do to get it working.

                1. Change query.functions.xml as shown above.
                2. Added overloaded method in QueryEvaluator and XPathQueryEvaluator

                public Object evaluate(Node contextNode, Token token) {
                 try {
                
                 this.setVariableContext( new ScopeVariableContext(token));
                 this.setFunctionContext( functionLibrary);
                 //TODO: if no where else, add method in SetNamespaceContext to add bpws.
                 ((SetNamespaceContext)this.getNamespaceContext()).addNamespace( "bpws", "http://schemas.xmlsoap.org/ws/2003/03/business-process/");
                 List nodeset = selectNodes(contextNode);
                 return narrowToSingleNode(nodeset);
                 }
                 catch (JaxenException e) {
                 throw new BpelFaultException(BpelConstants.FAULT_SUB_LANGUAGE_EXECUTION);
                 }
                 }


                Note: The namespace context did not have 'bpws' prefix which I have hardcoded here, I will get to fixing that hack next. I added a method in SetNamespaceContext to add a namespace at a time if prefix doesn't exist already.

                3. I call this new method in FromVariable.
                value = query.getEvaluator().evaluate((Element) value, token);
                


                4. Jaxen only allows 'number' or 'boolean' in predicate. With my original XPath, it was returning nodeset and getting resolved as boolean 'true'. So I had to wrap my 'getVariableData' call inside XPath 'number' function.
                /ns9:GetItemsByQueryResponse/ns9:return[number(bpws:getVariableData("ForEach_index"))]/ns9:genericItem/ns9:itemID
                


                This got my while loop working.

                Meghana

                • 5. Re: bpws.getVariableData as predicate is not supported?
                  Alejandro Guizar Master

                  Wonderful! I developed roughly the same solution. It is thrilling to see this level of expertise in the community :-)
                  Can you please create a Jira issue and reference this forum topic?

                  • 6. Re: bpws.getVariableData as predicate is not supported?
                    Meghana Joglekar Novice

                    Alex,

                    I debugged some more today because I wanted to get rid off that hack I have put in XPathQueryEvaluator. The problem is my BPEL process is based on 1.1 spec. and JBPM transforms it to 2.0.
                    In the process the converter XSLT removes 'bpws' namespace prefix pointing to 'BPEL 1.1' namespace. There is a comment that says on finding extension data, the transformer will add correct namespace but in this case where the extension function is inside predicate, that namespace is never added. Without that hack, my 'getVariableData' is not recognized by Jaxen.

                    Anyway I am going to leave it that way since I need to move on to other tasks. Though not happy about it. I would appreciate if you can suggest something.

                    Thank you,
                    Meghana

                    • 8. Re: bpws.getVariableData as predicate is not supported?
                      Alejandro Guizar Master

                      In case you are interested: AssignReader captures the namespace declarations in scope when parsing the query. When the evaluator is constructed, a SetNamespaceContext is initialized with the namespace declaration and set as the evaluator's namespaceContext property.

                      The function library is an attribute of the XPathQueryEvaluator class and is best set in QueryEvaluator instances by overriding the createFunctionContext method:

                      protected FunctionContext createFunctionContext() {
                       return functionLibrary;
                       }


                      The VariableContext depends on the token argument. Because multiple tokens could evaluate the same query simultaneously, it is not advisable to set it as the evaluator's variableContext property. Try the following:
                      public Object evaluate(Node contextNode, Token contextToken) {
                       Context context = createContext(contextNode, contextToken);
                       try {
                       List nodeSet = selectNodes(context);
                       return narrowToSingleNode(nodeSet);
                       }
                       catch (JaxenException e) {
                       log.error("query evaluation failed", e);
                       throw new BpelFaultException(BpelConstants.FAULT_SUB_LANGUAGE_EXECUTION);
                       }
                       }
                      
                       private Context createContext(Node contextNode, Token contextToken) {
                       ContextSupport support = new ContextSupport(getNamespaceContext(), getFunctionContext(),
                       new TokenVariableContext(contextToken), getNavigator());
                      
                       Context context = new Context(support);
                       context.setNodeSet(Collections.singletonList(contextNode));
                       return context;
                       }


                      • 9. Re: bpws.getVariableData as predicate is not supported?
                        Meghana Joglekar Novice

                        Thank you for correcting my XPathQueryEvaluator. I have made that change now.
                        However it is not going to solve my missing namespace problem because when that new SetNamespaceContext is created while parsing the query based on current element, the namespace iterator itself is missing 'bpws' entry. So I went in to check xslt converter and saw that it skips BPEL 1.1 declaration. I tried putting it back with error and then I stopped working on it since I had to move on.

                        Thanks,
                        Meghana.

                        • 10. Re: bpws.getVariableData as predicate is not supported?
                          Alejandro Guizar Master

                          The loss of the BPEL 1.1 namespace declaration was fixed as part of BPEL-175. This fix will also be delivered in v1.1.GA.

                          • 11. Re: bpws.getVariableData as predicate is not supported?
                            Meghana Joglekar Novice

                            Hello Alex,

                            I have come accross a similar case where I get 'SimpleVariableContext' in GetVariableDataFunction's evaluate(arg) method because the I have predicate inside another expression.

                            For example, bpws:getVariableData(name, part, query[bpws:getVariableData()]query contd.)

                            So I have made these changes to GetVariableDataFunction's evaluate(arg1, arg2, arg3) method

                            XPathQueryEvaluator locationEvaluator = XPathEvaluatorFactory.createQueryEvaluator(locationString);
                            
                             //if no where else, add method in SetNamespaceContext to add bpws.
                             ((SetNamespaceContext)support.getNamespaceContext()).addNamespace( "bpws", "http://schemas.xmlsoap.org/ws/2003/03/business-process/");
                            
                             locationEvaluator.setNamespaceContext(support.getNamespaceContext());
                             locationEvaluator.setVariableContext( variableContext);
                             locationEvaluator.setFunctionContext( support.getFunctionContext());
                             /*
                             * in BPEL 1.1, the context node is 'the root of the document fragment
                             * representing the entire part'
                             */
                             Object queryValue = locationEvaluator.evaluate(partValue.getOwnerDocument());
                             log.debug("evaluate : " + queryValue);
                             return queryValue;
                            


                            So you can see I have pretty much repeated the code I put in XPathQueryEvaluator to fix my original problem which started this thread. So a better way would be to call queryEvaluator's evaluate(node, Token) method. But since this is Jaxen's extension class I don't know how to get back Token from Context. If there is a way to do that, please let me know.

                            Also if there is a better of doing this please point that out. I appreciate your help.

                            Thank you,
                            Meghana