Am 26.08.2012 05:51, schrieb Andrew Yinger:
marcel: here is some more information.
The server has a
  e.printStackTrace();
in XmlNotPortable.java
can you provide that output please as well?

To simplify I have removed the reflection code in XmlNotPortable.java and have 
added a logging output.
Can you please do a svn update and try your testing with this and provide me 
the result?

Thank you
Marcel

here is the stack trace i'm seeing that says it's a server-side error
(note the "location=[XmlNotPortable]"):

     [junit] Caused by: errorCode=user.query.invalid message=#exported
Sorry, can't access, query syntax of
'/xmlBlaster/key[messageType='MSG_TYPE']' is wrong :
XmlBlasterException errorCode=[resource.configuration]
serverSideException=true location=[XmlNotPortable] message=[#exported
Can't process XPath expression
'/xmlBlaster/key[messageType='MSG_TYPE']' :
java.lang.reflect.InvocationTargetException] [See URL
http://www.xmlblaster.org/xmlBlaster/doc/requirements/admin.errorcodes.listing.html#resource.configuration]
     [junit]    at
org.xmlBlaster.util.XmlBlasterException.parseByteArr(XmlBlasterException.java:677)
     [junit]    at
org.xmlBlaster.util.xbformat.MsgInfo.getException(MsgInfo.java:589)
     [junit]    at
org.xmlBlaster.util.protocol.RequestReplyExecutor.receiveReply(RequestReplyExecutor.java:538)
     [junit]    at
org.xmlBlaster.client.protocol.socket.SocketCallbackImpl.run(SocketCallbackImpl.java:225)
     [junit]    at java.lang.Thread.run(Thread.java:662)



(i know that xpath syntax is correct, and it only happens when a lot
messages subscriptions are processed on the server)

on the client, i am testing subscription (using xpath) by doing
something like this in a unit test:

                int quantity = 90;
                final List<MessageContainer<String>> msgs = new
ArrayList<MessageContainer<String>>(quantity);
                // here, we use custom client code to subscripe using XPATH
expression: "/xmlBlaster/key[messageType='MSG_TYPE']"
                String subId = 
newVectorsClient.subscribeToMessageType("MSG_TYPE",
new MessagingClientCallback<String>()
                                {
                                        public void 
processSubscribedMessage(MessageContainer<String>
msg) throws IOException
                                          {
                                                // producer
                                                synchronized (this)
                                                {
                                                        msgs.add(msg);
                                                        notify();
                                                }
                                          }
                                });
                Thread.sleep(200);
                for (int i=0; i < quantity; i++)
                        setClient.publishMessageType("MSG_TYPE", "["+i+"]" + 
MSG_CONTENT);

                // consumer (here we wait to make sure we received all 90 msgs)
                synchronized (this)
                {
                        while (msgs.size() != quantity)
                                wait(10); // wait until async. producer 
finished...
                }
                // check it out
                assertTrue("msgs size should have been " + quantity, 
msgs.size() == quantity);
                newVectorsClient.unsubscribe(subId);


the problem occurs less frequently with version 2.1.0, but i can still
get it to occur by publishing a flood (90) of messages.

i think that maybe the synchronization should be even more
conservative in XmlNotPortable.getNodeSetFromXPath.  starting around
line 111, maybe something like:

             synchronized(XmlNotPortable.class) {
                Object myxpath = null;
                if (method_newXPath == null) {
                   clazz_XPathFactory =
java.lang.Class.forName("javax.xml.xpath.XPathFactory");
                   Class[] paramCls = new Class[0];
                   Object[] params = new Object[0];
                   java.lang.reflect.Method method =
clazz_XPathFactory.getMethod("newInstance", paramCls);
                   instance_XPathFactory =
method.invoke(clazz_XPathFactory, params);
                   method_newXPath =
clazz_XPathFactory.getMethod("newXPath", paramCls);

                   clazz_XPath =
java.lang.Class.forName("javax.xml.xpath.XPath");

                   Class clazz_XPathConstants =
java.lang.Class.forName("javax.xml.xpath.XPathConstants");
                   clazz_QName =
java.lang.Class.forName("javax.xml.namespace.QName");
                   java.lang.reflect.Field field =
clazz_XPathConstants.getDeclaredField("NODESET");
                   field_NODESET = field.get(null);
                   paramCls_StringDocument = new Class[] {
                                    java.lang.String.class,
                                    java.lang.Object.class, //
org.w3c.dom.Document.class,
                                    clazz_QName };
                }
                myxpath = method_newXPath.invoke(instance_XPathFactory,
new Object[0]);
                Object[] params = new Object[] { expression, document,
field_NODESET };
                java.lang.reflect.Method method_evaluate =
clazz_XPath.getMethod("evaluate", paramCls_StringDocument);
                final org.w3c.dom.NodeList nodes =
(org.w3c.dom.NodeList)method_evaluate.invoke(myxpath, params);

                final int length = nodes.getLength();
                return new java.util.Enumeration() {
                   int i=0;
                   public boolean hasMoreElements() {
                      return i<length;
                   }
                   public Object nextElement() {
                      i++;
                      return nodes.item(i-1);
                   }
                };
             }



thanks for looking into this,
andrew




---------- Forwarded message ----------
From: Andrew Yinger <[email protected]>
Date: Sat, Aug 25, 2012 at 10:07 PM
Subject: Re: [xmlblaster] server side exception: Can't process XPath expression
To: Marcel Ruff <[email protected]>
Cc: xmlblaster <[email protected]>


with version 2.1.0 of the server, i still (although rarely) see the
server-side error.  it seems to be encountered only during unit
testing, when many simultaneous publish/subscribe events are
triggered.  is it possible that there is an XPathFactory instance
somewhere else that is not properly synchronized?  (i am not positive
that the error is caused by an XPathFactory synchronization issue --
i'm just basing that diagnosis on earlier post regarding sporadic,
invalid, server-side xpath expression errors).

regards,
andrew


On Sat, Aug 25, 2012 at 2:07 AM, Marcel Ruff <[email protected]> wrote:
Am 24.08.2012 05:01, schrieb Andrew Yinger:

i believe this issue was identified before, but i occasionally see a
server-side exception that starts off like:

     errorCode=user.query.invalid message=#exported Sorry, can't access,
query syntax of
     ....
     XmlBlasterException errorCode=[resource.configuration]
serverSideException=true location=[XmlNotPortable]
      message=[#exported Can't process XPath expression .....


it was first suggested that this was a parsing issue -- a possible xml
parser library conflict.  (i have verified that i do *not* have any
extraneous xml parsing libs in my 'java\lib\endorsed' directory.)

later, a user noticed that a similar error was happening during unit
testing, and that it was a bug on the server:

The issues are:
1. The null check (method_newXPath == null) is outside the
synchronization block. Thread A and thread B could both pass through
the null check at the same time. Thread A will create the xpath
objects while B waits. Then thread B will go through and recreate
xpath objects while A is using them.

2. XPathFactory is, in general, not thread-safe (see
http://java.sun.com/javase/6/docs/api/javax/xml/xpath/XPathFactory.html),
and a method on that object is invoked outside the synchro block.
In the current code it looks like this:

             Object xpath = null;
             synchronized(XmlNotPortable.class) {
                if (method_newXPath == null) {
                   clazz_XPathFactory =
java.lang.Class.forName("javax.xml.xpath.XPathFactory");
                   Class[] paramCls = new Class[0];
                   Object[] params = new Object[0];
                   java.lang.reflect.Method method =
clazz_XPathFactory.getMethod("newInstance", paramCls);
                   instance_XPathFactory = method.invoke(clazz_XPathFactory,
params);
                   method_newXPath = clazz_XPathFactory.getMethod("newXPath",
paramCls);

                   clazz_XPath =
java.lang.Class.forName("javax.xml.xpath.XPath");

                   Class clazz_XPathConstants =
java.lang.Class.forName("javax.xml.xpath.XPathConstants");
                   clazz_QName =
java.lang.Class.forName("javax.xml.namespace.QName");
                   java.lang.reflect.Field field =
clazz_XPathConstants.getDeclaredField("NODESET");
                   field_NODESET = field.get(null);
                   paramCls_StringDocument = new Class[] {
                                    java.lang.String.class,
                                    java.lang.Object.class, //
org.w3c.dom.Document.class,
                                    clazz_QName };
                }
                xpath = method_newXPath.invoke(instance_XPathFactory, new
Object[0]);
             }

so it seems to be correctly synchronized, or do I overlook your issue?

Thank you
Marcel

has this bug been fixed?  if so, what version should i be using now?
(i am currently using xmlBlaster version 1.6.2 2007-12-03
'Openroads'.)

a response to this ongoing issue would be greatly appreciated, as it
is impacting our automated unit tests.


thanks,
andrew yinger




--
Marcel Ruff
http://www.xmlBlaster.org
http://watchee.net
Phone: +49 7551 309371

Reply via email to