Latest JBossWS CXF build has broken XTS again
adinn May 30, 2011 8:04 PMHi guys,
I have been working on integrating XTS into AS7 trunk and come across a problem in the CXF release (2.4.0, I believe). It's not a repeat of a previous regression at the code level but conceptually it is a regression. The specifc problem is detailed below. It happened because whoever updatd CXF assumed that wenevr you use WSA you must be invoking a request-reply web service API. That's true as far as the half-baked version of WSA that Sun incorporated into the JaxWS-WSA JSR is concerned -- the one which removed the ability to install/detect WSA headers from the API. But it's no good maoing that assumption in general.
Not only is it quite possible to use WSA with one-way messages in CXF (or, even, in JBossWS native) it is also, for certain purposes, critical to be able to do this. In particular, the WSTX standards on which XTS is based requrie one-way messages which use WSA. So, when a CXF dev adopts this simplifying assumption XTS invariably breaks. This has happened almost every time the CXF version used by JBossWS has been upgraded. So, as well as fixing the problem in the current release I think it is important that we get teh CXF devs to include explicit tests in their tes suite to ensure that it is possible to use WSA with one way messages.
The specific problem I encountered happens during deployment of an endpoint. I have a war file, ws-t11-client.war which contains a web,.xml which declares two servlets
. . . <!-- Client Side Endpoints --> <servlet> <servlet-name>CompletionInitiator</servlet-name> <servlet-class>com.arjuna.webservices11.wsat.sei.CompletionInitiatorPortTypeImpl</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>TerminationParticipant</servlet-name> <servlet-class>com.arjuna.webservices11.wsarjtx.sei.TerminationParticipantPortTypeImpl</servlet-class> <load-on-startup>1</load-on-startup> </servlet> . . .
The first class declared in the web.xml is located under WEB-INF/classes and defined as follows
. . .
@WebService(name = "CompletionInitiatorPortType", targetNamespace = "http://docs.oasis-open.org/ws-tx/wsat/2006/06",
serviceName = "CompletionInitiatorService", portName = "CompletionInitiatorPortType"
)
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@HandlerChain(file="/ws-t_handlers.xml")
@Addressing(required=true)
public class CompletionInitiatorPortTypeImpl
{
@Resource
private WebServiceContext webServiceCtx;
@WebMethod(operationName = "CommittedOperation", action = "http://docs.oasis-open.org/ws-tx/wsat/2006/06/Committed")
@Oneway
@Action(input="http://docs.oasis-open.org/ws-tx/wsat/2006/06/Committed")
public void committedOperation(
@WebParam(name = "Committed", targetNamespace = "http://docs.oasis-open.org/ws-tx/wsat/2006/06", partName = "parameters")
Notification parameters)
{
MessageContext ctx = webServiceCtx.getMessageContext();
. . .
}
@WebMethod(operationName = "AbortedOperation", action = "http://docs.oasis-open.org/ws-tx/wsat/2006/06/Aborted")
@Oneway
@Action(input="http://docs.oasis-open.org/ws-tx/wsat/2006/06/Aborted")
public void abortedOperation(
@WebParam(name = "Aborted", targetNamespace = "http://docs.oasis-open.org/ws-tx/wsat/2006/06", partName = "parameters")
Notification parameters)
{
MessageContext ctx = webServiceCtx.getMessageContext();
. . .
The second class is declared in essentially the same way.
When I deploy the war I get the following output
00:44:38,254 INFO [org.jboss.ws.common.management.DefaultEndpointRegistry] (MSC service thread 1-4) remove: jboss.ws:context=ws-t11-client,endpoint=CompletionInitiator 00:44:38,256 INFO [org.jboss.ws.common.management.DefaultEndpointRegistry] (MSC service thread 1-4) remove: jboss.ws:context=ws-t11-client,endpoint=TerminationParticipant 00:44:38,258 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-4) MSC00001: Failed to start service jboss.deployment.unit."ws-t11-client.war".INSTALL: org.jboss.msc.service.StartException in service jboss.deployment.unit."ws-t11-client.war".INSTALL: Failed to process phase INSTALL of deployment "ws-t11-client.war" at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:121) [jboss-as-server-7.0.0.Beta4-SNAPSHOT.jar:7.0.0.Beta4-SNAPSHOT] at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1675) [jboss-msc-1.0.0.Beta8.jar:1.0.0.Beta8] at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [:1.6.0_21] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [:1.6.0_21] at java.lang.Thread.run(Thread.java:619) [:1.6.0_21] Caused by: javax.xml.ws.WebServiceException: java.lang.NullPointerException at org.apache.cxf.jaxws.EndpointImpl.doPublish(EndpointImpl.java:350) at org.jboss.wsf.stack.cxf.deployment.EndpointImpl.doPublish(EndpointImpl.java:71) at org.apache.cxf.jaxws.EndpointImpl.publish(EndpointImpl.java:239) at org.apache.cxf.jaxws.EndpointImpl.publish(EndpointImpl.java:509) at org.jboss.wsf.stack.cxf.configuration.NonSpringBusHolder.configure(NonSpringBusHolder.java:113) at org.jboss.wsf.stack.cxf.deployment.aspect.BusDeploymentAspect.startDeploymentBus(BusDeploymentAspect.java:109) at org.jboss.wsf.stack.cxf.deployment.aspect.BusDeploymentAspect.start(BusDeploymentAspect.java:132) at org.jboss.as.webservices.deployers.AspectDeploymentProcessor.internalDeploy(AspectDeploymentProcessor.java:78) at org.jboss.as.webservices.deployers.TCCLDeploymentProcessor.deploy(TCCLDeploymentProcessor.java:42) at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:115) [jboss-as-server-7.0.0.Beta4-SNAPSHOT.jar:7.0.0.Beta4-SNAPSHOT] ... 4 more Caused by: java.lang.NullPointerException at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.buildWSAActions(JaxWsServiceFactoryBean.java:547) at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.createOperation(JaxWsServiceFactoryBean.java:620) at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.createInterface(ReflectionServiceFactoryBean.java:903) at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.buildServiceFromClass(ReflectionServiceFactoryBean.java:429) at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.buildServiceFromClass(JaxWsServiceFactoryBean.java:680) at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.initializeServiceModel(ReflectionServiceFactoryBean.java:501) at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.create(ReflectionServiceFactoryBean.java:241) at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.create(JaxWsServiceFactoryBean.java:202) at org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory.createEndpoint(AbstractWSDLBasedEndpointFactory.java:101) at org.apache.cxf.frontend.ServerFactoryBean.create(ServerFactoryBean.java:157) at org.apache.cxf.jaxws.JaxWsServerFactoryBean.create(JaxWsServerFactoryBean.java:192) at org.apache.cxf.jaxws.EndpointImpl.getServer(EndpointImpl.java:433) at org.apache.cxf.jaxws.EndpointImpl.doPublish(EndpointImpl.java:322) ... 13 more
The null pointer exception which causes the problem is in the following code taken from JaxWsServiceFactoryBean.buildWSAActions
Hi guys,
I have been working on integrating XTS into AS7 trunk and come across a problem in the CXF release (2.4.0, I believe). It's not a repeat of a previous regression at the code level but conceptually it is a regression. The specifc problem is detailed below. It happened because whoever updatd CXF assumed that wenevr you use WSA you must be invoking a request-reply web service API. That's true as far as the half-baked version of WSA that Sun incorporated into the JaxWS-WSA JSR is concerned -- the one which removed the ability to install/detect WSA headers from the API. But it's no good maoing that assumption in general.
Not only is it quite possible to use WSA with one-way messages in CXF (or, even, in JBossWS native) it is also, for certain purposes, critical to be able to do this. In particular, the WSTX standards on which XTS is based requrie one-way messages which use WSA. So, when a CXF dev adopts this simplifying assumption XTS invariably breaks. This has happened almost every time the CXF version used by JBossWS has been upgraded. So, as well as fixing the problem in the current release I think it is important that we get teh CXF devs to include explicit tests in their tes suite to ensure that it is possible to use WSA with one way messages.
The specific problem I encountered happens during deployment of an endpoint. I have a war file, ws-t11-client.war which contains a web,.xml which declares two servlets
. . .
<!-- Client Side Endpoints -->
<servlet>
<servlet-name>CompletionInitiator</servlet-name>
<servlet-class>com.arjuna.webservices11.wsat.sei.CompletionInitiatorPortTypeImpl</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>TerminationParticipant</servlet-name>
<servlet-class>com.arjuna.webservices11.wsarjtx.sei.TerminationParticipantPortTypeImpl</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
. . .
The first class declared in the web.xml is located under WEB-INF/classes and defined as follows
. . .
@WebService(name = "CompletionInitiatorPortType", targetNamespace = "http://docs.oasis-open.org/ws-tx/wsat/2006/06",
serviceName = "CompletionInitiatorService", portName = "CompletionInitiatorPortType"
)
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@HandlerChain(file="/ws-t_handlers.xml")
@Addressing(required=true)
public class CompletionInitiatorPortTypeImpl
{
@Resource
private WebServiceContext webServiceCtx;
@WebMethod(operationName = "CommittedOperation", action = "http://docs.oasis-open.org/ws-tx/wsat/2006/06/Committed")
@Oneway
@Action(input="http://docs.oasis-open.org/ws-tx/wsat/2006/06/Committed")
public void committedOperation(
@WebParam(name = "Committed", targetNamespace = "http://docs.oasis-open.org/ws-tx/wsat/2006/06", partName = "parameters")
Notification parameters)
{
MessageContext ctx = webServiceCtx.getMessageContext();
. . .
}
@WebMethod(operationName = "AbortedOperation", action = "http://docs.oasis-open.org/ws-tx/wsat/2006/06/Aborted")
@Oneway
@Action(input="http://docs.oasis-open.org/ws-tx/wsat/2006/06/Aborted")
public void abortedOperation(
@WebParam(name = "Aborted", targetNamespace = "http://docs.oasis-open.org/ws-tx/wsat/2006/06", partName = "parameters")
Notification parameters)
{
MessageContext ctx = webServiceCtx.getMessageContext();
. . .
The second class is declared in essentially the same way.
When I deploy the war I get the following output
00:44:38,254 INFO [org.jboss.ws.common.management.DefaultEndpointRegistry] (MSC service thread 1-4) remove: jboss.ws:context=ws-t11-client,endpoint=CompletionInitiator
00:44:38,256 INFO [org.jboss.ws.common.management.DefaultEndpointRegistry] (MSC service thread 1-4) remove: jboss.ws:context=ws-t11-client,endpoint=TerminationParticipant
00:44:38,258 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-4) MSC00001: Failed to start service jboss.deployment.unit."ws-t11-client.war".INSTALL: org.jboss.msc.service.StartException in service jboss.deployment.unit."ws-t11-client.war".INSTALL: Failed to process phase INSTALL of deployment "ws-t11-client.war"
at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:121) [jboss-as-server-7.0.0.Beta4-SNAPSHOT.jar:7.0.0.Beta4-SNAPSHOT]
at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1675) [jboss-msc-1.0.0.Beta8.jar:1.0.0.Beta8]
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [:1.6.0_21]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [:1.6.0_21]
at java.lang.Thread.run(Thread.java:619) [:1.6.0_21]
Caused by: javax.xml.ws.WebServiceException: java.lang.NullPointerException
at org.apache.cxf.jaxws.EndpointImpl.doPublish(EndpointImpl.java:350)
at org.jboss.wsf.stack.cxf.deployment.EndpointImpl.doPublish(EndpointImpl.java:71)
at org.apache.cxf.jaxws.EndpointImpl.publish(EndpointImpl.java:239)
at org.apache.cxf.jaxws.EndpointImpl.publish(EndpointImpl.java:509)
at org.jboss.wsf.stack.cxf.configuration.NonSpringBusHolder.configure(NonSpringBusHolder.java:113)
at org.jboss.wsf.stack.cxf.deployment.aspect.BusDeploymentAspect.startDeploymentBus(BusDeploymentAspect.java:109)
at org.jboss.wsf.stack.cxf.deployment.aspect.BusDeploymentAspect.start(BusDeploymentAspect.java:132)
at org.jboss.as.webservices.deployers.AspectDeploymentProcessor.internalDeploy(AspectDeploymentProcessor.java:78)
at org.jboss.as.webservices.deployers.TCCLDeploymentProcessor.deploy(TCCLDeploymentProcessor.java:42)
at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:115) [jboss-as-server-7.0.0.Beta4-SNAPSHOT.jar:7.0.0.Beta4-SNAPSHOT]
... 4 more
Caused by: java.lang.NullPointerException
at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.buildWSAActions(JaxWsServiceFactoryBean.java:547)
at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.createOperation(JaxWsServiceFactoryBean.java:620)
at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.createInterface(ReflectionServiceFactoryBean.java:903)
at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.buildServiceFromClass(ReflectionServiceFactoryBean.java:429)
at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.buildServiceFromClass(JaxWsServiceFactoryBean.java:680)
at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.initializeServiceModel(ReflectionServiceFactoryBean.java:501)
at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.create(ReflectionServiceFactoryBean.java:241)
at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.create(JaxWsServiceFactoryBean.java:202)
at org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory.createEndpoint(AbstractWSDLBasedEndpointFactory.java:101)
at org.apache.cxf.frontend.ServerFactoryBean.create(ServerFactoryBean.java:157)
at org.apache.cxf.jaxws.JaxWsServerFactoryBean.create(JaxWsServerFactoryBean.java:192)
at org.apache.cxf.jaxws.EndpointImpl.getServer(EndpointImpl.java:433)
at org.apache.cxf.jaxws.EndpointImpl.doPublish(EndpointImpl.java:322)
... 13 more
The null pointer exception which causes the problem is in the following code taken from JaxWsServiceFactoryBean.buildWSAActions
. . .
if (action == null && addressing != null) {
operation.getInput().addExtensionAttribute(JAXWSAConstants.WSAM_ACTION_QNAME,
inputAction);
operation.getInput().addExtensionAttribute(JAXWSAConstants.WSAW_ACTION_QNAME,
inputAction);
operation.getOutput().addExtensionAttribute(JAXWSAConstants.WSAM_ACTION_QNAME,
computeAction(operation, "Response"));
operation.getOutput().addExtensionAttribute(JAXWSAConstants.WSAW_ACTION_QNAME,
computeAction(operation, "Response"));
} else {
MessageInfo input = operation.getInput();
input.addExtensionAttribute(JAXWSAConstants.WSAM_ACTION_QNAME, inputAction);
if (!StringUtils.isEmpty(action.input())) {
input.addExtensionAttribute(JAXWSAConstants.WSAW_ACTION_QNAME, inputAction);
}
MessageInfo output = operation.getOutput();
if (output != null && !StringUtils.isEmpty(action.output())) {
output.addExtensionAttribute(JAXWSAConstants.WSAW_ACTION_QNAME, action.output());
. . .
The offending line is the one in bold. Notice that in the else clause the result of the getOutput() call is checked ut in the case where addressing is being used it is not checked. Clearly the code is based on the wrong assumption that code using WSA must be employing a request-reply exchange.
This needs a CXF JIRA a san umbrella for an underlying CXF JIRA. I suspect that this is likely to be the first of several problems. It's hard for me to hand over a test case for you to use at the moment as the XTS code is only integrated into AS7 using string and glue. Also, I have limited time to get this integration fixed so I need quick turnaround on a patch here. If you can provide advice on what I need to set up in order to rebuild a patched version of CXF I will happily continue to push on and debug as far as I can.
regards,
Andrew Dinn