blob: e13129c49ef387abcd383559f928eaf135a459e2 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.client;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.soap.SOAP12Constants;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axiom.soap.SOAPHeaderBlock;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.async.AxisCallback;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.OperationContext;
import org.apache.axis2.context.ServiceContext;
import org.apache.axis2.context.ServiceGroupContext;
import org.apache.axis2.description.AxisModule;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.AxisServiceGroup;
import org.apache.axis2.description.OutInAxisOperation;
import org.apache.axis2.description.OutOnlyAxisOperation;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.description.RobustOutOnlyAxisOperation;
import org.apache.axis2.description.TransportOutDescription;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.engine.ListenerManager;
import org.apache.axis2.i18n.Messages;
import org.apache.axis2.namespace.Constants;
import org.apache.axis2.util.Counter;
import org.apache.axis2.util.JavaUtils;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.wsdl.Definition;
import javax.xml.namespace.QName;
import java.net.URL;
import java.util.ArrayList;
/**
* Client access to a service. Each instance of this class is associated with a particular {@link
* org.apache.axis2.description.AxisService}, and the methods support operations using that service. Note that
* these instances are not intended to be thread-safe.
* {@link Options} instances are used to configure various aspects of the service access.
*/
public class ServiceClient {
protected static final Log log = LogFactory.getLog(ServiceClient.class);
/** Base name used for a service created without an existing configuration. */
public static final String ANON_SERVICE = "anonService";
/** Option property name for automatically cleaning up old OperationContexts */
public static final String AUTO_OPERATION_CLEANUP = "ServiceClient.autoOperationCleanup";
/** Counter used to generate the anonymous service name. */
private static Counter anonServiceCounter = new Counter();
/**
* Operation name used for an anonymous out-only operation (meaning we send a message with no
* response allowed from the service, equivalent to a WSDL In-Only operation).
*/
public static final QName ANON_OUT_ONLY_OP = new QName(
Constants.AXIS2_NAMESPACE_URI, "anonOutonlyOp", Constants.AXIS2_NAMESPACE_PREFIX);
/**
* Operation name used for an anonymous robust-out-only operation (meaning we send a message,
* with the only possible response a fault, equivalent to a WSDL Robust-In-Only operation).
*/
public static final QName ANON_ROBUST_OUT_ONLY_OP = new QName(
Constants.AXIS2_NAMESPACE_URI, "anonRobustOp", Constants.AXIS2_NAMESPACE_PREFIX);
/**
* Operation name used for an anonymous in-out operation (meaning we sent a message and receive
* a response, equivalent to a WSDL In-Out operation).
*/
public static final QName ANON_OUT_IN_OP = new QName(Constants.AXIS2_NAMESPACE_URI,
"anonOutInOp",
Constants.AXIS2_NAMESPACE_PREFIX);
// the meta-data of the service that this client access
private AxisService axisService;
// the configuration in which my meta-data lives
private AxisConfiguration axisConfig;
// the configuration context in which I live
private ConfigurationContext configContext;
// service context for this specific service instance
private ServiceContext serviceContext;
// client options for this service interaction
private Options options = new Options();
// options that must override those of the child operation client also
private Options overrideOptions;
// list of headers to be sent with the simple APIs
private ArrayList<OMElement> headers;
//whether we create configctx or not
private boolean createConfigCtx;
private int hashCode;
private boolean removeAxisService;
/**
* Create a service client configured to work with a specific AxisService. If this service is
* already in the world that's handed in (in the form of a ConfigurationContext) then I will
* happily work in it. If not I will create a small little virtual world and live there.
*
* @param configContext The configuration context under which this service lives (may be null,
* in which case a new local one will be created)
* @param axisService The service for which this is the client (may be <code>null</code>, in
* which case an anonymous service will be created)
* @throws AxisFault if something goes wrong while creating a config context (if needed)
*/
public ServiceClient(ConfigurationContext configContext,
AxisService axisService) throws AxisFault {
configureServiceClient(configContext, axisService);
}
private void configureServiceClient(ConfigurationContext configContext, AxisService axisService)
throws AxisFault {
if (configContext == null) {
if (MessageContext.getCurrentMessageContext() == null) {
configContext = ConfigurationContextFactory.
createConfigurationContextFromFileSystem(null, null);
createConfigCtx = true;
} else {
configContext = MessageContext.getCurrentMessageContext().getConfigurationContext();
}
}
this.configContext = configContext;
hashCode = (int)anonServiceCounter.incrementAndGet();
// Initialize transports
ListenerManager transportManager = configContext.getListenerManager();
if (transportManager == null) {
transportManager = new ListenerManager();
transportManager.init(this.configContext);
}
// save the axisConfig and service
axisConfig = configContext.getAxisConfiguration();
if (axisService == null) {
axisService = createAnonymousService();
}
// axis service is removed from the configuration context
// only if user has not added it to configuration context.
if (axisConfig.getService(axisService.getName()) == null) {
axisService.setClientSide(true);
axisConfig.addService(axisService);
removeAxisService = true;
this.axisService = axisService;
} else {
axisService.setClientSide(true);
removeAxisService = false;
this.axisService = axisConfig.getService(axisService.getName());
}
AxisServiceGroup axisServiceGroup = this.axisService.getAxisServiceGroup();
ServiceGroupContext sgc = configContext.createServiceGroupContext(axisServiceGroup);
serviceContext = sgc.getServiceContext(this.axisService);
}
/**
* This is WSDL4J based constructor to configure the Service Client/ TODO: make this policy
* aware
*
* @param configContext active ConfigurationContext
* @param wsdl4jDefinition the WSDL we're going to be using to configure ourselves
* @param wsdlServiceName QName of the WSDL service we'd like to access
* @param portName name of the WSDL port we'd like to access
* @throws AxisFault in case of error
*/
public ServiceClient(ConfigurationContext configContext, Definition wsdl4jDefinition,
QName wsdlServiceName, String portName) throws AxisFault {
configureServiceClient(configContext, AxisService.createClientSideAxisService(
wsdl4jDefinition, wsdlServiceName, portName, options));
}
/**
* Create a service client for WSDL service identified by the QName of the wsdl:service element
* in a WSDL document.
*
* @param configContext The configuration context under which this service lives (may be
* <code>null</code>, in which case a new local one will be created) *
* @param wsdlURL The URL of the WSDL document to read
* @param wsdlServiceName The QName of the WSDL service in the WSDL document to create a client
* for
* @param portName The name of the WSDL 1.1 port to create a client for. May be null (if
* WSDL 2.0 is used or if only one port is there). .
* @throws AxisFault if something goes wrong while creating a config context (if needed)
*/
public ServiceClient(ConfigurationContext configContext, URL wsdlURL,
QName wsdlServiceName, String portName) throws AxisFault {
configureServiceClient(configContext, AxisService.createClientSideAxisService(wsdlURL,
wsdlServiceName,
portName,
options));
Parameter transportName = axisService.getParameter("TRANSPORT_NAME");
if (transportName != null) {
TransportOutDescription transportOut =
configContext.getAxisConfiguration().getTransportOut(
transportName.getValue().toString());
if (transportOut == null) {
throw new AxisFault(
"Cannot load transport from binding, either defin in Axis2.config " +
"or set it explicitely in ServiceClinet.Options");
} else {
options.setTransportOut(transportOut);
}
}
}
/**
* Create a service client by assuming an anonymous service and any other necessary
* information.
*
* @throws AxisFault in case of error
*/
public ServiceClient() throws AxisFault {
this(null, null);
}
/**
* Create an anonymous axisService with one (anonymous) operation for each MEP that we support
* dealing with anonymously using the convenience APIs.
*
* @return the minted anonymous service
*/
private AxisService createAnonymousService() {
// now add anonymous operations to the axis2 service for use with the
// shortcut client API. NOTE: We only add the ones we know we'll use
// later in the convenience API; if you use
// this constructor then you can't expect any magic!
AxisService axisService =
new AxisService(ANON_SERVICE + anonServiceCounter.incrementAndGet());
RobustOutOnlyAxisOperation robustoutoonlyOperation = new RobustOutOnlyAxisOperation(
ANON_ROBUST_OUT_ONLY_OP);
axisService.addOperation(robustoutoonlyOperation);
OutOnlyAxisOperation outOnlyOperation = new OutOnlyAxisOperation(
ANON_OUT_ONLY_OP);
axisService.addOperation(outOnlyOperation);
OutInAxisOperation outInOperation = new OutInAxisOperation(
ANON_OUT_IN_OP);
axisService.addOperation(outInOperation);
return axisService;
}
/**
* Get the AxisConfiguration
*
* @return the AxisConfiguration associated with the client.
*/
public AxisConfiguration getAxisConfiguration() {
synchronized (this.axisConfig) {
return axisConfig;
}
}
/**
* Return the AxisService this is a client for. This is primarily useful when the AxisService is
* created anonymously or from WSDL as otherwise the user had the AxisService to start with.
*
* @return the axisService
*/
public AxisService getAxisService() {
return axisService;
}
/**
* Set the basic client configuration related to this service interaction.
*
* @param options (non-<code>null</code>)
*/
public void setOptions(Options options) {
this.options = options;
}
/**
* Get the basic client configuration from this service interaction.
*
* @return options
*/
public Options getOptions() {
return options;
}
/**
* Set a client configuration to override the normal options used by an operation client. Any
* values set in this configuration will be used for each client, with the standard values for
* the client still used for any values not set in the override configuration.
*
* @param overrideOptions the Options to use
*/
public void setOverrideOptions(Options overrideOptions) {
this.overrideOptions = overrideOptions;
}
/**
* Get the client configuration used to override the normal options set by an operation client.
*
* @return override options
*/
public Options getOverrideOptions() {
return overrideOptions;
}
/**
* Engage a module for this service client.
*
* @param moduleName name of the module to engage
* @throws AxisFault if something goes wrong
*/
public void engageModule(String moduleName) throws AxisFault {
synchronized (this.axisConfig) {
AxisModule module = axisConfig.getModule(moduleName);
if (module != null) {
axisService.engageModule(module);
} else {
throw new AxisFault("Unable to engage module : " + moduleName);
}
}
}
/**
* Disengage a module for this service client
*
* @param moduleName name of Module to disengage
*/
public void disengageModule(String moduleName) {
synchronized (this.axisConfig) {
AxisModule module = axisConfig.getModule(moduleName);
if (module != null) {
try {
axisService.disengageModule(module);
} catch (AxisFault axisFault) {
log.error(axisFault.getMessage(), axisFault);
}
}
}
}
/**
* Add an arbitrary XML element as a header to be sent with outgoing messages.
*
* @param header header to be sent (non-<code>null</code>)
*/
public void addHeader(OMElement header) {
if (headers == null) {
headers = new ArrayList<OMElement>();
}
headers.add(header);
}
/**
* Add SOAP Header to be sent with outgoing messages.
*
* @param header header to be sent (non-<code>null</code>)
*/
public void addHeader(SOAPHeaderBlock header) {
if (headers == null) {
headers = new ArrayList<OMElement>();
}
headers.add(header);
}
/** Remove all headers for outgoing message. */
public void removeHeaders() {
if (headers != null) {
headers.clear();
}
}
/**
* Add a simple header containing some text to be sent with interactions.
*
* @param headerName name of header to add
* @param headerText text content for header
* @throws AxisFault in case of error
*/
public void addStringHeader(QName headerName, String headerText) throws AxisFault {
if (headerName.getNamespaceURI() == null || "".equals(headerName.getNamespaceURI())) {
throw new AxisFault(
"Failed to add string header, you have to have namespaceURI for the QName");
}
OMElement omElement = OMAbstractFactory.getOMFactory().createOMElement(headerName, null);
omElement.setText(headerText);
addHeader(omElement);
}
/**
* Directly invoke an anonymous operation with a Robust In-Only MEP. This method just sends your
* supplied XML and possibly receives a fault. For more control, you can instead create a client
* for the operation and use that client to execute the send.
*
* @param elem XML to send
* @throws AxisFault if something goes wrong while sending, or if a fault is received in
* response (per the Robust In-Only MEP).
* @see #createClient(QName)
*/
public void sendRobust(OMElement elem) throws AxisFault {
sendRobust(ANON_ROBUST_OUT_ONLY_OP, elem);
}
/**
* Directly invoke a named operation with a Robust In-Only MEP. This method just sends your
* supplied XML and possibly receives a fault. For more control, you can instead create a client
* for the operation and use that client to execute the send.
*
* @param operation name of operation to be invoked (non-<code>null</code>)
* @param elem XML to send
* @throws AxisFault if something goes wrong while sending it or if a fault is received in
* response (per the Robust In-Only MEP).
* @see #createClient(QName)
*/
public void sendRobust(QName operation, OMElement elem) throws AxisFault {
MessageContext mc = new MessageContext();
fillSOAPEnvelope(mc, elem);
OperationClient mepClient = createClient(operation);
mepClient.addMessageContext(mc);
mepClient.execute(true);
}
/**
* Directly invoke an anonymous operation with an In-Only MEP. This method just sends your
* supplied XML without the possibility of any response from the service (even an error - though
* you can still get client-side errors such as "Host not found"). For more control, you can
* instead create a client for the operation and use that client to execute the send.
*
* @param elem XML to send
* @throws AxisFault ff something goes wrong trying to send the XML
* @see #createClient(QName)
*/
public void fireAndForget(OMElement elem) throws AxisFault {
fireAndForget(ANON_OUT_ONLY_OP, elem);
}
/**
* Directly invoke a named operation with an In-Only MEP. This method just sends your supplied
* XML without the possibility of any response from the service (even an error - though you can
* still get client-side errors such as "Host not found"). For more control, you can instead
* create a client for the operation and use that client to execute the send.
*
* @param operation name of operation to be invoked (non-<code>null</code>)
* @param elem XML to send
* @throws AxisFault if something goes wrong trying to send the XML
* @see #createClient(QName)
*/
public void fireAndForget(QName operation, OMElement elem) throws AxisFault {
// look up the appropriate axisop and create the client
OperationClient mepClient = createClient(operation);
// create a message context and put the payload in there along with any
// headers
MessageContext mc = new MessageContext();
fillSOAPEnvelope(mc, elem);
// add the message context there and have it go
mepClient.addMessageContext(mc);
mepClient.execute(false);
}
/**
* Directly invoke an anonymous operation with an In-Out MEP. This method sends your supplied
* XML and receives a response. For more control, you can instead create a client for the
* operation and use that client to execute the exchange.
* <p>
* Unless the <code>callTransportCleanup</code> property on the {@link Options} object has been
* set to <code>true</code>, the caller must invoke {@link #cleanupTransport()} after
* processing the response.
*
* @param elem the data to send (becomes the content of SOAP body)
* @return response
* @throws AxisFault in case of error
* @see #createClient(QName)
* @see #cleanupTransport()
*/
public OMElement sendReceive(OMElement elem) throws AxisFault {
return sendReceive(ANON_OUT_IN_OP, elem);
}
/**
* Directly invoke a named operationQName with an In-Out MEP. This method sends your supplied
* XML and receives a response. For more control, you can instead create a client for the
* operationQName and use that client to execute the exchange.
* <p>
* Unless the <code>callTransportCleanup</code> property on the {@link Options} object has been
* set to <code>true</code>, the caller must invoke {@link #cleanupTransport()} after
* processing the response.
*
* @param operationQName name of operationQName to be invoked (non-<code>null</code>)
* @param xmlPayload the data to send (becomes the content of SOAP body)
* @return response OMElement
* @throws AxisFault in case of error
* @see #cleanupTransport()
*/
public OMElement sendReceive(QName operationQName, OMElement xmlPayload)
throws AxisFault {
MessageContext messageContext = new MessageContext();
fillSOAPEnvelope(messageContext, xmlPayload);
OperationClient operationClient = createClient(operationQName);
operationClient.addMessageContext(messageContext);
operationClient.execute(true);
MessageContext response = operationClient
.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
if (options.isCallTransportCleanup()) {
response.getEnvelope().build();
cleanupTransport();
}
return response.getEnvelope().getBody().getFirstElement();
}
/**
* Directly invoke an anonymous operation with an In-Out MEP without waiting for a response.
* This method sends your supplied XML with response notification to your callback handler. For
* more control, you can instead create a client for the operation and use that client to
* execute the exchange.
*
* @param elem the data to send (becomes the content of SOAP body)
* @param callback a Callback which will be notified upon completion
* @throws AxisFault in case of error
* @see #createClient(QName)
*/
public void sendReceiveNonBlocking(OMElement elem, AxisCallback callback)
throws AxisFault {
sendReceiveNonBlocking(ANON_OUT_IN_OP, elem, callback);
}
/**
* Directly invoke a named operation with an In-Out MEP without waiting for a response. This
* method sends your supplied XML with response notification to your callback handler. For more
* control, you can instead create a client for the operation and use that client to execute the
* exchange.
*
* @param operation name of operation to be invoked (non-<code>null</code>)
* @param elem the data to send (becomes the content of SOAP body)
* @param callback a Callback which will be notified upon completion
* @throws AxisFault in case of error
* @see #createClient(QName)
*/
public void sendReceiveNonBlocking(QName operation, OMElement elem, AxisCallback callback)
throws AxisFault {
MessageContext mc = new MessageContext();
fillSOAPEnvelope(mc, elem);
OperationClient mepClient = createClient(operation);
// here a blocking invocation happens in a new thread, so the
// progamming model is non blocking
mepClient.setCallback(callback);
mepClient.addMessageContext(mc);
mepClient.execute(false);
}
/**
* Create an operation client with the appropriate message exchange pattern (MEP). This method
* creates a full-function MEP client which can be used to exchange messages for a specific
* operation. It configures the constructed operation client to use the current normal and
* override options. This method is used internally, and also by generated client stub code.
*
* @param operationQName qualified name of operation (local name is operation name, namespace
* URI is just the empty string)
* @return client configured to talk to the given operation
* @throws AxisFault if the operation is not found
*/
public OperationClient createClient(QName operationQName) throws AxisFault {
// If we're configured to do so, clean up the last OperationContext (thus
// releasing its resources) each time we create a new one.
if (JavaUtils.isTrue(getOptions().getProperty(AUTO_OPERATION_CLEANUP), true) &&
!getOptions().isUseSeparateListener()) {
cleanupTransport();
}
AxisOperation axisOperation = axisService.getOperation(operationQName);
if (axisOperation == null) {
throw new AxisFault(Messages
.getMessage("operationnotfound", operationQName.getLocalPart()));
}
// add the option properties to the service context
String key;
for (Object o : options.getProperties().keySet()) {
key = (String)o;
serviceContext.setProperty(key, options.getProperties().get(key));
}
OperationClient operationClient = axisOperation.createClient(serviceContext, options);
// if overide options have been set, that means we need to make sure
// those options override the options of even the operation client. So,
// what we do is switch the parents around to make that work.
if (overrideOptions != null) {
overrideOptions.setParent(operationClient.getOptions());
operationClient.setOptions(overrideOptions);
}
return operationClient;
}
/**
* Return the SOAP factory to use depending on what options have been set. If the SOAP version
* can not be seen in the options, version 1.1 is the default.
*
* @return the SOAP factory
* @see Options#setSoapVersionURI(String)
*/
private SOAPFactory getSOAPFactory() {
String soapVersionURI = options.getSoapVersionURI();
if (SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(soapVersionURI)) {
return OMAbstractFactory.getSOAP12Factory();
} else {
// make the SOAP 1.1 the default SOAP version
return OMAbstractFactory.getSOAP11Factory();
}
}
/**
* Prepare a SOAP envelope with the stuff to be sent.
*
* @param messageContext the message context to be filled
* @param xmlPayload the payload content
* @throws AxisFault if something goes wrong
*/
private void fillSOAPEnvelope(MessageContext messageContext, OMElement xmlPayload)
throws AxisFault {
messageContext.setServiceContext(serviceContext);
SOAPFactory soapFactory = getSOAPFactory();
SOAPEnvelope envelope = soapFactory.getDefaultEnvelope();
if (xmlPayload != null) {
envelope.getBody().addChild(xmlPayload);
}
addHeadersToEnvelope(envelope);
messageContext.setEnvelope(envelope);
}
/**
* Add all configured headers to a SOAP envelope.
*
* @param envelope the SOAPEnvelope in which to write the headers
*/
public void addHeadersToEnvelope(SOAPEnvelope envelope) {
if (headers != null) {
SOAPHeader soapHeader = envelope.getHeader();
for (Object header : headers) {
soapHeader.addChild((OMElement)header);
}
}
}
/**
* Get the endpoint reference for this client using a particular transport.
*
* @param transport transport name (non-<code>null</code>)
* @return local endpoint
* @throws AxisFault in case of error
*/
public EndpointReference getMyEPR(String transport) throws AxisFault {
return serviceContext.getMyEPR(transport);
}
/**
* Get the endpoint reference for the service.
*
* @return service endpoint
*/
public EndpointReference getTargetEPR() {
return serviceContext.getTargetEPR();
}
/**
* Set the endpoint reference for the service.
*
* @param targetEpr the EPR this ServiceClient should target
*/
public void setTargetEPR(EndpointReference targetEpr) {
serviceContext.setTargetEPR(targetEpr);
options.setTo(targetEpr);
}
/**
* Gets the last OperationContext
*
* @return the last OperationContext that was invoked by this ServiceClient
*/
public OperationContext getLastOperationContext() {
return serviceContext.getLastOperationContext();
}
/**
* Get the service context.
*
* @return context
*/
public ServiceContext getServiceContext() {
return serviceContext;
}
protected void finalize() throws Throwable {
try {
cleanup();
} finally {
super.finalize();
}
}
/**
* Clean up configuration created with this client. Call this method when you're done using the
* client, in order to discard any associated resources.
*
* @throws AxisFault in case of error
*/
public void cleanup() throws AxisFault {
// if a configuration context was created for this client there'll also
// be a service group, so discard that
if (!createConfigCtx) {
String serviceGroupName = axisService.getAxisServiceGroup().getServiceGroupName();
AxisConfiguration axisConfiguration = configContext.getAxisConfiguration();
AxisServiceGroup asg = axisConfiguration.getServiceGroup(serviceGroupName);
if ((asg != null) && removeAxisService) {
axisConfiguration.removeServiceGroup(serviceGroupName);
}
} else {
configContext.terminate();
}
}
/**
* Release resources allocated by the transport during the last service invocation.
* This method will call
* {@link org.apache.axis2.transport.TransportSender#cleanup(MessageContext)} on the
* transport sender used during that invocation.
* <p>
* If the <code>callTransportCleanup</code> property on the {@link Options} object is
* set to <code>false</code> (which is the default), then this method must be called
* after each invocation of an operation with an in-out MEP, but not before the response
* from that operation has been completely processed (or {@link OMElement#build()}
* has been called on the response element).
* <p>
* If the <code>callTransportCleanup</code> property is set to <code>true</code>,
* then this method is called automatically. Note that in this case, {@link OMElement#build()}
* will be called on the response element before is returned. This effectively disables
* deferred parsing of the response and prevents the code from starting to process the
* response before it has been completely received. Therefore this approach is not recommended
* whenever performance is important.
*
* @throws AxisFault
*/
public void cleanupTransport() throws AxisFault {
final OperationContext lastOperationContext = getLastOperationContext();
if (lastOperationContext != null) {
MessageContext outMessageContext =
lastOperationContext
.getMessageContext(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
if (outMessageContext != null) {
if (outMessageContext.getTransportOut() != null &&
outMessageContext.getTransportOut().getSender() != null) {
outMessageContext.getTransportOut().getSender().cleanup(outMessageContext);
}
}
}
}
/**
* Configure the ServiceClient to interact with the Web service described by the specified
* AxisService object.
*
* @param axisService the AxisService that represents the new Web service.
* @throws AxisFault if an error occurs while configuring the ServiceClient.
*/
public void setAxisService(AxisService axisService) throws AxisFault {
if (axisService == null) {
// AxisFault?
throw new IllegalArgumentException("AxisService is null");
}
synchronized (this.axisConfig) {
axisConfig.removeService(this.axisService.getName());
this.axisService = axisService;
axisService.setClientSide(true);
axisConfig.addService(axisService);
}
AxisServiceGroup axisServiceGroup = axisService.getAxisServiceGroup();
ServiceGroupContext serviceGroupContext =
configContext.createServiceGroupContext(axisServiceGroup);
this.serviceContext = serviceGroupContext.getServiceContext(axisService);
}
/** @see java.lang.Object#hashCode() */
public int hashCode() {
return this.hashCode;
}
/** @see java.lang.Object#equals(java.lang.Object) */
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof ServiceClient))
return false;
final ServiceClient other = (ServiceClient)obj;
return hashCode == other.hashCode;
}
}