Uploaded image for project: 'Axis'
  1. Axis
  2. AXIS-2880

Type mappings should be registered in the locator instead of the stub



    • Bug
    • Status: Open
    • Major
    • Resolution: Unresolved
    • 1.4
    • 1.4.1
    • Basic Architecture
    • None


      The createCall method in a generated stub contains the following code:

      // All the type mapping information is registered
      // when the first call is made.
      // The type mapping information is actually registered in
      // the TypeMappingRegistry of the service, which
      // is the reason why registration is only needed for the first call.
      synchronized (this) {
      if (firstCall()) {
      // must set encoding style before registering serializers
      for (int i = 0; i < cachedSerFactories.size(); ++i) {
      java.lang.Class cls = (java.lang.Class) cachedSerClasses.get;
      javax.xml.namespace.QName qName =
      (javax.xml.namespace.QName) cachedSerQNames.get;
      java.lang.Object x = cachedSerFactories.get;
      if (x instanceof Class)

      { java.lang.Class sf = (java.lang.Class) cachedSerFactories.get(i); java.lang.Class df = (java.lang.Class) cachedDeserFactories.get(i); _call.registerTypeMapping(cls, qName, sf, df, false); }

      else if (x instanceof javax.xml.rpc.encoding.SerializerFactory)

      { org.apache.axis.encoding.SerializerFactory sf = (org.apache.axis.encoding.SerializerFactory) cachedSerFactories.get(i); org.apache.axis.encoding.DeserializerFactory df = (org.apache.axis.encoding.DeserializerFactory) cachedDeserFactories.get(i); _call.registerTypeMapping(cls, qName, sf, df, false); }


      As noted in the comment, the type mapping is actually registered in the type mapping registry of the service (implemented by the locator). This raises the question why that registration is not done in the locator in the first place. In fact, doing the registration before the first call in the stub has a couple of issues:

      • This is prone to concurrency issues as described in AXIS-2498.
      • It unnecessarily increases the cost of creating a stub. Note that each stub will actually attempt to perform the registration, but only the first one will effectively modify the type mappings. Execution of the code shown above by subsequently created stubs (from the same locator) will be a no-op because the type mappings are already registered (and registerTypeMapping will silently skip the registration).
      • If the service has multiple ports, then the code (in the stub constructor) that initializes the cachedSerClasses, cachedSerQNames, cachedSerFactories and cachedDeserFactories fields is actually duplicated in each stub because the same type mappings are registered in each stub (although with potentially different encoding styles).

      Note that if the code generator is changed so that type mappings are registered in the locator, then the constructors of the stubs need to be changed:

      public XxxStub() throws org.apache.axis.AxisFault {

      public XxxStub(java.net.URL endpointURL, javax.xml.rpc.Service service) throws org.apache.axis.AxisFault {
      super.cachedEndpoint = endpointURL;

      public XxxStub(javax.xml.rpc.Service service) throws org.apache.axis.AxisFault {
      if (service == null)

      { super.service = new org.apache.axis.client.Service(); }


      { super.service = service; }


      Instead of creating a plain org.apache.axis.client.Service instance, the code should create an instance of the locator. Note that this would still make a difference for application code that directly creates a stub and passes a reference to a Service that is not an instance of the locator. However, this is a very unlikely scenario.


        Issue Links



              veithen Andreas Veithen
              veithen Andreas Veithen
              0 Vote for this issue
              1 Start watching this issue