使用QuickBooks Web Connector的身份验证问题:未将对象引用设置为对象的实例

时间:2014-07-07 19:27:29

标签: java soap clojure axis2 quickbooks

(是的,我知道这个问题与another question posted类似;但是,这个问题从未得到解答。)

目的

我尝试使用Clojure和Axis 2使用QuickBooks WebConnector(从现在开始的QBWC)访问QuickBooks数据。 QBWC使用SOAP与外部应用程序通信,这就是我的Clojure应用程序使用Axis 2作为SOAP接口的原因。我使用来自GitHub的micha's clj-soap来提供与Axis 2的Java调用的更高级(抽象)Clojure互操作。

问题

问题在于使用QBWC验证我的SOAP Web服务。使用我的SOAP Web服务的authenticate方法,QBWC会抛出错误。在QBWC日志文件中,它说明如下:

QBWebConnector.SOAPWebService.do_authenticate() : QBWC1012: Authentication failed due to following error message: Object reference not set to an instance of an object.
StackTrace = at QBWebConnector.WebService.do_authenticate(String& ticket, String& companyFileName)
Source = QBWebConnector

代码

下面是Clojure代码,该代码为我使用的Axis 2服务器定义了一个名为SOCAccess的Web服务。

(对于那些不熟悉Clojure但熟悉Java的人,下面的代码创建了一个名为developer.intuit.com.SOCAccess的类,并定义了与QBWC通信所需的许多方法(包括authenticateserverVersion等。插入符号表示返回或参数类型.Clojure编译成Java字节码,默认情况下它不使用强类型,这转换为大多数类型提示为Object,但由于Java2WSDL的工作方式,需要强类型。例如:

类型^String最终为<xs:element minOccurs="0" name="return" nillable="true" type="xs:string"/>

类型^Object最终为<xs:element minOccurs="0" name="return" nillable="true" type="xs:anyType"/>

类型^"[Ljava.lang.String;"String[]相同,最终为<xs:element maxOccurs="unbounded" minOccurs="0" name="return" nillable="true" type="xs:string"/>

(soap/defservice developer.intuit.com.SOCAccess
  (authenticate2 ^"[Ljava.lang.String;" [^String username ^String password]
    (authenticate2* username password))
  (authenticate ^"[Ljava.lang.String;" [^String username ^String password]
    (authenticate* username password))
  (prefix35authenticate ^"[Ljava.lang.String;" [^String username ^String password]
    (authenticate* username password))
  (sendRequestXML ^Object
    [^String ticket ^String hcp-response ^String company-file-name ^String qb-xml-country
     ^Integer qb-xml-major-vers, ^Integer qb-xml-minor-vers]
    (send-request-xml ticket hcp-response company-file-name qb-xml-country qb-xml-major-vers qb-xml-minor-vers))
  (receiveResponseXML  ^Integer [^String ticket ^String response ^String hresult ^String message]
    (receive-response-xml ticket response hresult message))
  (connectionError     ^Object [^String ticket ^String hresult ^String message]
    (connection-error ticket hresult message))
  (getLastError        ^String [^String ticket]
    (get-last-error ticket))
  (closeConnection     ^String [^String ticket]
    (close-connection ticket))
  (getServerVersion    ^String [^String ticket] (server-version ticket))
  (serverVersion       ^String [^String ticket] (server-version ticket))
  (clientVersion       ^String [^String version] (client-version version))
  (interactiveDone     ^String [^String ticket] (interactive-done ticket))
  (interactiveRejected ^String [^String ticket ^String reason] (interactive-rejected ticket reason)))

服务器初始化

一旦我启动AxisServer并使用类名.addService调用"developer.intuit.com.SOCAccess",输出窗口将打印以下内容,这是一个根据上述代码编译的类:

Jul 07, 2014 11:22:20 AM org.apache.axis2.transport.http.server.DefaultConnectionListener run
INFO: Listening on port 6060

一切似乎都正常运行。

SOAP调用

但是,当我在运行的JVM中对我的Web服务进行SOAP调用(authenticate "my-username" "my-password")时,返回值应该是String[]并且println()输出显示它确实是一个String[],但返回值只显示为数组的第一个元素,这很奇怪。我的猜测是,这是QBWC发生Object reference not set to an instance of an object错误的原因,因为它试图将String的第n个元素视为数组。

======

有什么想法?我意识到这是一个很长的问题。让我知道您希望我以代码,WSDL等方式提供什么。

谢谢!

ADDENDUM:日志文件

20140707.20:06:40 UTC   : QBWebConnector.WebServiceManager.DoUpdateSelected() : updateWS() for application = 'SOCAccess' has STARTED
20140707.20:06:40 UTC   : QBWebConnector.RegistryManager.getUpdateLock() : HKEY_CURRENT_USER\Software\Intuit\QBWebConnector\UpdateLock = FALSE
20140707.20:06:40 UTC   : QBWebConnector.RegistryManager.setUpdateLock() : HKEY_CURRENT_USER\Software\Intuit\QBWebConnector\UpdateLock has been set to True
20140707.20:06:40 UTC   : QBWebConnector.RegistryManager.setUpdateLock() : ********************* Update session locked *********************
20140707.20:06:40 UTC   : QBWebConnector.SOAPWebService.instantiateWebService() : Initiated connection to the following application.
20140707.20:06:40 UTC   : QBWebConnector.SOAPWebService.instantiateWebService() : AppName: SOCAccess
20140707.20:06:40 UTC   : QBWebConnector.SOAPWebService.instantiateWebService() : AppUniqueName (if available): SOCAccess
20140707.20:06:40 UTC   : QBWebConnector.SOAPWebService.instantiateWebService() : AppURL: http://localhost:6060/axis2/services/SOCAccess
20140707.20:06:40 UTC   : QBWebConnector.SOAPWebService.do_serverVersion() : *** Calling serverVersion().
20140707.20:06:40 UTC   : QBWebConnector.SOAPWebService.do_serverVersion() : Received from serverVersion() following parameter:<serverVersionRet="">
20140707.20:06:40 UTC   : QBWebConnector.SOAPWebService.do_serverVersion() : This application sent a null for server version. Allowing update operation.
20140707.20:06:40 UTC   : QBWebConnector.SOAPWebService.do_clientVersion() : *** Calling clientVersion() with following parameter:<productVersion="2.1.0.27">
20140707.20:06:40 UTC   : QBWebConnector.SOAPWebService.do_clientVersion() : Received from clientVersion() following parameter:<clientVersionRet="">
20140707.20:06:40 UTC   : QBWebConnector.SOAPWebService.do_clientVersion() : This application agrees with the current version of QBWebConnector. Allowing update operation.
20140707.20:06:40 UTC   : QBWebConnector.SOAPWebService.do_authenticate() : Authenticating to application 'SOCAccess', username = 'alexandergunnarson'
20140707.20:06:40 UTC   : QBWebConnector.SOAPWebService.do_authenticate() : *** Calling authenticate() with following parameters:<userName="alexandergunnarson"><password=<MaskedForSecurity>
20140707.20:06:40 UTC   : QBWebConnector.SOAPWebService.do_authenticate() : QBWC1012: Authentication failed due to following error message.
Object reference not set to an instance of an object.
More info:
StackTrace =    at QBWebConnector.WebService.do_authenticate(String& ticket, String& companyFileName)
Source = QBWebConnector
20140707.20:06:40 UTC   : QBWebConnector.RegistryManager.setUpdateLock() : HKEY_CURRENT_USER\Software\Intuit\QBWebConnector\UpdateLock has been set to False
20140707.20:06:40 UTC   : QBWebConnector.RegistryManager.setUpdateLock() : ********************* Update session unlocked *********************
20140707.20:06:40 UTC   : QBWebConnector.WebServiceManager.DoUpdateSelected() : Update completed with errors. See log (QWClog.txt) for details.

ADDENDUM:SOAP IN

<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">
  <soapenv:Body>
    <axis2ns34:authenticate xmlns:axis2ns34=\"http://developer.intuit.com/\">
      <axis2ns35:args0 xmlns:axis2ns35=\"http://developer.intuit.com/\">
        alexandergunnarson
      </axis2ns35:args0>
      <axis2ns36:args1 xmlns:axis2ns36=\"http://developer.intuit.com/\">
        password
      </axis2ns36:args1>
    </axis2ns34:authenticate>
  </soapenv:Body>
</soapenv:Envelope>

ADDENDUM:SOAP OUT

<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">
  <soapenv:Body>
    <ns:authenticateResponse xmlns:ns=\"http://developer.intuit.com/\">
      <return>my-session-token</return>
      <return>none</return>
      <return>60</return>
      <return>60</return>
    </ns:authenticateResponse>
  </soapenv:Body>
</soapenv:Envelope>

更新

自从我上次发布以来,发生了很多事情。 1)我试图实现ArrayOfString,但是它没有很好地集成到WSDL中。 2)我从Intuit网站下载了QuickBooks WSDL,并使用WSDL2Java(在Axis2中)生成一个名为QBWebConnectorSvcStub.java的巨型(10K LOC).java文件。 3)我尝试扩展类并重写方法,但我一直遇到很多异常/错误。 4)然后我尝试编辑QBWebConnectorSvcStub类的源代码,特别关注某些方法(首先编辑authenticateserverVersionclientVersion,因为这样做了QBWC首先要求的是什么。对于这些方法,我将返回值绑定到Clojure类中的函数,将QBWebConnectorSvcStub方法的输入传递给相应的Clojure函数并返回所述函数的输出。基本上我让Clojure函数完成工作,QBWebConnectorSvcStub充当SOAP中间人。 5)此时,我回到了与之前相同的错误(虽然幸运,clientVersion按预期工作,如日志所示:Received from clientVersion() following parameter:<clientVersionRet="">

QBWebConnector.SOAPWebService.do_authenticate() : Authenticating to application 'QBWebConnectorSvcStub', username = 'alexandergunnarson'
QBWebConnector.SOAPWebService.do_authenticate() : *** Calling authenticate() with following parameters:<userName="alexandergunnarson"><password=<MaskedForSecurity>
QBWebConnector.SOAPWebService.do_authenticate() : QBWC1012: Authentication failed due to following error message.
Object reference not set to an instance of an object.

为此,SOAP输出到QuickBooks是:

 <ns:authenticateResponse xmlns:ns="http://developer.intuit.com/">
    <return xmlns:ax22="http://io.java/xsd" xmlns:ax21="http://rmi.java/xsd" xmlns:ax25="http://developer.intuit.com/xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ax25:QBWebConnectorSvcStub_AuthenticateResponse">
      <authenticateResult>
        <string xmlns="http://developer.intuit.com/">
          my-session-token
        </string>
        <string xmlns="http://developer.intuit.com/">
          nvu
        </string>
        <string xmlns="http://developer.intuit.com/">
          60
        </string>
        <string xmlns="http://developer.intuit.com/">
          60
        </string>
      </authenticateResult>
    <authenticateResultSpecified>
      true
    </authenticateResultSpecified>
  </return>
</ns:authenticateResponse>

幸运的是(!)现在只有一个返回值,与以前不同。

看了example working authenticate SOAP request后,或许还有一个问题,因为我拿出了SOAP信封/标题?他们给我带来了nullPointerExceptions等问题。我会尝试将它们放回去。

最后的话

这次痛苦冒险的下一部分现在是here

1 个答案:

答案 0 :(得分:1)

我不确定您的QBC文件是什么样的(为Quickbooks Web Connector定义应用程序的xml文件),但我通过更改样式设置修复了类似的问题

<Style>RPC</Style>

<Style>DocWrapped</Style>

如果未定义,您可能需要尝试“DocWrapped”或“RPC”值。来自QBWC_proguide

的样式详情
  

Web服务使用的SOAP编码样式。如果没有提供,   使用的默认值是Document。   Document是.NET使用时的标准编码风格   [WebMethod]属性应用于函数声明。   (可选)您可以指定DocWrapped值。 DocWrapped   与我们构建的Axis Web服务非常好地互操作   建议使用WSDL2Java从中生成Java Web类   Web连接器使用的标准WSDL(http://   developer.intuit.com/uploadedFiles/Support/   QBWebConnectorSvc.wsdl)   或者,您可以选择指定值RPC。 RPC风格是   Java类所用的Axis使用的标准编码样式   通过JWS或自动转换为SOAP服务   Java2WSDL工具。