Uploaded image for project: 'Axis2'
  1. Axis2
  2. AXIS2-5745

Changing a service name doesn't update its TypeTable struct

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Major
    • Resolution: Unresolved
    • 1.6.2
    • None
    • kernel
    • None
    • Windows 8.1 x86-64, Tomcat 7.0.68 x86-64

    Description

      I have an implementation of ServiceLifeCycle in which I'm overriding startUp and change the name of my service in some special way to make my deployment easier. I'm simply implementing some kind of mandator mechanism based on exploded services and their unique name in the file system.

      This worked pretty fine the last years, but today I encountered that Axis2 is handling structures internally in which the service name is used as some component of a key. Those structures were built before startUp was called and were not updated on a changed service name. My service generated an exception for some reason, Axis2 tried to handle that and failed itself with a NPE, which made debugging pretty hard of course because the original exception was lost.

      The NPE was thrown in the following line 183 of RPCMessageReceiver and the not up to date structure was TypeTable for the service, that's why elementQName was null instead of a valid object. Gladly I was able to access that map in my ServiceLifeCycle implementation and update the generated keys and QNames with my new updated service name. I would have expected that if I'm able to change the service name, structs containing it would get updated automatically by Axis 2, which at least for TypeTable currently isn't the case.

      175            Class[] exceptionTypes = method.getExceptionTypes();
      176            for (Class exceptionType : exceptionTypes){
      177                if (exceptionType.getName().equals(cause.getClass().getName())){
      178                    // this is an bussiness logic exception so handle it properly
      179                    String partQName = inMessage.getAxisService().getName() + getSimpleClassName(exceptionType);
      180                    TypeTable typeTable = inMessage.getAxisService().getTypeTable();
      181                    QName elementQName = typeTable.getQNamefortheType(partQName);
      182                    SOAPFactory fac = getSOAPFactory(inMessage);
      183                    OMElement exceptionElement = fac.createOMElement(elementQName);
      184
      185                    if (exceptionType.getName().equals(Exception.class.getName())){
      186                        // this is an exception class. so create a element by hand and add the message
      187                       OMElement innterExceptionElement = fac.createOMElement(elementQName);
      188                       OMElement messageElement = fac.createOMElement("Message", inMessage.getAxisService().getTargetNamespace(), null);
      189                       messageElement.setText(cause.getMessage());
      

      http://grepcode.com/file/repo1.maven.org/maven2/org.apache.axis2/axis2-adb/1.6.2/org/apache/axis2/rpc/receivers/RPCMessageReceiver.java/#183

      I'm currently unable to build Axis2 from src and am not sure where one would implement such a change, therefore can't provide patches, but instead I'll simply post my implemantation of the change for TypeTable in my ServiceLifeCycle. In my case, TypeTable contained the following data for my old service name "SoapAuth":

      complexTypeMap  HashMap<K,V>  (id=165)
      {java.sql={http://sql.java/xsd}SQLException, SoapAuthSecurityException={http://soap.ws.clients.backend.docs.docsrv.am_soft.de}SoapAuthSecurityException, java.sql.SQLException={http://sql.java/xsd}SQLException, logout={http://soap.ws.clients.backend.docs.docsrv.am_soft.de}logout, java.io={http://io.java/xsd}FileNotFoundException, SoapAuthSQLException={http://soap.ws.clients.backend.docs.docsrv.am_soft.de}SoapAuthSQLException, cookieAbgleich={http://soap.ws.clients.backend.docs.docsrv.am_soft.de}cookieAbgleich, SoapAuthClassNotFoundException={http://soap.ws.clients.backend.docs.docsrv.am_soft.de}SoapAuthClassNotFoundException, SoapAuthFileNotFoundException={http://soap.ws.clients.backend.docs.docsrv.am_soft.de}SoapAuthFileNotFoundException, java.io.IOException={http://io.java/xsd}IOException, SoapAuthIOException={http://soap.ws.clients.backend.docs.docsrv.am_soft.de}SoapAuthIOException, java.io.FileNotFoundException={http://io.java/xsd}FileNotFoundException}
      

      My LifeCycle changes the name from "SoapAuth" to "de.am_soft.docsrv.docs.backend.SoapAuth" and therefore I simply rename all entries with the wrong service name, remove them and put new ones in.

      private void updateSvcTypeTable(AxisService	service,
      								String		oldSvcName,
      								String		newSvcName)
      {
      	TypeTable			tt				= service.getTypeTable();
      	@SuppressWarnings("unchecked")
      	Map<String, QName>	schemaMap		= tt.getComplexSchemaMap();
      	Map<String, QName>	addSchemaMap	= new HashMap<String, QName>(schemaMap.size());
      
      	for (Iterator<Entry<String, QName>>	it = schemaMap.entrySet().iterator();
      										it.hasNext(); )
      	{
      		Entry<String, QName>	entry	= it.next();
      		String					key		= entry.getKey();
      		QName					value	= entry.getValue();
      
      		if (!key.startsWith(oldSvcName))
      		{
      			continue;
      		}
      
      		String newKeyRegExp		= String.format("^\\Q%s\\E", oldSvcName);
      		String newValueRegExp	= String.format("}\\Q%s\\E", oldSvcName);
      		String newKey			= key.replaceFirst(newKeyRegExp, newSvcName);
      		String newValue			= value.toString().replaceFirst(newValueRegExp, "}".concat(newSvcName));
      
      		addSchemaMap.put(newKey, QName.valueOf(newValue));
      		it.remove();
      	}
      	schemaMap.putAll(addSchemaMap);
      }
      
      private void changeSvcName(AxisService service)
      {
      	logger.trace("Start: {}", service.getName());
      
      	File	configDir	= this.getConfigDir(service);
      	File	svcDir		= configDir.getParentFile().getParentFile();
      	String	oldSvcName	= service.getName();
      	String	newSvcName	= svcDir.getName().concat(".").concat(oldSvcName);
      
      	service.setName(newSvcName);
      	this.updateSvcTypeTable(service, oldSvcName, newSvcName);
      
      	logger.trace("End: {}", service.getName());
      }
      

      Attachments

        1. WsAxis2SvcLc.java
          10 kB
          Thorsten Schöning

        Issue Links

          Activity

            People

              Unassigned Unassigned
              tschoening Thorsten Schöning
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated: