[JBoss JIRA] Created: (JBWS-1859) Concurrency issue in building the request handler chain when more than one handler is specified
by Bruce (JIRA)
Concurrency issue in building the request handler chain when more than one handler is specified
-----------------------------------------------------------------------------------------------
Key: JBWS-1859
URL: http://jira.jboss.com/jira/browse/JBWS-1859
Project: JBoss Web Services
Issue Type: Bug
Security Level: Public (Everyone can see)
Components: jbossws-jaxws
Affects Versions: jbossws-2.0.1, jbossws-1.2.1
Reporter: Bruce
>From what I can tell jbossws has concurrency issues in building the request handler chain when more than one handler is specified, and multiple requests are made to the server while it is starting. The problem is that too many copies of the handlers are inserted into the handler chain because more than one thread is building it. This only becomes apparent when one of the handlers is for WS Security. During request handling, the first WS Security handler removes the wsse header, so any subsequent handler throws an exception. The client receives the fault string "This service requires <wsse:Security>, which is missing". The server stack trace:
javax.xml.ws.WebServiceException: org.jboss.ws.core.CommonSOAPFaultException: This service requires <wsse:Security>, which is missing.
at org.jboss.ws.core.jaxws.handler.HandlerChainExecutor.processHandlerFailure(HandlerChainExecutor.java:276)
at org.jboss.ws.core.jaxws.handler.HandlerChainExecutor.handleMessage(HandlerChainExecutor.java:155)
at org.jboss.ws.core.jaxws.handler.HandlerDelegateJAXWS.callRequestHandlerChain(HandlerDelegateJAXWS.java:87)
at org.jboss.ws.core.server.ServiceEndpointInvoker.callRequestHandlerChain(ServiceEndpointInvoker.java:126)
at org.jboss.ws.core.server.ServiceEndpointInvoker.invoke(ServiceEndpointInvoker.java:170)
at org.jboss.wsf.stack.jbws.RequestHandlerImpl.processRequest(RequestHandlerImpl.java:408)
at org.jboss.wsf.stack.jbws.RequestHandlerImpl.handleRequest(RequestHandlerImpl.java:272)
at org.jboss.wsf.stack.jbws.RequestHandlerImpl.doPost(RequestHandlerImpl.java:189)
at org.jboss.wsf.stack.jbws.RequestHandlerImpl.handleHttpRequest(RequestHandlerImpl.java:122)
at org.jboss.wsf.stack.jbws.EndpointServlet.service(EndpointServlet.java:84)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:175)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:74)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
at org.jboss.web.tomcat.tc5.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:156)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
at java.lang.Thread.run(Thread.java:595)
Steps to duplicate
- Create web service that exposes a ping() method, and requires both WS Security and WS Addressing. A customized standard-jaxws-endpoint-config.xml file is required.
- Create a client application that calls ping() every second in a loop
- Start the server
- Once the server initializes, start 2 instances of the client
- Restart the server
- Most of the time the error will start to occur for every request. You may have to restart the server a few time to get the error condition. Sometimes the server is able to initialize successfully. If it is successful, it will stay that way. Even having many clients pounding on the server for hours will not cause the error.
- Once the error condition begins, the server is unable to properly process any more ping requests, even if both clients are stopped, and only one is restarted.
standard-jaxws-endpoint-config.xml addition:
<endpoint-config>
<config-name>WSAddressing + WSSecurity Endpoint</config-name>
<post-handler-chains>
<javaee:handler-chain>
<javaee:protocol-bindings>##SOAP11_HTTP</javaee:protocol-bindings>
<javaee:handler>
<javaee:handler-name>WSAddressing Handler</javaee:handler-name>
<javaee:handler-class>org.jboss.ws.extensions.addressing.jaxws.WSAddressingServerHandler</javaee:handler-class>
</javaee:handler>
<javaee:handler>
<javaee:handler-name>WSSecurity Handler</javaee:handler-name>
<javaee:handler-class>org.jboss.ws.extensions.security.jaxws.WSSecurityHandlerServer</javaee:handler-class>
</javaee:handler>
</javaee:handler-chain>
</post-handler-chains>
</endpoint-config>
I have sample server and client code that you can use, but could not see how to attach it to the bug report.
I was able to prevent the error from occurring with a slight modification to callRequestHandlerChain() in org.jboss.ws.core.jaxws.handler.HandlerDelegateJAXWS. I changed:
if (isInitialized() == false)
{
resolver.initHandlerChain(sepMetaData, HandlerType.PRE, true);
resolver.initHandlerChain(sepMetaData, HandlerType.ENDPOINT, true);
resolver.initHandlerChain(sepMetaData, HandlerType.POST, true);
setInitialized(true);
}
to
if (isInitialized() == false)
{
synchronized(this)
{
if (isInitialized() == false)
{
resolver.initHandlerChain(sepMetaData, HandlerType.PRE, true);
resolver.initHandlerChain(sepMetaData, HandlerType.ENDPOINT, true);
resolver.initHandlerChain(sepMetaData, HandlerType.POST, true);
setInitialized(true);
}
}
}
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
16 years, 9 months
[JBoss JIRA] Created: (JBWS-1861) Exception message could be better: @WebService[portName,serviceName,endpointInterface] MUST NOT be defined on ...
by Johannes Rudolph (JIRA)
Exception message could be better: @WebService[portName,serviceName,endpointInterface] MUST NOT be defined on ...
-----------------------------------------------------------------------------------------------------------------
Key: JBWS-1861
URL: http://jira.jboss.com/jira/browse/JBWS-1861
Project: JBoss Web Services
Issue Type: Feature Request
Security Level: Public (Everyone can see)
Components: jbossws-jaxws
Affects Versions: jbossws-1.2.1
Reporter: Johannes Rudolph
Priority: Trivial
I know this is a trivial case but it would be helpful if the exception message "@WebService[portName,serviceName,endpointInterface] MUST NOT be defined on ..." would be more clear. Perhaps you could change it to "Attributes portName,serviceName and endpointInterface of @WebService are not allowed for use on the endpointInterface" or similar.
If you know the cause of the problem it surely is trivial, but if you don't, you end up looking into the source code which is not the sense of an error message.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
16 years, 9 months
[JBoss JIRA] Created: (JBWS-1863) NAMESPACE_ERR on invoking SOAPBodyImpl SOAPBodyElement addDocument(Document doc) with a document composed of ElementImpl nodes.
by Eddie Waner (JIRA)
NAMESPACE_ERR on invoking SOAPBodyImpl SOAPBodyElement addDocument(Document doc) with a document composed of ElementImpl nodes.
-------------------------------------------------------------------------------------------------------------------------------
Key: JBWS-1863
URL: http://jira.jboss.com/jira/browse/JBWS-1863
Project: JBoss Web Services
Issue Type: Bug
Security Level: Public (Everyone can see)
Components: jbossws-jaxws
Affects Versions: jbossws-1.2.1
Environment: Windows XP. Java version "1.5.0_10". JBossAS 5.0.0.2
Reporter: Eddie Waner
When creating a SOAP response for a web service following the @WebServiceProvider pattern, documents that are composed of ElementImpl nodes rather than ElementNSImpl nodes cause Xerces to throw a NAMESPACE_ERR exception. JBoss WS assumes that nodes coming in on the document are ElementImplNS nodes. If a document composed of ElementImpl nodes is passed to SOAPBodyElement addDocument(Document doc) the qualified name ends up being null in the call to Xerces ElementNSImpl setName(String namespaceURI, String qname). Thus the name space error... See stack trace and detail below.
I ran into this problem using the Castor framework. This framework only creates ElementImpl nodes. I also reproduced the problem with simple cases. See below.
Details:
SOAPBodyImpl
SOAPBodyElement addDocument(Document doc)
creates a soapFactory and begins the copy of elements from the document into the soapBody with the default as deep through soapFactory.createElement(rootElement). In SOAPFactoryImpl createElement(Element domElement, boolean deep) an assumption is made that the element passed in is an ElementNSImpl (has a localName).
SOAPFactoryImpl
...
public SOAPElement createElement(Element domElement, boolean deep) throws SOAPException
{
if (domElement == null)
throw new IllegalArgumentException("Source node cannot be null");
if (domElement instanceof SOAPElement)
return (SOAPElement)domElement;
String localName = domElement.getLocalName();
String prefix = domElement.getPrefix() != null ? domElement.getPrefix() : "";
String nsURI = domElement.getNamespaceURI() != null ? domElement.getNamespaceURI() : "";
...
In the case of an ElementImpl the localName is null as well as the prefix, ElementImpl will have the field name set. Thus when DOMUtils createElement(String localPart, String prefix, String url) is called the localPart == null but the prefix is an empty string.
DOMUtils
...
public static Element createElement(String localPart, String prefix, String uri)
{
Document doc = getOwnerDocument();
if (prefix == null || prefix.length() == 0)
{
log.trace("createElement {" + uri + "}" + localPart);
return doc.createElementNS(uri, localPart);
}
else
{
log.trace("createElement {" + uri + "}" + prefix + ":" + localPart);
return doc.createElementNS(uri, prefix + ":" + localPart);
}
}
...
So the call into Xerces for createElementNS fails on setName(String namespaceURI, String qname) in ElementNSImpl as noted in the comment in the Xerces code:
//NAMESPACE_ERR:
//1. if the qualified name is 'null' it is malformed.
//2. or if the qualifiedName is null and the namespaceURI is different from null,
// We dont need to check for namespaceURI != null, if qualified name is null throw DOMException.
ElementNSImpl.java
private void setName(String namespaceURI, String qname) {
String prefix;
// DOM Level 3: namespace URI is never empty string.
this.namespaceURI = namespaceURI;
if (namespaceURI != null) {
//convert the empty string to 'null'
this.namespaceURI = (namespaceURI.length() == 0) ? null : namespaceURI;
}
int colon1, colon2 ;
//NAMESPACE_ERR:
//1. if the qualified name is 'null' it is malformed.
//2. or if the qualifiedName is null and the namespaceURI is different from null,
// We dont need to check for namespaceURI != null, if qualified name is null throw DOMException.
if(qname == null){
String msg =
DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"NAMESPACE_ERR",
null);
throw new DOMException(DOMException.NAMESPACE_ERR, msg);
}
Stack Trace:
org.w3c.dom.DOMException: NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
at org.apache.xerces.dom.ElementNSImpl.setName(ElementNSImpl.java:105)
at org.apache.xerces.dom.ElementNSImpl.<init>(ElementNSImpl.java:80)
at org.apache.xerces.dom.CoreDocumentImpl.createElementNS(CoreDocumentImpl.java:2076)
at org.jboss.ws.core.utils.DOMUtils.createElement(DOMUtils.java:179)
at org.jboss.ws.core.soap.SOAPElementImpl.<init>(SOAPElementImpl.java:84)
at org.jboss.ws.core.soap.SOAPFactoryImpl.createElement(SOAPFactoryImpl.java:95)
at org.jboss.ws.core.soap.SOAPFactoryImpl.createElement(SOAPFactoryImpl.java:121)
at org.jboss.ws.core.soap.SOAPFactoryImpl.createElement(SOAPFactoryImpl.java:101)
at org.jboss.ws.core.soap.SOAPBodyImpl.addDocument(SOAPBodyImpl.java:97)
at com.hhn.services.hl7.MessageHandler.createResponseSOAPMessage(MessageHandler.java:182)
at com.hhn.services.hl7.MessageHandler.handleMessage(MessageHandler.java:45)
at com.hhn.services.jsr181.HHNProviderTest.invoke(HHNProviderTest.java:97)
at com.hhn.services.jsr181.HHNProviderTest.invoke(HHNProviderTest.java:1)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.jboss.aop.joinpoint.MethodInvocation.invokeTarget(MethodInvocation.java:121)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:110)
at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:166)
at org.jboss.ejb3.interceptor.EJB3InterceptorsInterceptor.invoke(EJB3InterceptorsInterceptor.java:63)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor.invoke(TransactionScopedEntityManagerInterceptor.java:54)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInterceptor.java:47)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:79)
at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:193)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:76)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:62)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at org.jboss.ejb3.tx.NullInterceptor.invoke(NullInterceptor.java:42)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:77)
at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3AuthenticationInterceptor.java:105)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:46)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at org.jboss.ws.integration.jboss50.ServiceEndpointInvokerEJB3.invokeServiceEndpointInstance(ServiceEndpointInvokerEJB3.java:129)
at org.jboss.ws.core.server.AbstractServiceEndpointInvoker.invoke(AbstractServiceEndpointInvoker.java:207)
at org.jboss.ws.core.server.ServiceEndpoint.processRequest(ServiceEndpoint.java:212)
at org.jboss.ws.core.server.ServiceEndpointManager.processRequest(ServiceEndpointManager.java:448)
at org.jboss.ws.core.server.AbstractServiceEndpointServlet.doPost(AbstractServiceEndpointServlet.java:114)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
at org.jboss.ws.core.server.AbstractServiceEndpointServlet.service(AbstractServiceEndpointServlet.java:75)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:231)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:174)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:86)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:238)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:624)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:595)
Test:
boolean createNS = false;
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
document = builder.newDocument();
if(createNS){
Element element = document.createElementNS(null, "Moo");
document.appendChild(element);
}
else
{
// Causes the NAMESPACE_ERR to be thrown
Element element = document.createElement("Moo");
element.appendChild(document.createTextNode(messageType));
}
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
message = messageFactory.createMessage();
SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
SOAPBody body = envelope.getBody();
body.addDocument(document);
Workaround:
For Castor I can use the following to recreate the DOM tree...
...
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(source, domResult = new DOMResult(builder.newDocument()));
...
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
16 years, 9 months