Проблема аутентификации с использованием QuickBooks Web Connector: ссылка на объект не установлена на экземпляр объекта

1

(Да, я понимаю, что этот вопрос похож на другой вопрос, но на этот вопрос никогда не отвечали.)

Задача

Я пытаюсь использовать Clojure с Axis 2 для доступа к данным QuickBooks с помощью QuickBooks WebConnector (теперь QBWC). QBWC использует SOAP для связи с внешними приложениями, поэтому, почему мое приложение Clojure использует Axis 2 в качестве SOAP-интерфейса. Я использую micha clj-soap от GitHub для обеспечения более сложного (абстрагированного) взаимодействия Clojure с Java-вызовами Axis 2.

вопрос

Проблема заключается в аутентификации моего веб-сервиса SOAP с помощью QBWC. Используя метод authenticate моего веб-сервиса SOAP, 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, который определяет веб-службу SOCAccess для сервера Axis 2, который я использую.

(Для тех, кто не знаком с Clojure, но знаком с Java, следующий код создает класс под названием developer.intuit.com.SOCAccess и определяет ряд методов, которые необходимы для связи с QBWC (включая authenticate, serverVersion и т.д.). укажите тип возврата или параметра. 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-вызовы

Однако, когда я делаю вызов SOAP (authenticate "my-username" "my-password") на моем веб-сервисе в JVM, который я запускаю, возвращаемое значение должно быть String[] и выводом println() показывает, что это действительно String[] но возвращаемое значение показано как только первый элемент массива, что странно. Я предполагаю, что это является причиной того, что Object reference not set to an instance of an object на Object reference not set to an instance of an object ошибки из QBWC, поскольку она пытается получить n-й элемент String как если бы это был массив.

========

Есть предположения? Я понимаю, что это долгий вопрос. Позвольте мне знать, что еще вы хотели бы мне предоставить в виде кода, WSDL и т.д.

Благодарю!

ДОБАВЛЕНИЕ: Файл журнала

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.

ДОБАВЛЕНИЕ: 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) Я загрузил QuickBooks WSDL с сайта Intuit и использовал WSDL2Java (в Axis2) для создания мегалитического (10K LOC).java файла с именем QBWebConnectorSvcStub.java. 3) Я попытался расширить класс и переопределить методы, но я продолжал получать множество исключений/ошибок. 4) Затем я попытался отредактировать исходный код класса QBWebConnectorSvcStub, в частности, сосредоточив внимание на некоторых методах (serverVersion редактирование authenticate, serverVersion и clientVersion потому что это то, что сначала вызывает 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>

К счастью (!) В настоящее время существует только одно возвращаемое значение, в отличие от предыдущего.

Взглянув на пример, работающий с подтверждением SOAP-запроса, возможно, есть проблема, потому что я достал конверт SOAP/заголовки? Они давали мне проблемы с nullPointerExceptions и т.д. Я попытаюсь вернуть их обратно.

ЗАКЛЮЧИТЕЛЬНОЕ СЛОВО

Следующий взнос этого болезненного приключения теперь здесь.

  • 0
    Вы знаете, как на самом деле выглядит ответ SOAP, который вы отправляете в Web Connector? Можете ли вы опубликовать это и многое другое из файла журнала?
  • 0
    Большое спасибо за быстрый ответ! Я разместил файл журнала и запрос / ответ SOAP.
Показать ещё 4 комментария
Теги:
soap
clojure
quickbooks
axis2

1 ответ

0

Я не уверен, как выглядит ваш файл QBC (файл xml, где ваше приложение определено для Quickbooks Web Connector), но я исправил аналогичную проблему, изменив параметр Style из

<Style>RPC</Style>

в

<Style>DocWrapped</Style>

Вы можете попробовать значения "DocWrapped" или "RPC", если они не определены. Детали для стиля из QBWC_proguide:

Стиль кодирования SOAP, используемый вашим веб-сервисом. Если не указано, по умолчанию используется документ. Документ - это стандартный стиль кодирования, используемый.NET, когда к объявлению функции применяется атрибут [WebMethod]. При желании вы можете указать значение DocWrapped. DocWrapped очень хорошо взаимодействует с веб-сервисами Axis, которые построены, как мы рекомендуем, используя WSDL2Java для создания веб-классов Java из стандартного WSDL, используемого веб-коннектором (http://developer.intuit.com/uploadedFiles/Support/QBWebConnectorSvc.wsdl) Или, необязательно, вы можете указать значение RPC. Стиль RPC - это стандартный стиль кодирования, используемый Axis, когда класс Java автоматически преобразуется в SOAP-сервис либо через JWS, либо в инструмент Java2WSDL.

  • 0
    Это здорово! Теперь в журнале написано: This application agrees with the current version of QBWebConnector. Allowing update operation. вместо null . Возвращаемые значения для serverVersion и clientVersion теперь правильные - "3.0" и "" соответственно. Однако ... Object reference not set to an instance of an object на Object reference not set to an instance of an object ошибки Object reference not set to an instance of an object все еще сохраняется. Вместо строкового массива по-прежнему возвращается несколько возвращаемых значений, поэтому QBWC пытается получить первый элемент первого возвращенного значения, но не может. Кроме того, я использовал RPC, потому что я использовал Java2WSDL, согласно справочному документу QBWC.
  • 0
    Кроме того, формат DocWrapped, к сожалению, не исправляет множественные возвращаемые значения. : / Я собираюсь попробовать реализовать класс ArrayOfString вместо использования встроенного массива String [] и посмотреть, поможет ли это.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню