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 <andrew.yinger at gmail.com>
Date: Sat, Aug 25, 2012 at 10:07 PM
Subject: Re: [xmlblaster] server side exception: Can't process XPath expression
To: Marcel Ruff <mr at marcelruff.info>
Cc: xmlblaster <xmlblaster at server.xmlblaster.org>
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 <mr at marcelruff.info> 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