[SP-pm] Problema ao usar SOAP::Lite pra falar com servidor Java

Gustavo Leite de Mendonça Chaves gustavo at gnustavo.com
Tue Dec 8 10:59:33 PST 2009


Olá. Estou há alguns dias tentando depurar um cliente Perl falando com
um servidor Java via SOAP sem sucesso. Alguém com mais experiência no
SOAP::Lite pode me ajudar?

O contexto é o meu módulo JIRA::Client
(http://search.cpan.org/~gnustavo/JIRA-Client/) que implementa uma
interface estendida pra API SOAP do JIRA
(http://docs.atlassian.com/software/jira/docs/api/rpc-jira-plugin/latest/com/atlassian/jira/rpc/soap/JiraSoapService.html).

Pois bem, não estou conseguindo invocar um método da API em particular
que tem a seguinte assinatura em Java:

    boolean addBase64EncodedAttachmentsToIssue(java.lang.String token,
java.lang.String issueKey, java.lang.String[] fileNames,
java.lang.String[] base64EncodedAttachmentData)

Quando o módulo JIRA::Client invoca o método 'call' num objeto
SOAP::Client os argumentos são estes:

    $soaplite->call('addBase64EncodedAttachmentsToIssue',
'08FiZ3A5Cu', 'TST-20616', ['file1.txt'],
['VGVzdCBmcm9tIEpJUkE6OkNsaWVudC4K']);

O servidor devolve a seguinte mensagem de erro:
soapenv:Server.userException: java.lang.ArrayStoreException:
[Ljava.lang.String;

Os dois primeiros argumentos (token e issueKey) devem estar corretos,
porque eu consigo chamar vários outros métodos da API que também os
requerem. Algo deve estar errado com os dois últimos arrays.

Baixei um cliente de exemplo em Java que consegue fazer a chamada ao
método pra comparar o SOAP que ele gera. Eis o XML trocado entre o
cliente Java e o JIRA para fazer a autenticação inicial e depois
anexar um arquivo via addBase64EncodedAttachmentsToIssue:

--------------------------------------------------------- Cliente Java
# CALL login
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <ns1:login soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://soap.rpc.jira.atlassian.com">
      <in0 xsi:type="xsd:string">soaptester</in0>
      <in1 xsi:type="xsd:string">soaptester</in1>
    </ns1:login>
  </soapenv:Body>
</soapenv:Envelope>
# RESPONSE
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <ns1:loginResponse
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://soap.rpc.jira.atlassian.com">
      <loginReturn xsi:type="xsd:string">Y1nU54fr3T</loginReturn>
    </ns1:loginResponse>
  </soapenv:Body>
</soapenv:Envelope>


# CALL addBase64EncodedAttachmentsToIssue
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <ns1:addBase64EncodedAttachmentsToIssue
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://soap.rpc.jira.atlassian.com">
      <in0 xsi:type="xsd:string">Y1nU54fr3T</in0>
      <in1 xsi:type="xsd:string">TST-20616</in1>
      <in2 soapenc:arrayType="xsd:string[1]" xsi:type="soapenc:Array"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
	<in2 xsi:type="xsd:string">attachment643562722194294045760.txt</in2>
      </in2>
      <in3 soapenc:arrayType="xsd:string[1]" xsi:type="soapenc:Array"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
	<in3 xsi:type="xsd:string">QSBzYW1wbGUgZmlsZSBhdHRhY2hlZCB2aWEgU09BUCB0byBKSVJBIGlzc3VlIFRTVC0yMDYxNg==</in3>
      </in3>
    </ns1:addBase64EncodedAttachmentsToIssue>
  </soapenv:Body>
</soapenv:Envelope>
# RESPONSE
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <ns1:addBase64EncodedAttachmentsToIssueResponse
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://soap.rpc.jira.atlassian.com">
      <addBase64EncodedAttachmentsToIssueReturn
xsi:type="xsd:boolean">true</addBase64EncodedAttachmentsToIssueReturn>
    </ns1:addBase64EncodedAttachmentsToIssueResponse>
  </soapenv:Body>
</soapenv:Envelope>
---------------------------------------------------------------

Agora eis o mesmo exemplo com o cliente Perl (o nome e o conteúdo do
arquivo anexo é diferente):

--------------------------------------------------------- cliente Perl
# CALL login
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <login>
      <c-gensym3 xsi:type="xsd:string">soaptester</c-gensym3>
      <c-gensym5 xsi:type="xsd:string">soaptester</c-gensym5>
    </login>
  </soap:Body>
</soap:Envelope>
# RESPONSE
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <loginResponse
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
      <loginReturn xsi:type="xsd:string">pX8Vpqp1Z8</loginReturn>
    </loginResponse>
  </soapenv:Body>
</soapenv:Envelope>

# CALL addBase64EncodedAttachmentsToIssue
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <addBase64EncodedAttachmentsToIssue>
      <c-gensym8 xsi:type="xsd:string">pX8Vpqp1Z8</c-gensym8>
      <c-gensym10 xsi:type="xsd:string">TST-20616</c-gensym10>
      <soapenc:Array soapenc:arrayType="xsd:string[1]" xsi:type="soapenc:Array">
	<item xsi:type="xsd:string">file1.txt</item>
      </soapenc:Array>
      <soapenc:Array soapenc:arrayType="xsd:string[1]" xsi:type="soapenc:Array">
	<item xsi:type="xsd:string">VGVzdCBmcm9tIEpJUkE6OkNsaWVudC4K
	</item>
      </soapenc:Array>
    </addBase64EncodedAttachmentsToIssue>
  </soap:Body>
</soap:Envelope>
# RESPONSE
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <soapenv:Fault>
      <faultcode>soapenv:Server.userException</faultcode>
      <faultstring>java.lang.ArrayStoreException:
[Ljava.lang.String;</faultstring>
      <detail>
	<faultData xsi:type="ns1:ArrayStoreException" xmlns:ns1="http://lang.java"/>
	<ns2:hostname xmlns:ns2="http://xml.apache.org/axis/">atlassian14.managed.contegix.com</ns2:hostname>
      </detail>
    </soapenv:Fault>
  </soapenv:Body>
</soapenv:Envelope>

----------------------------------------------------------

Eu comparei visualmente o XML da chamada SOAP ao método e há realmente
várias diferenças. Mas eu não entendo muito de SOAP pra saber o que é
relevante. O que eu sei é que o XML não precisa mesmo ser idêntico,
pois o módulo JIRA::Client já é usado há um bom tempo para executar
vários outros métodos da API.

Uma coisa que logo me chamou a atenção foi o fato de o conteúdo do
anexo (o item do último argumento) ter um newline antes do fechamento
da tag </item> na versão gerada com Perl e não ter o newline na versão
gerada com Java. Mas eu executei o script no depurador uma outra vez e
removi na mão o newline. Mesmo assim o problema persistiu.

A mensagem de erro do servidor também não parece muito específica. A
especificação (http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ArrayStoreException.html)
diz que a exceção ArrayStoreException "[is] thrown to indicate that an
attempt has been made to store the wrong type of object into an array
of objects". O que vem a seguir ([Ljava.lang.String;) é um código que
significa "array de objetos java.lang.String". Que é o que o servidor
deveria estar esperando e é o que eu acho que estou enviando...

Alguém pode me ajudar com alguma dica?

Obrigado.

Gustavo.


More information about the SaoPaulo-pm mailing list