Save This Page
Home » axis2-1.5-src » org.apache » axis2 » client » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one
    3    * or more contributor license agreements. See the NOTICE file
    4    * distributed with this work for additional information
    5    * regarding copyright ownership. The ASF licenses this file
    6    * to you under the Apache License, Version 2.0 (the
    7    * "License"); you may not use this file except in compliance
    8    * with the License. You may obtain a copy of the License at
    9    *
   10    * http://www.apache.org/licenses/LICENSE-2.0
   11    *
   12    * Unless required by applicable law or agreed to in writing,
   13    * software distributed under the License is distributed on an
   14    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   15    * KIND, either express or implied. See the License for the
   16    * specific language governing permissions and limitations
   17    * under the License.
   18    */
   19   
   20   package org.apache.axis2.client;
   21   
   22   import org.apache.axiom.om.OMAbstractFactory;
   23   import org.apache.axiom.om.OMElement;
   24   import org.apache.axiom.soap.SOAP12Constants;
   25   import org.apache.axiom.soap.SOAPEnvelope;
   26   import org.apache.axiom.soap.SOAPFactory;
   27   import org.apache.axiom.soap.SOAPHeader;
   28   import org.apache.axiom.soap.SOAPHeaderBlock;
   29   import org.apache.axis2.AxisFault;
   30   import org.apache.axis2.addressing.EndpointReference;
   31   import org.apache.axis2.client.async.AxisCallback;
   32   import org.apache.axis2.client.async.Callback;
   33   import org.apache.axis2.context.ConfigurationContext;
   34   import org.apache.axis2.context.ConfigurationContextFactory;
   35   import org.apache.axis2.context.MessageContext;
   36   import org.apache.axis2.context.OperationContext;
   37   import org.apache.axis2.context.ServiceContext;
   38   import org.apache.axis2.context.ServiceGroupContext;
   39   import org.apache.axis2.description.AxisModule;
   40   import org.apache.axis2.description.AxisOperation;
   41   import org.apache.axis2.description.AxisService;
   42   import org.apache.axis2.description.AxisServiceGroup;
   43   import org.apache.axis2.description.OutInAxisOperation;
   44   import org.apache.axis2.description.OutOnlyAxisOperation;
   45   import org.apache.axis2.description.Parameter;
   46   import org.apache.axis2.description.RobustOutOnlyAxisOperation;
   47   import org.apache.axis2.description.TransportOutDescription;
   48   import org.apache.axis2.engine.AxisConfiguration;
   49   import org.apache.axis2.engine.ListenerManager;
   50   import org.apache.axis2.i18n.Messages;
   51   import org.apache.axis2.namespace.Constants;
   52   import org.apache.axis2.util.Counter;
   53   import org.apache.axis2.wsdl.WSDLConstants;
   54   import org.apache.commons.logging.Log;
   55   import org.apache.commons.logging.LogFactory;
   56   
   57   import javax.wsdl.Definition;
   58   import javax.xml.namespace.QName;
   59   import java.net.URL;
   60   import java.util.ArrayList;
   61   
   62   /**
   63    * Client access to a service. Each instance of this class is associated with a particular {@link
   64    * org.apache.axis2.description.AxisService}, and the methods support operations using that service.
   65    * {@link Options} instances are used to configure various aspects of the service access.
   66    */
   67   public class ServiceClient {
   68       protected static final Log log = LogFactory.getLog(ServiceClient.class);
   69   
   70       /** Base name used for a service created without an existing configuration. */
   71       public static final String ANON_SERVICE = "anonService";
   72   
   73       /** Counter used to generate the anonymous service name. */
   74       private static Counter anonServiceCounter = new Counter();
   75   
   76       /**
   77        * Operation name used for an anonymous out-only operation (meaning we send a message with no
   78        * response allowed from the service, equivalent to a WSDL In-Only operation).
   79        */
   80       public static final QName ANON_OUT_ONLY_OP = new QName(
   81               Constants.AXIS2_NAMESPACE_URI, "anonOutonlyOp", Constants.AXIS2_NAMESPACE_PREFIX);
   82   
   83       /**
   84        * Operation name used for an anonymous robust-out-only operation (meaning we send a message,
   85        * with the only possible response a fault, equivalent to a WSDL Robust-In-Only operation).
   86        */
   87       public static final QName ANON_ROBUST_OUT_ONLY_OP = new QName(
   88               Constants.AXIS2_NAMESPACE_URI, "anonRobustOp", Constants.AXIS2_NAMESPACE_PREFIX);
   89   
   90       /**
   91        * Operation name used for an anonymous in-out operation (meaning we sent a message and receive
   92        * a response, equivalent to a WSDL In-Out operation).
   93        */
   94       public static final QName ANON_OUT_IN_OP = new QName(Constants.AXIS2_NAMESPACE_URI,
   95                                                            "anonOutInOp",
   96                                                            Constants.AXIS2_NAMESPACE_PREFIX);
   97   
   98       // the meta-data of the service that this client access
   99       private AxisService axisService;
  100   
  101       // the configuration in which my meta-data lives
  102       private AxisConfiguration axisConfig;
  103   
  104       // the configuration context in which I live
  105       private ConfigurationContext configContext;
  106   
  107       // service context for this specific service instance
  108       private ServiceContext serviceContext;
  109   
  110       // client options for this service interaction
  111       private Options options = new Options();
  112   
  113       // options that must override those of the child operation client also
  114       private Options overrideOptions;
  115   
  116       // list of headers to be sent with the simple APIs
  117       private ArrayList<OMElement> headers;
  118   
  119       //whether we create configctx or not
  120       private boolean createConfigCtx;
  121   
  122       private int hashCode;
  123   
  124       private boolean removeAxisService;
  125   
  126       /**
  127        * Create a service client configured to work with a specific AxisService. If this service is
  128        * already in the world that's handed in (in the form of a ConfigurationContext) then I will
  129        * happily work in it. If not I will create a small little virtual world and live there.
  130        *
  131        * @param configContext The configuration context under which this service lives (may be null,
  132        *                      in which case a new local one will be created)
  133        * @param axisService   The service for which this is the client (may be <code>null</code>, in
  134        *                      which case an anonymous service will be created)
  135        * @throws AxisFault if something goes wrong while creating a config context (if needed)
  136        */
  137       public ServiceClient(ConfigurationContext configContext,
  138                            AxisService axisService) throws AxisFault {
  139           configureServiceClient(configContext, axisService);
  140       }
  141   
  142       private void configureServiceClient(ConfigurationContext configContext, AxisService axisService)
  143               throws AxisFault {
  144           if (configContext == null) {
  145               if (ListenerManager.defaultConfigurationContext == null) {
  146                   configContext = ConfigurationContextFactory.
  147                           createConfigurationContextFromFileSystem(null, null);
  148                   ListenerManager.defaultConfigurationContext = configContext;
  149                   createConfigCtx = true;
  150               } else {
  151                   configContext = ListenerManager.defaultConfigurationContext;
  152               }
  153           }
  154           this.configContext = configContext;
  155           hashCode = (int)anonServiceCounter.incrementAndGet();
  156   
  157           // Initialize transports
  158           ListenerManager transportManager = configContext.getListenerManager();
  159           if (transportManager == null) {
  160               transportManager = new ListenerManager();
  161               transportManager.init(this.configContext);
  162           }
  163   
  164           // save the axisConfig and service
  165           axisConfig = configContext.getAxisConfiguration();
  166   
  167           if (axisService == null) {
  168               axisService = createAnonymousService();
  169           }
  170           this.axisService = axisService;
  171           // axis service is removed from the configuration context
  172           // only if user has not added it to configuration context.
  173           if (axisConfig.getService(axisService.getName()) == null) {
  174               axisService.setClientSide(true);
  175               axisConfig.addService(axisService);
  176               removeAxisService = true;
  177           } else {
  178               axisService.setClientSide(true);
  179               removeAxisService = false;
  180           }
  181           AxisServiceGroup axisServiceGroup = axisService.getAxisServiceGroup();
  182           ServiceGroupContext sgc = configContext.createServiceGroupContext(axisServiceGroup);
  183           serviceContext = sgc.getServiceContext(axisService);
  184       }
  185   
  186   
  187       /**
  188        * This is WSDL4J based constructor to configure the Service Client/ TODO: make this policy
  189        * aware
  190        *
  191        * @param configContext    active ConfigurationContext
  192        * @param wsdl4jDefinition the WSDL we're going to be using to configure ourselves
  193        * @param wsdlServiceName  QName of the WSDL service we'd like to access
  194        * @param portName         name of the WSDL port we'd like to access
  195        * @throws AxisFault in case of error
  196        */
  197   
  198       public ServiceClient(ConfigurationContext configContext, Definition wsdl4jDefinition,
  199                            QName wsdlServiceName, String portName) throws AxisFault {
  200           configureServiceClient(configContext, AxisService.createClientSideAxisService(
  201                   wsdl4jDefinition, wsdlServiceName, portName, options));
  202       }
  203   
  204       /**
  205        * Create a service client for WSDL service identified by the QName of the wsdl:service element
  206        * in a WSDL document.
  207        *
  208        * @param configContext   The configuration context under which this service lives (may be
  209        *                        <code>null</code>, in which case a new local one will be created) *
  210        * @param wsdlURL         The URL of the WSDL document to read
  211        * @param wsdlServiceName The QName of the WSDL service in the WSDL document to create a client
  212        *                        for
  213        * @param portName        The name of the WSDL 1.1 port to create a client for. May be null (if
  214        *                        WSDL 2.0 is used or if only one port is there). .
  215        * @throws AxisFault if something goes wrong while creating a config context (if needed)
  216        */
  217       public ServiceClient(ConfigurationContext configContext, URL wsdlURL,
  218                            QName wsdlServiceName, String portName) throws AxisFault {
  219           configureServiceClient(configContext, AxisService.createClientSideAxisService(wsdlURL,
  220                                                                                         wsdlServiceName,
  221                                                                                         portName,
  222                                                                                         options));
  223           Parameter transportName = axisService.getParameter("TRANSPORT_NAME");
  224           if (transportName != null) {
  225               TransportOutDescription transportOut =
  226                       configContext.getAxisConfiguration().getTransportOut(
  227                               transportName.getValue().toString());
  228               if (transportOut == null) {
  229                   throw new AxisFault(
  230                           "Cannot load transport from binding, either defin in Axis2.config " +
  231                           "or set it explicitely in ServiceClinet.Options");
  232               } else {
  233                   options.setTransportOut(transportOut);
  234               }
  235           }
  236       }
  237   
  238       /**
  239        * Create a service client by assuming an anonymous service and any other necessary
  240        * information.
  241        *
  242        * @throws AxisFault in case of error
  243        */
  244       public ServiceClient() throws AxisFault {
  245           this(null, null);
  246       }
  247   
  248       /**
  249        * Create an anonymous axisService with one (anonymous) operation for each MEP that we support
  250        * dealing with anonymously using the convenience APIs.
  251        *
  252        * @return the minted anonymous service
  253        */
  254       private AxisService createAnonymousService() {
  255           // now add anonymous operations to the axis2 service for use with the
  256           // shortcut client API. NOTE: We only add the ones we know we'll use
  257           // later in the convenience API; if you use
  258           // this constructor then you can't expect any magic!
  259           AxisService axisService =
  260                   new AxisService(ANON_SERVICE + anonServiceCounter.incrementAndGet());
  261           RobustOutOnlyAxisOperation robustoutoonlyOperation = new RobustOutOnlyAxisOperation(
  262                   ANON_ROBUST_OUT_ONLY_OP);
  263           axisService.addOperation(robustoutoonlyOperation);
  264   
  265           OutOnlyAxisOperation outOnlyOperation = new OutOnlyAxisOperation(
  266                   ANON_OUT_ONLY_OP);
  267           axisService.addOperation(outOnlyOperation);
  268   
  269           OutInAxisOperation outInOperation = new OutInAxisOperation(
  270                   ANON_OUT_IN_OP);
  271           axisService.addOperation(outInOperation);
  272           return axisService;
  273       }
  274   
  275       /**
  276        * Get the AxisConfiguration
  277        *
  278        * @return the AxisConfiguration associated with the client.
  279        */
  280       public AxisConfiguration getAxisConfiguration() {
  281           synchronized (this.axisConfig) {
  282               return axisConfig;
  283           }
  284       }
  285   
  286       /**
  287        * Return the AxisService this is a client for. This is primarily useful when the AxisService is
  288        * created anonymously or from WSDL as otherwise the user had the AxisService to start with.
  289        *
  290        * @return the axisService
  291        */
  292       public AxisService getAxisService() {
  293           return axisService;
  294       }
  295   
  296       /**
  297        * Set the basic client configuration related to this service interaction.
  298        *
  299        * @param options (non-<code>null</code>)
  300        */
  301       public void setOptions(Options options) {
  302           this.options = options;
  303       }
  304   
  305       /**
  306        * Get the basic client configuration from this service interaction.
  307        *
  308        * @return options
  309        */
  310       public Options getOptions() {
  311           return options;
  312       }
  313   
  314       /**
  315        * Set a client configuration to override the normal options used by an operation client. Any
  316        * values set in this configuration will be used for each client, with the standard values for
  317        * the client still used for any values not set in the override configuration.
  318        *
  319        * @param overrideOptions the Options to use
  320        */
  321       public void setOverrideOptions(Options overrideOptions) {
  322           this.overrideOptions = overrideOptions;
  323       }
  324   
  325       /**
  326        * Get the client configuration used to override the normal options set by an operation client.
  327        *
  328        * @return override options
  329        */
  330       public Options getOverrideOptions() {
  331           return overrideOptions;
  332       }
  333   
  334       /**
  335        * Engage a module for this service client.
  336        *
  337        * @param moduleName name of the module to engage
  338        * @throws AxisFault if something goes wrong
  339        * @deprecated Please use String version instead
  340        */
  341       public void engageModule(QName moduleName) throws AxisFault {
  342           engageModule(moduleName.getLocalPart());
  343       }
  344   
  345       /**
  346        * Engage a module for this service client.
  347        *
  348        * @param moduleName name of the module to engage
  349        * @throws AxisFault if something goes wrong
  350        */
  351       public void engageModule(String moduleName) throws AxisFault {
  352           synchronized (this.axisConfig) {
  353               AxisModule module = axisConfig.getModule(moduleName);
  354               if (module != null) {
  355                   axisService.engageModule(module);
  356               } else {
  357                   throw new AxisFault("Unable to engage module : " + moduleName);
  358               }
  359           }
  360       }
  361   
  362       /**
  363        * Disengage a module for this service client
  364        *
  365        * @param moduleName name of Module to disengage
  366        * @deprecated Please use String version instead
  367        */
  368       public void disengageModule(QName moduleName) {
  369           disengageModule(moduleName.getLocalPart());
  370       }
  371   
  372       /**
  373        * Disengage a module for this service client
  374        *
  375        * @param moduleName name of Module to disengage
  376        */
  377       public void disengageModule(String moduleName) {
  378           synchronized (this.axisConfig) {
  379               AxisModule module = axisConfig.getModule(moduleName);
  380               if (module != null) {
  381                   try {
  382                       axisService.disengageModule(module);
  383                   } catch (AxisFault axisFault) {
  384                       log.error(axisFault.getMessage(), axisFault);
  385                   }
  386               }
  387           }
  388       }
  389   
  390       /**
  391        * Add an arbitrary XML element as a header to be sent with outgoing messages.
  392        *
  393        * @param header header to be sent (non-<code>null</code>)
  394        */
  395       public void addHeader(OMElement header) {
  396           if (headers == null) {
  397               headers = new ArrayList<OMElement>();
  398           }
  399           headers.add(header);
  400       }
  401   
  402       /**
  403        * Add SOAP Header to be sent with outgoing messages.
  404        *
  405        * @param header header to be sent (non-<code>null</code>)
  406        */
  407       public void addHeader(SOAPHeaderBlock header) {
  408           if (headers == null) {
  409               headers = new ArrayList<OMElement>();
  410           }
  411           headers.add(header);
  412       }
  413   
  414       /** Remove all headers for outgoing message. */
  415       public void removeHeaders() {
  416           if (headers != null) {
  417               headers.clear();
  418           }
  419       }
  420   
  421   
  422       /**
  423        * Add a simple header containing some text to be sent with interactions.
  424        *
  425        * @param headerName name of header to add
  426        * @param headerText text content for header
  427        * @throws AxisFault in case of error
  428        */
  429       public void addStringHeader(QName headerName, String headerText) throws AxisFault {
  430           if (headerName.getNamespaceURI() == null || "".equals(headerName.getNamespaceURI())) {
  431               throw new AxisFault(
  432                       "Failed to add string header, you have to have namespaceURI for the QName");
  433           }
  434           OMElement omElement = OMAbstractFactory.getOMFactory().createOMElement(headerName, null);
  435           omElement.setText(headerText);
  436           addHeader(omElement);
  437       }
  438   
  439       /**
  440        * Directly invoke an anonymous operation with a Robust In-Only MEP. This method just sends your
  441        * supplied XML and possibly receives a fault. For more control, you can instead create a client
  442        * for the operation and use that client to execute the send.
  443        *
  444        * @param elem XML to send
  445        * @throws AxisFault if something goes wrong while sending, or if a fault is received in
  446        *                   response (per the Robust In-Only MEP).
  447        * @see #createClient(QName)
  448        */
  449       public void sendRobust(OMElement elem) throws AxisFault {
  450           sendRobust(ANON_ROBUST_OUT_ONLY_OP, elem);
  451       }
  452   
  453       /**
  454        * Directly invoke a named operation with a Robust In-Only MEP. This method just sends your
  455        * supplied XML and possibly receives a fault. For more control, you can instead create a client
  456        * for the operation and use that client to execute the send.
  457        *
  458        * @param operation name of operation to be invoked (non-<code>null</code>)
  459        * @param elem      XML to send
  460        * @throws AxisFault if something goes wrong while sending it or if a fault is received in
  461        *                   response (per the Robust In-Only MEP).
  462        * @see #createClient(QName)
  463        */
  464       public void sendRobust(QName operation, OMElement elem) throws AxisFault {
  465           MessageContext mc = new MessageContext();
  466           fillSOAPEnvelope(mc, elem);
  467           OperationClient mepClient = createClient(operation);
  468           mepClient.addMessageContext(mc);
  469           mepClient.execute(true);
  470       }
  471   
  472       /**
  473        * Directly invoke an anonymous operation with an In-Only MEP. This method just sends your
  474        * supplied XML without the possibility of any response from the service (even an error - though
  475        * you can still get client-side errors such as "Host not found"). For more control, you can
  476        * instead create a client for the operation and use that client to execute the send.
  477        *
  478        * @param elem XML to send
  479        * @throws AxisFault ff something goes wrong trying to send the XML
  480        * @see #createClient(QName)
  481        */
  482       public void fireAndForget(OMElement elem) throws AxisFault {
  483           fireAndForget(ANON_OUT_ONLY_OP, elem);
  484       }
  485   
  486       /**
  487        * Directly invoke a named operation with an In-Only MEP. This method just sends your supplied
  488        * XML without the possibility of any response from the service (even an error - though you can
  489        * still get client-side errors such as "Host not found"). For more control, you can instead
  490        * create a client for the operation and use that client to execute the send.
  491        *
  492        * @param operation name of operation to be invoked (non-<code>null</code>)
  493        * @param elem      XML to send
  494        * @throws AxisFault if something goes wrong trying to send the XML
  495        * @see #createClient(QName)
  496        */
  497       public void fireAndForget(QName operation, OMElement elem) throws AxisFault {
  498           // look up the appropriate axisop and create the client
  499           OperationClient mepClient = createClient(operation);
  500           // create a message context and put the payload in there along with any
  501           // headers
  502           MessageContext mc = new MessageContext();
  503           fillSOAPEnvelope(mc, elem);
  504           // add the message context there and have it go
  505           mepClient.addMessageContext(mc);
  506           mepClient.execute(false);
  507       }
  508   
  509       /**
  510        * Directly invoke an anonymous operation with an In-Out MEP. This method sends your supplied
  511        * XML and receives a response. For more control, you can instead create a client for the
  512        * operation and use that client to execute the exchange.
  513        *
  514        * @param elem the data to send (becomes the content of SOAP body)
  515        * @return response
  516        * @throws AxisFault in case of error
  517        * @see #createClient(QName)
  518        */
  519       public OMElement sendReceive(OMElement elem) throws AxisFault {
  520           return sendReceive(ANON_OUT_IN_OP, elem);
  521       }
  522   
  523       /**
  524        * Directly invoke a named operationQName with an In-Out MEP. This method sends your supplied
  525        * XML and receives a response. For more control, you can instead create a client for the
  526        * operationQName and use that client to execute the exchange.
  527        *
  528        * @param operationQName name of operationQName to be invoked (non-<code>null</code>)
  529        * @param xmlPayload     the data to send (becomes the content of SOAP body)
  530        * @return response OMElement
  531        * @throws AxisFault in case of error
  532        */
  533       public OMElement sendReceive(QName operationQName, OMElement xmlPayload)
  534               throws AxisFault {
  535           MessageContext messageContext = new MessageContext();
  536           fillSOAPEnvelope(messageContext, xmlPayload);
  537           OperationClient operationClient = createClient(operationQName);
  538           operationClient.addMessageContext(messageContext);
  539           operationClient.execute(true);
  540           MessageContext response = operationClient
  541                   .getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
  542           if (options.isCallTransportCleanup()) {
  543               response.getEnvelope().build();
  544               cleanupTransport();
  545           }
  546           return response.getEnvelope().getBody().getFirstElement();
  547       }
  548   
  549       /**
  550        * Directly invoke an anonymous operation with an In-Out MEP without waiting for a response.
  551        * This method sends your supplied XML with response notification to your callback handler. For
  552        * more control, you can instead create a client for the operation and use that client to
  553        * execute the exchange.
  554        *
  555        * @param elem     the data to send (becomes the content of SOAP body)
  556        * @param callback a Callback which will be notified upon completion
  557        * @throws AxisFault in case of error
  558        * @see #createClient(QName)
  559        * @deprecated Please use the AxisCallback interface rather than Callback, which has been
  560        *             deprecated
  561        */
  562       public void sendReceiveNonBlocking(OMElement elem, Callback callback)
  563               throws AxisFault {
  564           sendReceiveNonBlocking(ANON_OUT_IN_OP, elem, callback);
  565       }
  566   
  567       /**
  568        * Directly invoke an anonymous operation with an In-Out MEP without waiting for a response.
  569        * This method sends your supplied XML with response notification to your callback handler. For
  570        * more control, you can instead create a client for the operation and use that client to
  571        * execute the exchange.
  572        *
  573        * @param elem     the data to send (becomes the content of SOAP body)
  574        * @param callback a Callback which will be notified upon completion
  575        * @throws AxisFault in case of error
  576        * @see #createClient(QName)
  577        */
  578       public void sendReceiveNonBlocking(OMElement elem, AxisCallback callback)
  579               throws AxisFault {
  580           sendReceiveNonBlocking(ANON_OUT_IN_OP, elem, callback);
  581       }
  582   
  583       /**
  584        * Directly invoke a named operation with an In-Out MEP without waiting for a response. This
  585        * method sends your supplied XML with response notification to your callback handler. For more
  586        * control, you can instead create a client for the operation and use that client to execute the
  587        * exchange.
  588        *
  589        * @param operation name of operation to be invoked (non-<code>null</code>)
  590        * @param elem      the data to send (becomes the content of SOAP body)
  591        * @param callback  a Callback which will be notified upon completion
  592        * @throws AxisFault in case of error
  593        * @see #createClient(QName)
  594        * @deprecated Please use the AxisCallback interface rather than Callback, which has been
  595        *             deprecated
  596        */
  597       public void sendReceiveNonBlocking(QName operation, OMElement elem, Callback callback)
  598               throws AxisFault {
  599           MessageContext mc = new MessageContext();
  600           fillSOAPEnvelope(mc, elem);
  601           OperationClient mepClient = createClient(operation);
  602           // here a blocking invocation happens in a new thread, so the
  603           // progamming model is non blocking
  604           mepClient.setCallback(callback);
  605           mepClient.addMessageContext(mc);
  606           mepClient.execute(false);
  607       }
  608   
  609       /**
  610        * Directly invoke a named operation with an In-Out MEP without waiting for a response. This
  611        * method sends your supplied XML with response notification to your callback handler. For more
  612        * control, you can instead create a client for the operation and use that client to execute the
  613        * exchange.
  614        *
  615        * @param operation name of operation to be invoked (non-<code>null</code>)
  616        * @param elem      the data to send (becomes the content of SOAP body)
  617        * @param callback  a Callback which will be notified upon completion
  618        * @throws AxisFault in case of error
  619        * @see #createClient(QName)
  620        */
  621       public void sendReceiveNonBlocking(QName operation, OMElement elem, AxisCallback callback)
  622               throws AxisFault {
  623           MessageContext mc = new MessageContext();
  624           fillSOAPEnvelope(mc, elem);
  625           OperationClient mepClient = createClient(operation);
  626           // here a blocking invocation happens in a new thread, so the
  627           // progamming model is non blocking
  628           mepClient.setCallback(callback);
  629           mepClient.addMessageContext(mc);
  630           mepClient.execute(false);
  631       }
  632   
  633       /**
  634        * Create an operation client with the appropriate message exchange pattern (MEP). This method
  635        * creates a full-function MEP client which can be used to exchange messages for a specific
  636        * operation. It configures the constructed operation client to use the current normal and
  637        * override options. This method is used internally, and also by generated client stub code.
  638        *
  639        * @param operationQName qualified name of operation (local name is operation name, namespace
  640        *                       URI is just the empty string)
  641        * @return client configured to talk to the given operation
  642        * @throws AxisFault if the operation is not found
  643        */
  644       public OperationClient createClient(QName operationQName) throws AxisFault {
  645           AxisOperation axisOperation = axisService.getOperation(operationQName);
  646           if (axisOperation == null) {
  647               throw new AxisFault(Messages
  648                       .getMessage("operationnotfound", operationQName.getLocalPart()));
  649           }
  650   
  651           // add the option properties to the service context
  652           String key;
  653           for (Object o : options.getProperties().keySet()) {
  654               key = (String)o;
  655               serviceContext.setProperty(key, options.getProperties().get(key));
  656           }
  657           OperationClient operationClient = axisOperation.createClient(serviceContext, options);
  658   
  659           // if overide options have been set, that means we need to make sure
  660           // those options override the options of even the operation client. So,
  661           // what we do is switch the parents around to make that work.
  662           if (overrideOptions != null) {
  663               overrideOptions.setParent(operationClient.getOptions());
  664               operationClient.setOptions(overrideOptions);
  665           }
  666           return operationClient;
  667       }
  668   
  669       /**
  670        * Return the SOAP factory to use depending on what options have been set. If the SOAP version
  671        * can not be seen in the options, version 1.1 is the default.
  672        *
  673        * @return the SOAP factory
  674        * @see Options#setSoapVersionURI(String)
  675        */
  676       private SOAPFactory getSOAPFactory() {
  677           String soapVersionURI = options.getSoapVersionURI();
  678           if (SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(soapVersionURI)) {
  679               return OMAbstractFactory.getSOAP12Factory();
  680           } else {
  681               // make the SOAP 1.1 the default SOAP version
  682               return OMAbstractFactory.getSOAP11Factory();
  683           }
  684       }
  685   
  686       /**
  687        * Prepare a SOAP envelope with the stuff to be sent.
  688        *
  689        * @param messageContext the message context to be filled
  690        * @param xmlPayload     the payload content
  691        * @throws AxisFault if something goes wrong
  692        */
  693       private void fillSOAPEnvelope(MessageContext messageContext, OMElement xmlPayload)
  694               throws AxisFault {
  695           messageContext.setServiceContext(serviceContext);
  696           SOAPFactory soapFactory = getSOAPFactory();
  697           SOAPEnvelope envelope = soapFactory.getDefaultEnvelope();
  698           if (xmlPayload != null) {
  699               envelope.getBody().addChild(xmlPayload);
  700           }
  701           addHeadersToEnvelope(envelope);
  702           messageContext.setEnvelope(envelope);
  703       }
  704   
  705   
  706       /**
  707        * Add all configured headers to a SOAP envelope.
  708        *
  709        * @param envelope the SOAPEnvelope in which to write the headers
  710        */
  711       public void addHeadersToEnvelope(SOAPEnvelope envelope) {
  712           if (headers != null) {
  713               SOAPHeader soapHeader = envelope.getHeader();
  714               for (Object header : headers) {
  715                   soapHeader.addChild((OMElement)header);
  716               }
  717           }
  718       }
  719   
  720   
  721       /**
  722        * Get the endpoint reference for this client using a particular transport.
  723        *
  724        * @param transport transport name (non-<code>null</code>)
  725        * @return local endpoint
  726        * @throws AxisFault in case of error
  727        */
  728       public EndpointReference getMyEPR(String transport) throws AxisFault {
  729           return serviceContext.getMyEPR(transport);
  730       }
  731   
  732       /**
  733        * Get the endpoint reference for the service.
  734        *
  735        * @return service endpoint
  736        */
  737       public EndpointReference getTargetEPR() {
  738           return serviceContext.getTargetEPR();
  739       }
  740   
  741       /**
  742        * Set the endpoint reference for the service.
  743        *
  744        * @param targetEpr the EPR this ServiceClient should target
  745        */
  746       public void setTargetEPR(EndpointReference targetEpr) {
  747           serviceContext.setTargetEPR(targetEpr);
  748           options.setTo(targetEpr);
  749       }
  750   
  751       /**
  752        * Gets the last OperationContext
  753        *
  754        * @return the last OperationContext that was invoked by this ServiceClient
  755        */
  756       public OperationContext getLastOperationContext() {
  757           return serviceContext.getLastOperationContext();
  758       }
  759   
  760       /**
  761        * Sets whether or not to cache the last OperationContext
  762        *
  763        * @param cachingOpContext true if we should hold onto the last active OperationContext
  764        * @deprecated
  765        */
  766       public void setCachingOperationContext(boolean cachingOpContext) {
  767           serviceContext.setCachingOperationContext(cachingOpContext);
  768       }
  769   
  770   
  771       /**
  772        * Get the service context.
  773        *
  774        * @return context
  775        */
  776       public ServiceContext getServiceContext() {
  777           return serviceContext;
  778       }
  779   
  780       protected void finalize() throws Throwable {
  781           super.finalize();
  782           cleanup();
  783       }
  784   
  785       /**
  786        * Clean up configuration created with this client. Call this method when you're done using the
  787        * client, in order to discard any associated resources.
  788        *
  789        * @throws AxisFault in case of error
  790        */
  791       public void cleanup() throws AxisFault {
  792           // if a configuration context was created for this client there'll also
  793           //  be a service group, so discard that
  794           if (!createConfigCtx) {
  795               String serviceGroupName = axisService.getAxisServiceGroup().getServiceGroupName();
  796               AxisConfiguration axisConfiguration = configContext.getAxisConfiguration();
  797               AxisServiceGroup asg = axisConfiguration.getServiceGroup(serviceGroupName);
  798               if ((asg != null) && removeAxisService) {
  799                   axisConfiguration.removeServiceGroup(serviceGroupName);
  800               }
  801           } else {
  802               configContext.terminate();
  803           }
  804       }
  805   
  806       public void cleanupTransport() throws AxisFault {
  807           if (getLastOperationContext() != null) {
  808               MessageContext outMessageContext =
  809                       getLastOperationContext()
  810                               .getMessageContext(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
  811               if (outMessageContext != null) {
  812                   outMessageContext.getTransportOut().getSender().cleanup(outMessageContext);
  813               }
  814           }
  815       }
  816   
  817       /**
  818        * Configure the ServiceClient to interact with the Web service described by the specified
  819        * AxisService object.
  820        *
  821        * @param axisService the AxisService that represents the new Web service.
  822        * @throws AxisFault if an error occurs while configuring the ServiceClient.
  823        */
  824       public void setAxisService(AxisService axisService) throws AxisFault {
  825   
  826           if (axisService == null) {
  827               // AxisFault?
  828               throw new IllegalArgumentException("AxisService is null");
  829           }
  830   
  831           synchronized (this.axisConfig) {
  832               axisConfig.removeService(this.axisService.getName());
  833               this.axisService = axisService;
  834   
  835               axisService.setClientSide(true);
  836               axisConfig.addService(axisService);
  837           }
  838           AxisServiceGroup axisServiceGroup = axisService.getAxisServiceGroup();
  839           ServiceGroupContext serviceGroupContext =
  840                   configContext.createServiceGroupContext(axisServiceGroup);
  841           this.serviceContext = serviceGroupContext.getServiceContext(axisService);
  842       }
  843   
  844       /** @see java.lang.Object#hashCode() */
  845       public int hashCode() {
  846           return this.hashCode;
  847       }
  848   
  849       /** @see java.lang.Object#equals(java.lang.Object) */
  850       public boolean equals(Object obj) {
  851           if (this == obj)
  852               return true;
  853           if (obj == null)
  854               return false;
  855           if (!(obj instanceof ServiceClient))
  856               return false;
  857           final ServiceClient other = (ServiceClient)obj;
  858           return hashCode == other.hashCode;
  859       }
  860   
  861   }

Save This Page
Home » axis2-1.5-src » org.apache » axis2 » client » [javadoc | source]