[
https://issues.apache.org/jira/browse/AXIS2-5745?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16160982#comment-16160982
]
Thorsten Schöning commented on AXIS2-5745:
------------------------------------------
Any ideas on how to fix this properly? I see multiple ways and maybe my
use-case gets clearer if I'm describing it using some concrete examples:
Some of my services are deployed individually for each customer/mandator into
the same Axis2 repo using some simple naming convention by adding a suffix. In
the following example the suffixes ".sp1" and ".sp2" are used for what is
basically the same logical service, only as individual and distinct
deployments, no files shared. To not need to change too many configuration
files, the "services.xml" of those services contain the exact same service
name. Because those names need to be unique in Axis2, I simply change those
names in the LifeCycle callback using the unique directory name created in the
Axis2 service repository. So one service called "Auth" in "services.xml" in
both example deployments becomes "de.am_soft.sm_mtg.backend.sp1.Auth" etc.
Axis2-Repo:
{CODE}
tschoening@potsdam:/var/lib/tomcat7/webapps/axis2/WEB-INF/services$ ls -lisa
[...]
130911 4 lrwxrwxrwx 1 tomcat7 tomcat7 61 Apr 20 2015
de.am_soft.sm_mtg.backend.sp1
131348 4 lrwxrwxrwx 1 tomcat7 tomcat7 61 Apr 20 2015
de.am_soft.sm_mtg.backend.sp2
{CODE}
services.xml:
{CODE}
<service name="Auth"
class="de.am_soft.util.backend.svcs.WsAxis2SvcLc">
<Description>
de.am_soft.sm_mtg.backend.svcs.ws.WsAuth
</Description>
<parameter name="ServiceClass">
de.am_soft.sm_mtg.backend.svcs.ws.WsAuth
</parameter>
<messageReceivers>
<messageReceiver
mep="http://www.w3.org/2004/08/wsdl/in-only"
class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"
/>
<messageReceiver
mep="http://www.w3.org/2004/08/wsdl/in-out"
class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"
/>
</messageReceivers>
</service>
{CODE}
axis2/services/listServices:
{CODE}
de.am_soft.sm_mtg.backend.sp1.Auth
de.am_soft.sm_mtg.backend.sp2.Auth
{CODE}
This works fine for some years now, besides the problem described initially. So
if you say it is wrong or a misusage of the LifeCycle/deployment, in my opinion
it should be disallowed to change service names at all. I would need an
alternative solution for my use-case then of course... If you say my use-case
is valid, I need a solution for the problem with the not up-to-date internal
structures anymore after I change the name.
1. The low level rewriting of TypeTable I'm currently doing externally could be
done in AxisService.setName. But that's only one internal structure and seems
more like an ugly hack.
2. ServiceBuilder.populateService calls the lifecycle of a service at the end
currently. In theory it could be called a lot earlier maybe allowing to set a
name before it is used in internal structures. We would need a way to not let
the set values be overridden by what is parsed form the config then.
3. ServiceBuilder.populateService could query for settings at runtime using
some other interface than the lifecycle and merge those with what is available
using the config as some fallback. Could be the same interface curently used
with "some_element" and some proxy/dispatcher/whatever first calls the new
interface and without any value it forwards to "some_element" like is currently
used. The interesting question would be which data would be provided to that
interface because I need to determine the directory my sertvice ist stored
in... Currently I'm using two approaches, either "AxisService.getFileName" or
"service.getClassLoader().getResource".
4. Storing an "initial service name" in AxisService.setName if not already
available and use that while querying TypeTable and similar structs.
Any other ideas?
I'm not sure I completely understand where and how the TypeTable is filled
initially and sometimes AxisService-instances are already created with names
using a special CTOR, without ServiceBuilder.populateService. But I do have the
feeling that if changing names is allowed, Axis2 should maintain up-to-date
structures internally.
> Changing a service name doesn't update its TypeTable struct
> -----------------------------------------------------------
>
> Key: AXIS2-5745
> URL: https://issues.apache.org/jira/browse/AXIS2-5745
> Project: Axis2
> Issue Type: Bug
> Components: kernel
> Affects Versions: 1.6.2
> Environment: Windows 8.1 x86-64, Tomcat 7.0.68 x86-64
> Reporter: Thorsten Schöning
> Attachments: WsAxis2SvcLc.java
>
>
> 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.
> {CODE}
> 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());
> {CODE}
> 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":
> {CODE}
> 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}
> {CODE}
> 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.
> {CODE}
> 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);
> }
> {CODE}
> {CODE}
> 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());
> }
> {CODE}
--
This message was sent by Atlassian JIRA
(v6.4.14#64029)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]