I tried to perform a stress test by making concurrent web service calls, the standalone web service server will keep throwing javax.xml.stream.XMLStreamException.
Is it a bug? Not sure. I will post it to java forum.
If it's a bug. I think it may due to Sun's light weight http server.
I did a very simple experiment:
1. Create a simple web method:
// Calculator.java
package simplews;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
@WebService
public class Calculator {
@WebMethod
public int add(int a, int b) {
return a + b;
}
}
2. Generate web service class by using apt:
D:\>c:\Program Files\java\jdk1.6.0_06\bin"\apt -d . src\simplews\Calculator.java
warning: Annotation types without processors: [javax.xml.bind.annotation.XmlRootElement, javax.xml.bind.annotation.XmlAccessorType, javax.xml.bind.annotation.XmlType, javax.xml.bind.annotation.XmlElement]
1 warning
3. Create my endpoint:
//Main.java
package simplews;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.xml.ws.Endpoint;
public class Main {
private static ArrayBlockingQueue m_arrayBlockingQueue = null;
private static ThreadPoolExecutor m_executor = null;
public static void main(String[] args) {
// create and publish an endpoint
m_arrayBlockingQueue = new ArrayBlockingQueue(10000);
m_executor = new ThreadPoolExecutor(5, 50, 15L, TimeUnit.SECONDS, m_arrayBlockingQueue);
Calculator calculator = new Calculator();
Endpoint endpoint = Endpoint.publish("http://localhost:8080/calculator", calculator);
}
}
4. Create my web service client:
//Main.java
public class Main {
private static int totalThread = 20;
private static int countPerThread = 1000;
private static long sleeptime = 1L;
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
try {
totalThread = Integer.parseInt(args[0]);
} catch (Exception e) {
}
try {
countPerThread = Integer.parseInt(args[1]);
} catch (Exception e) {
}
try {
sleeptime = Long.parseLong(args[2]);
} catch (Exception e) {
}
for (int i = 0; i < totalThread; i++) {
Runnable runnable = new Runnable() {
int count = countPerThread;
public void run() {
while (--count > 0) {
try { // Call Web Service Operation
simplews.CalculatorService service = new simplews.CalculatorService();
simplews.Calculator port = service.getCalculatorPort();
// TODO initialize WS operation arguments here
int arg0 = 5;
int arg1 = 6;
// TODO process result here
int result = port.add(arg0, arg1);
System.out.println(Thread.currentThread().toString() + " | Result = " + result);
Thread.sleep(sleeptime);
} catch (Exception ex) {
// TODO handle custom exceptions here
ex.printStackTrace();
}
}
}
};
Thread thread = new Thread(runnable);
thread.start();
try {
Thread.sleep(sleeptime);
} catch (Exception e) {
}
}
}
}
What I am doing here is to create certain number of threads and keep calling remote web method.
5. Start server
6. Start clients with 10 threads, 100 web service calls per thread and sleep = 1 millis.
Server side will keep throwing:
com.sun.xml.internal.ws.streaming.XMLStreamReaderException: XML reader error: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,2]
Message: The markup in the document preceding the root element must be well-formed.
at com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil.wrapException(XMLStreamReaderUtil.java:242)
at com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil.next(XMLStreamReaderUtil.java:70)
at com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil.nextContent(XMLStreamReaderUtil.java:85)
at com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil.nextElementContent(XMLStreamReaderUtil.java:75)
at com.sun.xml.internal.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:167)
at com.sun.xml.internal.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:149)
at com.sun.xml.internal.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:121)
at com.sun.xml.internal.ws.encoding.SOAPBindingCodec.decode(SOAPBindingCodec.java:280)
at com.sun.xml.internal.ws.transport.http.HttpAdapter.decodePacket(HttpAdapter.java:207)
at com.sun.xml.internal.ws.transport.http.HttpAdapter.access$500(HttpAdapter.java:74)
at com.sun.xml.internal.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:363)
at com.sun.xml.internal.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:175)
at com.sun.xml.internal.ws.transport.http.server.WSHttpHandler.handleExchange(WSHttpHandler.java:100)
at com.sun.xml.internal.ws.transport.http.server.WSHttpHandler.handle(WSHttpHandler.java:77)
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:65)
at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:65)
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:68)
at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:552)
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:65)
at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:524)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:619)
Caused by: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,2]
Message: The markup in the document preceding the root element must be well-formed.
at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next(XMLStreamReaderImpl.java:588)
at com.sun.xml.internal.ws.util.xml.XMLStreamReaderFilter.next(XMLStreamReaderFilter.java:78)
at com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil.next(XMLStreamReaderUtil.java:51)
... 21 more
At the same time, number of loopback connections (by Selector) at server
side will be increased by one per exception! Those loopback connections cannot be released unless restarting application.
The application will halt when the number of leaked connection rearch
server limit (max filedispatcher).
Bug 6712353 is dispatched and pending for fix, I am not sure when the fix can be released.
So, if you plan to use standalone jax-ws, make sure the bug is fixed otherwise you are in trouble. Currently one of our application in production is suffered and we have to detect number of leaked connections and trigger an auto-restart of the application in order to free those leaked connections.
I attached my test code here (NetBeans Project):
http://kentsang77.googlepages.com/SimpleWS.rar
http://kentsang77.googlepages.com/SimpleWSClient.rar
jdk version:
java version "1.6.0_06"
Java(TM) SE Runtime Environment (build 1.6.0_06-b02)
Java HotSpot(TM) 64-Bit Server VM (build 10.0-b22, mixed mode)