blob: e7bb3e9bf244efffb4fa73d4a8f383563d6c3586 [file] [log] [blame]
/*
* Copyright 2006 The Apache Software Foundation.
* Copyright 2006 International Business Machines Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.axis2.jaxws.core.controller;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.activation.DataHandler;
import javax.xml.namespace.QName;
import javax.xml.ws.AsyncHandler;
import javax.xml.ws.Response;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMText;
import org.apache.axiom.om.impl.MTOMConstants;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants.Configuration;
import org.apache.axis2.addressing.AddressingConstants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.OperationClient;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.context.AbstractContext;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.engine.MessageReceiver;
import org.apache.axis2.jaxws.AxisCallback;
import org.apache.axis2.jaxws.BindingProvider;
import org.apache.axis2.jaxws.ExceptionFactory;
import org.apache.axis2.jaxws.core.InvocationContext;
import org.apache.axis2.jaxws.core.MessageContext;
import org.apache.axis2.jaxws.description.OperationDescription;
import org.apache.axis2.jaxws.i18n.Messages;
import org.apache.axis2.jaxws.impl.AsyncListener;
import org.apache.axis2.jaxws.impl.AsyncListenerWrapper;
import org.apache.axis2.jaxws.message.Attachment;
import org.apache.axis2.jaxws.message.Message;
import org.apache.axis2.jaxws.message.MessageException;
import org.apache.axis2.jaxws.message.attachments.AttachmentUtils;
import org.apache.axis2.jaxws.message.factory.MessageFactory;
import org.apache.axis2.jaxws.message.impl.AttachmentImpl;
import org.apache.axis2.jaxws.registry.FactoryRegistry;
import org.apache.axis2.jaxws.util.Constants;
import org.apache.axis2.util.CallbackReceiver;
import org.apache.axis2.util.ThreadContextMigratorUtil;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* The <tt>AxisInvocationController</tt> is an implementation of the
* {@link org.apache.axis2.jaxws.core.controller.InvocationController}
* interface. This implemenation uses the Axis2 engine to drive the
* request to the target service.
*
* For more information on how to invoke this class, please see the
* InvocationController interface comments.
*/
public class AxisInvocationController implements InvocationController {
private static Log log = LogFactory.getLog(AxisInvocationController.class);
/*
* (non-Javadoc)
* @see org.apache.axis2.jaxws.core.controller.InvocationController#invoke(org.apache.axis2.jaxws.core.InvocationContext)
*/
public InvocationContext invoke(InvocationContext ic) {
if (log.isDebugEnabled()) {
log.debug("Invocation pattern: synchronous");
}
// Check to make sure we at least have a valid InvocationContext
// and request MessageContext
if (ic == null) {
throw ExceptionFactory.makeWebServiceException(Messages.getMessage("ICErr1"));
}
if (ic.getRequestMessageContext() == null) {
throw ExceptionFactory.makeWebServiceException(Messages.getMessage("ICErr2"));
}
// Get the request MessageContext
MessageContext requestMsgCtx = ic.getRequestMessageContext();
MessageContext responseMsgCtx = null;
// We need the qname of the operation being invoked to know which
// AxisOperation the OperationClient should be based on.
// Note that the OperationDesc is only set through use of the Proxy. Dispatch
// clients do not use operations, so the operationDesc will be null. In this
// case an anonymous AxisService with anoymouns AxisOperations for the supported
// MEPs will be created; and it is that anonymous operation name which needs to
// be specified
// TODO: Fix this logic once AxisService is created via annoations and not just WSDL
// If ServiceDesc.axisService is null, then we created an Annon Service and operations in
// ServiceDelegate.getServiceClient(), and that is what the service client points to.
// Therefore, we need to use the annonymous operation name in that case, so the anonymous service client will find
// the anonymous AxisOperation on that service.
// This means the ServiceDesc was not build with WSDL, and so there are no Axis objects attached to them
// i.e the OperationDesc.axisOperation == null
QName operationName = getOperationNameToUse(requestMsgCtx, ServiceClient.ANON_OUT_IN_OP);
// TODO: Will the ServiceClient stick around on the InvocationContext
// or will we need some other mechanism of creating this?
// Try to create an OperationClient from the passed in ServiceClient
ServiceClient svcClient = ic.getServiceClient();
OperationClient opClient = createOperationClient(svcClient, operationName);
setupProperties(requestMsgCtx, opClient.getOptions());
if (opClient != null) {
// Get the target endpoint address and setup the TO endpoint
// reference. This tells us where the request is going.
String targetUrl = (String) requestMsgCtx.getProperties().get(
BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
EndpointReference toEPR = new EndpointReference(targetUrl);
opClient.getOptions().setTo(toEPR);
// Get the SOAP Action (if needed)
String soapAction = configureSOAPAction(requestMsgCtx);
opClient.getOptions().setAction(soapAction);
// Use the OperationClient to send the request and put the contents
// of the response in the response MessageContext.
try {
// The MessageContext will contain a Message object with the
// contents that need to be sent. We need to get those contents
// in a form that Axis2 can consume them, an AXIOM SOAPEnvelope.
Message requestMsg = requestMsgCtx.getMessage();
SOAPEnvelope requestOM = (SOAPEnvelope) requestMsg.getAsOMElement();
org.apache.axis2.context.MessageContext axisRequestMsgCtx =
requestMsgCtx.getAxisMessageContext();
axisRequestMsgCtx.setEnvelope(requestOM);
// For now, just take all of the properties that were in the
// JAX-WS MessageContext, and set them on the Axis2 MessageContext.
axisRequestMsgCtx.setProperty(AbstractContext.COPY_PROPERTIES,
Boolean.TRUE);
Map props = axisRequestMsgCtx.getOptions().getProperties();
props.putAll(requestMsgCtx.getProperties());
axisRequestMsgCtx.getOptions().setProperties(props);
if (log.isDebugEnabled()) {
log.debug("Properties: " + axisRequestMsgCtx.getProperties().toString());
}
// Setting the ServiceContext will create the association between
// the OperationClient it's MessageContexts and the
// AxisService/AxisOperation that they are tied to.
axisRequestMsgCtx.setServiceContext(svcClient.getServiceContext());
// Set the Axis2 request MessageContext
opClient.addMessageContext(axisRequestMsgCtx);
//This assumes that we are on the ultimate execution thread
ThreadContextMigratorUtil.performMigrationToContext(Constants.THREAD_CONTEXT_MIGRATOR_LIST_ID, axisRequestMsgCtx);
opClient.execute(true);
ThreadContextMigratorUtil.performContextCleanup(Constants.THREAD_CONTEXT_MIGRATOR_LIST_ID, axisRequestMsgCtx);
// Collect the response MessageContext and envelope
org.apache.axis2.context.MessageContext axisResponseMsgCtx =
opClient.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
//This assumes that we are on the ultimate execution thread
ThreadContextMigratorUtil.performMigrationToThread(Constants.THREAD_CONTEXT_MIGRATOR_LIST_ID, axisResponseMsgCtx);
SOAPEnvelope rspEnvelope = axisResponseMsgCtx.getEnvelope();
Message responseMsg = null;
if (rspEnvelope != null) {
responseMsg = createMessageFromOM(rspEnvelope);
}
// Setup the response MessageContext
responseMsgCtx = new MessageContext(axisResponseMsgCtx);
responseMsgCtx.setMessage(responseMsg);
//FIXME: This should be revisited when we re-work the MTOM support.
//This destroys performance by forcing a double pass through the message.
//If attachments are found, we must find all of the OMText nodes and
//replace them with <xop:include> elements so they can be processed
//correctly by JAXB.
if (axisResponseMsgCtx.getProperty(MTOMConstants.ATTACHMENTS) != null) {
Message response = responseMsgCtx.getMessage();
response.setMTOMEnabled(true);
ArrayList<OMText> binaryNodes = AttachmentUtils.findBinaryNodes(
axisResponseMsgCtx.getEnvelope());
if (binaryNodes != null) {
Iterator<OMText> itr = binaryNodes.iterator();
while (itr.hasNext()) {
OMText node = itr.next();
OMElement xop = AttachmentUtils.makeXopElement(node);
node.getParent().addChild(xop);
node.detach();
Attachment a = new AttachmentImpl((DataHandler) node.getDataHandler(),
node.getContentID());
response.addAttachment(a);
}
}
}
} catch (AxisFault e) {
throw ExceptionFactory.makeWebServiceException(e);
} catch (MessageException e) {
throw ExceptionFactory.makeWebServiceException(e);
}
// Set the response MessageContext on the InvocationContext
ic.setResponseMessageContext(responseMsgCtx);
}
return ic;
}
/*
* (non-Javadoc)
* @see org.apache.axis2.jaxws.core.controller.InvocationController#invokeOneWay(org.apache.axis2.jaxws.core.InvocationContext)
*/
public void invokeOneWay(InvocationContext ic) {
if (log.isDebugEnabled()) {
log.debug("Invocation pattern: one-way");
}
// Check to make sure we at least have a valid InvocationContext
// and request MessageContext
if (ic == null) {
throw ExceptionFactory.makeWebServiceException("Cannot invoke; InvocationContext was null");
}
if (ic.getRequestMessageContext() == null) {
throw ExceptionFactory.makeWebServiceException("Cannot invoke; request MessageContext was null");
}
// Setup the MessageContext for the response
MessageContext requestMsgCtx = ic.getRequestMessageContext();
//TODO: Need to figure out whether or not we need to create the response
//MessageContext here and whether or not handlers need to be run for
//one-way invocations.
MessageContext responseMsgCtx = new MessageContext();
ic.setResponseMessageContext(responseMsgCtx);
// Try to create an OperationClient from the passed in ServiceClient
ServiceClient svcClient = ic.getServiceClient();
// We need the qname of the operation being invoked to know which
// AxisOperation the OperationClient should be based on.
// Note that the OperationDesc is only set through use of the Proxy. Dispatch
// clients do not use operations, so the operationDesc will be null. In this
// case an anonymous AxisService with anoymouns AxisOperations for the supported
// MEPs will be created; and it is that anonymous operation name which needs to
// be specified
// TODO: Fix this logic once AxisService is created via annoations and not just WSDL
// If ServiceDesc.axisService is null, then we created an Annon Service and operations in
// ServiceDelegate.getServiceClient(), and that is what the service client points to.
// Therefore, we need to use the annonymous operation name in that case, so the anonymous service client will find
// the anonymous AxisOperation on that service.
// This means the ServiceDesc was not build with WSDL, and so there are no Axis objects attached to them
// i.e the OperationDesc.axisOperation == null
QName operationName = getOperationNameToUse(requestMsgCtx, ServiceClient.ANON_OUT_ONLY_OP);
OperationClient opClient = createOperationClient(svcClient, operationName);
setupProperties(requestMsgCtx, opClient.getOptions());
if (opClient != null) {
// Get the target endpoint address and setup the TO endpoint
// reference. This tells us where the request is going.
String targetUrl = (String) requestMsgCtx.getProperties().get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
EndpointReference toEPR = new EndpointReference(targetUrl);
opClient.getOptions().setTo(toEPR);
// Get the SOAP Action (if needed)
String soapAction = configureSOAPAction(requestMsgCtx);
opClient.getOptions().setAction(soapAction);
// Use the OperationClient to send the request.
Message responseMsg = null;
org.apache.axis2.context.MessageContext axisResponseMsgCtx = null;
try {
// We need to prepare the contents of the Message from the request
// MessageContext to be sent
Message requestMsg = requestMsgCtx.getMessage();
SOAPEnvelope requestOM = (SOAPEnvelope) requestMsg.getAsOMElement();
org.apache.axis2.context.MessageContext axisRequestMsgCtx =
requestMsgCtx.getAxisMessageContext();
// For now, just take all of the properties that were in the
// JAX-WS MessageContext, and set them on the Axis2 MessageContext.
axisRequestMsgCtx.setProperty(AbstractContext.COPY_PROPERTIES,
Boolean.TRUE);
Map props = axisRequestMsgCtx.getOptions().getProperties();
props.putAll(requestMsgCtx.getProperties());
axisRequestMsgCtx.getOptions().setProperties(props);
if (log.isDebugEnabled()) {
log.debug("Properties: " + axisRequestMsgCtx.getProperties().toString());
}
axisRequestMsgCtx.setEnvelope(requestOM);
// Setting the ServiceContext will create the association between
// the OperationClient it's MessageContexts and the
// AxisService/AxisOperation that they are tied to.
axisRequestMsgCtx.setServiceContext(svcClient.getServiceContext());
opClient.addMessageContext(axisRequestMsgCtx);
//This assumes that we are on the ultimate execution thread
ThreadContextMigratorUtil.performMigrationToContext(Constants.THREAD_CONTEXT_MIGRATOR_LIST_ID, axisRequestMsgCtx);
opClient.execute(true);
ThreadContextMigratorUtil.performContextCleanup(Constants.THREAD_CONTEXT_MIGRATOR_LIST_ID, axisRequestMsgCtx);
} catch (AxisFault e) {
throw ExceptionFactory.makeWebServiceException(e);
} catch (MessageException e) {
throw ExceptionFactory.makeWebServiceException(e);
}
}
return;
}
/*
* (non-Javadoc)
* @see org.apache.axis2.jaxws.core.controller.InvocationController#invokeAsync(org.apache.axis2.jaxws.core.InvocationContext, javax.xml.ws.AsyncHandler)
*/
public Future<?> invokeAsync(InvocationContext ic, AsyncHandler callback) {
if (log.isDebugEnabled()) {
log.debug("Invocation pattern: async (callback)");
}
// Check to make sure we at least have a valid InvocationContext
// and request MessageContext
if (ic == null) {
throw ExceptionFactory.makeWebServiceException(Messages.getMessage("ICErr1"));
}
if (ic.getRequestMessageContext() == null) {
throw ExceptionFactory.makeWebServiceException(Messages.getMessage("ICErr3"));
}
// Setup the MessageContext for the response
MessageContext requestMsgCtx = ic.getRequestMessageContext();
ServiceClient svcClient = ic.getServiceClient();
// We need the qname of the operation being invoked to know which
// AxisOperation the OperationClient should be based on.
// Note that the OperationDesc is only set through use of the Proxy. Dispatch
// clients do not use operations, so the operationDesc will be null. In this
// case an anonymous AxisService with anoymouns AxisOperations for the supported
// MEPs will be created; and it is that anonymous operation name which needs to
// be specified
// TODO: Fix this logic once AxisService is created via annoations and not just WSDL
// If ServiceDesc.axisService is null, then we created an Annon Service and operations in
// ServiceDelegate.getServiceClient(), and that is what the service client points to.
// Therefore, we need to use the annonymous operation name in that case, so the anonymous service client will find
// the anonymous AxisOperation on that service.
// This means the ServiceDesc was not build with WSDL, and so there are no Axis objects attached to them
// i.e the OperationDesc.axisOperation == null
QName operationName = getOperationNameToUse(requestMsgCtx, ServiceClient.ANON_OUT_IN_OP);
OperationClient opClient = createOperationClient(svcClient, operationName);
setupProperties(requestMsgCtx, opClient.getOptions());
if (opClient != null) {
// Get the target endpoint address and setup the TO endpoint
// reference. This tells us where the request is going.
String targetUrl = (String) requestMsgCtx.getProperties().get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
EndpointReference toEPR = new EndpointReference(targetUrl);
opClient.getOptions().setTo(toEPR);
// Get the SOAP Action (if needed)
String soapAction = configureSOAPAction(requestMsgCtx);
opClient.getOptions().setAction(soapAction);
// Setup the client so that it knows whether the underlying call to
// Axis2 knows whether or not to start a listening port for an
// asynchronous response.
Boolean useAsyncMep = (Boolean) requestMsgCtx.getProperties().get(Constants.USE_ASYNC_MEP);
if((useAsyncMep != null && useAsyncMep.booleanValue())
|| opClient.getOptions().isUseSeparateListener()) {
opClient.getOptions().setUseSeparateListener(true);
opClient.getOptions().setTransportInProtocol("http");
// Setup the response callback receiver to receive the async response
// This logic is based on org.apache.axis2.client.ServiceClient.sendReceiveNonBlocking(...)
AxisOperation op = opClient.getOperationContext().getAxisOperation();
MessageReceiver messageReceiver = op.getMessageReceiver();
if (messageReceiver == null || !(messageReceiver instanceof CallbackReceiver))
op.setMessageReceiver(new CallbackReceiver());
}
// There should be an AsyncListener that is configured and set on the
// InvocationContext. We must get this and use it to wait for the
// async response to come back. The AxisCallback that is set on the
// AsyncListener is the callback that Axis2 will call when the response
// has arrived.
AsyncListener listener = ic.getAsyncListener();
AxisCallback axisCallback = new AxisCallback();
listener.setAxisCallback(axisCallback);
listener.setInvocationContext(ic);
// Once the AsyncListener is configured, we must include that in an
// AsyncListenerWrapper. The wrapper is what will handle the lifecycle
// of the listener and determine when it's started and stopped.
AsyncListenerWrapper<?> wrapper = new AsyncListenerWrapper<Object>(listener);
// Inside of the wrapper we must set the callback that the JAX-WS
// client programmer provided. This is the user object that we
// must call back on once we've done everything we need to do at
// the JAX-WS layer.
if(callback != null){
wrapper.setAsyncHandler(callback);
}
else {
throw ExceptionFactory.makeWebServiceException(Messages.getMessage("ICErr4"));
}
try {
// Get the request message from the MessageContext and send it
// using the OperationClient API.
Message requestMsg = requestMsgCtx.getMessage();
SOAPEnvelope requestOM = (SOAPEnvelope) requestMsg.getAsOMElement();
// The envelope must be set on the Axis2 MessageContext as a
// OM-based SOAPEnvelope
org.apache.axis2.context.MessageContext axisRequestMsgCtx =
requestMsgCtx.getAxisMessageContext();
axisRequestMsgCtx.setEnvelope(requestOM);
// For now, just take all of the properties that were in the
// JAX-WS MessageContext, and set them on the Axis2 MessageContext.
axisRequestMsgCtx.setProperty(AbstractContext.COPY_PROPERTIES,
Boolean.TRUE);
Map props = axisRequestMsgCtx.getOptions().getProperties();
props.putAll(requestMsgCtx.getProperties());
axisRequestMsgCtx.getOptions().setProperties(props);
if (log.isDebugEnabled()) {
log.debug("Properties: " + axisRequestMsgCtx.getProperties().toString());
}
// Setting the ServiceContext will create the association between
// the OperationClient it's MessageContexts and the
// AxisService/AxisOperation that they are tied to.
axisRequestMsgCtx.setServiceContext(svcClient.getServiceContext());
opClient.addMessageContext(axisRequestMsgCtx);
opClient.setCallback(axisCallback);
ThreadContextMigratorUtil.performMigrationToContext(Constants.THREAD_CONTEXT_MIGRATOR_LIST_ID, axisRequestMsgCtx);
opClient.execute(false);
ThreadContextMigratorUtil.performContextCleanup(Constants.THREAD_CONTEXT_MIGRATOR_LIST_ID, axisRequestMsgCtx);
} catch (AxisFault e) {
throw ExceptionFactory.makeWebServiceException(e);
} catch (MessageException e) {
throw ExceptionFactory.makeWebServiceException(e);
}
// Now that the request has been sent, start the listener thread so that it can
// catch the async response.
// TODO: Need to determine whether this should be done BEFORE or AFTER
// we send the request. My guess is before though.
try {
// TODO:Need to figure out where we get the Executor from
// Can't be from the MessageContext, but should maybe be
// set somewhere accessible.
// FIXME: This should NOT be an ExecutorService, but should just
// be a plain old Executor.
ExecutorService exec = (ExecutorService) ic.getExecutor();
Future<?> future = exec.submit(wrapper);
future.get();
//TODO temp fix to resolve async callback hang.
exec.shutdown();
} catch (InterruptedException e) {
e.printStackTrace();
throw ExceptionFactory.makeWebServiceException(e);
} catch (ExecutionException e) {
e.printStackTrace();
throw ExceptionFactory.makeWebServiceException(e);
}
return wrapper;
}
return null;
}
/*
* (non-Javadoc)
* @see org.apache.axis2.jaxws.core.controller.InvocationController#invokeAsync(org.apache.axis2.jaxws.core.InvocationContext)
*/
public Response invokeAsync(InvocationContext ic) {
if (log.isDebugEnabled()) {
log.debug("Invocation pattern: async (polling)");
}
throw ExceptionFactory.makeWebServiceException(Messages.getMessage("AsyncPollingNotSupported"));
}
/**
* Returns the SOAPAction that should be used for the invocation. This
* method will get the information from the MessageContext passed in
* either from :
*
* a) the JAX-WS properties available on the MessageContext or
* b) the WSDL configuration information available from the MessageContext
*
* @param ctx
* @return
*/
private String configureSOAPAction(MessageContext ctx) {
//TODO: Need to get SOAPAction information from the WSDL config
//TODO: Need to determine what the story is with using the SOAPAction
// declared in the WSDL. If the property says not to use it, but it's
// listed in the WSDL, do we still include it? Do we include it if
// the property is not even set?
Boolean useSoapAction = (Boolean) ctx.getProperties().get(BindingProvider.SOAPACTION_USE_PROPERTY);
if(useSoapAction != null && useSoapAction.booleanValue()){
return (String) ctx.getProperties().get(BindingProvider.SOAPACTION_URI_PROPERTY);
}
return null;
}
/**
* Use the provided ServiceClient instance to create an OperationClient identified
* by the operation QName provided.
*
* @param sc
* @param operation
* @return
*/
private OperationClient createOperationClient(ServiceClient sc, QName operation) {
if (sc == null) {
throw ExceptionFactory.makeWebServiceException(Messages.getMessage("ICCreateOpClientErr1"));
}
if (operation == null) {
throw ExceptionFactory.makeWebServiceException(Messages.getMessage("ICCreateOpClientErr2"));
}
if (log.isDebugEnabled()) {
log.debug("Creating OperationClient for operation: " + operation);
}
try {
OperationClient client = sc.createClient(operation);
return client;
} catch (AxisFault e) {
//TODO: NLS and ExceptionFactory
throw ExceptionFactory.makeWebServiceException(e);
}
}
private Message createMessageFromOM(OMElement om) throws MessageException {
try {
MessageFactory mf = (MessageFactory) FactoryRegistry.getFactory(MessageFactory.class);
Message msg = mf.createFrom(om);
return msg;
} catch (Exception e) {
throw ExceptionFactory.makeWebServiceException(e);
}
}
/*
* TODO: This is a first pass at filtering the properties that are set on the
* RequestContext. Right now it's called during the invoke, but needs to be
* moved over to when the property is set. This should not be in the path
* of performance.
*/
private void setupProperties(MessageContext mc, Options ops) {
Map<String, Object> properties = mc.getProperties();
for (Iterator<String> it = properties.keySet().iterator(); it.hasNext(); ) {
String key = it.next();
Object value = properties.get(key);
ops.setProperty(key, value);
}
// Enable MTOM
Message msg = mc.getMessage();
if (msg.isMTOMEnabled()) {
ops.setProperty(Configuration.ENABLE_MTOM, "true");
}
}
// TODO: This method may need to be removed or refactored when the ServiceDescription can
// create the AxisService hierachy using annotations. Currently the AxisService hierachy is
// only created under a ServiceDescription if WSDL is supplied
private static QName getOperationNameToUse(MessageContext requestMsgCtx, QName defaultOpName) {
// We need the qname of the operation being invoked to know which
// AxisOperation the OperationClient should be based on.
// Note that the OperationDesc is only set through use of the Proxy. Dispatch
// clients do not use operations, so the operationDesc will be null. In this
// case an anonymous AxisService with anoymouns AxisOperations for the supported
// MEPs will be created; and it is that anonymous operation name which needs to
// be specified
// TODO: Fix this logic once AxisService is created via annoations and not just WSDL
// If ServiceDesc.axisService is null (which currently happens if no WSDL
// was supplied when the ServiceDesc is created), then we created an annonymous Service and operations in
// ServiceDelegate.getServiceClient(), and that is what the service client used in the inovke points to.
// Therefore, we need to use the annonymous operation name in that case, so the anonymous service client will find
// the anonymous AxisOperation on that service.
// The check below for this case is that the AxisOperation is null, since all Axis description
// objects (including AxisOperation) are only created if WSDL was use to create the ServiceDesc.
// This will probably need to change once Axis descriptions are also created from annotions.
QName operationName = null;
OperationDescription opDesc = requestMsgCtx.getOperationDescription();
if (opDesc != null && opDesc.getAxisOperation() != null)
operationName = opDesc.getName();
else
operationName = defaultOpName;
return operationName;
}
}