JBE created CXF-5231: ------------------------ Summary: NoSuchElementException in ClientFaultConverter when stack trace message contains line breaks Key: CXF-5231 URL: https://issues.apache.org/jira/browse/CXF-5231 Project: CXF Issue Type: Bug Affects Versions: 2.7.6, 2.7.3 Reporter: JBE
On server side, I have enabled those two flags in order to be able to retrieve the full exception in client : {code} Message.FAULT_STACKTRACE_ENABLED -> true Message.EXCEPTION_MESSAGE_CAUSE_ENABLED -> true {code} The problem is that one of the exception message contains a line break "\n" character. Thus when the exception is thrown, here is what I have on client side with version 2.7.6 : {code} java.util.NoSuchElementException at java.util.StringTokenizer.nextToken(StringTokenizer.java:349) at org.apache.cxf.interceptor.ClientFaultConverter.parseStackTrackLine(ClientFaultConverter.java:288) at org.apache.cxf.interceptor.ClientFaultConverter.getCause(ClientFaultConverter.java:279) at org.apache.cxf.interceptor.ClientFaultConverter.setStackTrace(ClientFaultConverter.java:247) at org.apache.cxf.interceptor.ClientFaultConverter.handleMessage(ClientFaultConverter.java:80) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271) at org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:113) at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:69) at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:34) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271) at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:811) at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1590) at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1486) at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1305) at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56) at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:623) at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271) at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:541) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:474) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:377) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:330) at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96) at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134) at com.sun.proxy.$Proxy71.execute(Unknown Source) at com.mycompany.client.WebServiceClient.main(WebServiceClient.java:111) Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: Fault string, and possibly fault code, not set at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:156) at com.sun.proxy.$Proxy71.execute(Unknown Source) at com.mycompany.client.WebServiceClient.main(WebServiceClient.java:111) Caused by: java.util.NoSuchElementException at java.util.StringTokenizer.nextToken(StringTokenizer.java:349) at org.apache.cxf.interceptor.ClientFaultConverter.parseStackTrackLine(ClientFaultConverter.java:288) at org.apache.cxf.interceptor.ClientFaultConverter.getCause(ClientFaultConverter.java:279) at org.apache.cxf.interceptor.ClientFaultConverter.setStackTrace(ClientFaultConverter.java:247) at org.apache.cxf.interceptor.ClientFaultConverter.handleMessage(ClientFaultConverter.java:80) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271) at org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:113) at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:69) at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:34) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271) at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:811) at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1590) at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1486) at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1305) at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56) at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:623) at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271) at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:541) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:474) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:377) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:330) at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96) at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134) ... 2 more {code} After debugging, I can see that in the getCause method of ClientFaultConverter, you are using a StringTokenizer to iterate through different lines. {quote} StringTokenizer st = new StringTokenizer(ss, "\n"); {quote} When it comes to the exception message, we have this kind of string : {quote} Caused by: beginning of the message end of the message first line of stack trace {quote} Thus this piece of code: {code} private Throwable getCause(StringTokenizer st, String firstLine) { // The actual exception class of the cause might be unavailable at the // client -> use a standard throwable to represent the cause. Throwable res = new Throwable(firstLine.substring(firstLine.indexOf(":") + 2)); List<StackTraceElement> stackTraceList = new ArrayList<StackTraceElement>(); while (st.hasMoreTokens()) { String oneLine = st.nextToken(); if (oneLine.startsWith("Caused by:")) { Throwable nestedCause = getCause(st, oneLine); res.initCause(nestedCause); break; } stackTraceList.add(parseStackTrackLine(oneLine)); } StackTraceElement[] stackTraceElement = new StackTraceElement[stackTraceList.size()]; res.setStackTrace(stackTraceList.toArray(stackTraceElement)); return res; } {code} will result in calling "parseStackTrackLine" on element "end of the message" which causes the exception. -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira