LotusScript Web Services and NullPointerException

von Bernd Hort,
assono GmbH, Standort Hamburg,

Letztens habe ich für einen Kunden an einer Demo Anwendung für die Verwendung von Web Service Consumer in LotusScript gearbeitet. Dabei habe ich ziemlich lange die Ursache für einen java.lang.NullPointerException Fehler gesucht. Dieser Blogeintrag richtet sich an jeden, der vielleicht in das gleiche Problem hineinläuft. Denn ehrlich gesagt, war die Lösung im Nachhinein betrachtet, sehr einfach.

Ich verrate ihn erst die Lösung und die technischen Einzelheiten ein bisschen weiter unten. Auch wenn Sie die technischen Einzelheiten im Moment nicht interessieren, sollten Sie sich einen Punkt merken:

LotusScript Web Services Consumer und Provider verwenden intern Java und Java unterscheidet zwischen Groß- und Kleinschreibung. Wenn man dieses nicht berücksichtigt, verliert man Stunden bei der Suche nach einem Fehler, der nicht existiert.

Hier sind die technischen Details.

Bei der Demo-Anwendung ging es unter anderem um die verschiedenen Typen von WSDL Dateien bei der Implementierung von Web Service Providern. Es existiert ein großartiger Artikel auf IBM developerWorks Which style of WSDL should I use? zu dem Thema. Er ist sehr zu empfehlen!

Um die Unterschiede zwischen RPC/encoded und Document/literal WSDL Typen zu zeigen, habe ich zwei Web Service Provider implementiert. Beide Provider verwenden den absolut identischen LotusScript Code.

Dann implementierte ich zwei Web Service Consumer, in dem ich die WSDL Dateien von den zuvor erstellten Web Service Providern importierte. Hier sind nun die beiden entscheidenden Methoden aus den Web Service Consumern.

Web Service Consumer Aufruf eines RPC/encoded Web Service Provider
Web Service Provider RPC/encoded Settings

Function checkout_status(auftragnr As String) As String
  If Not IsDebugMode Then On Error Goto errorHandler
  On Error lsERR_NOTES_WSENGINE_UNINIT_METHOD_ARG Goto wsErrorHandler
  On Error lsERR_NOTES_WSENGINE_NOTINIT Goto wsErrorHandler
  On Error lsERR_NOTES_WSENGINE_ERROR Goto wsErrorHandler
  On Error lsERR_NOTES_WSENGINE_METHOD_ERROR Goto wsErrorHandler
  On Error lsERR_NOTES_WSENGINE_METHOD_FAULT Goto wsErrorHandler
  
  Let checkout_status = Service.Invoke("checkout_status", auftragnr)
  
  Exit Function
  
errorHandler:
  If HandleErrorWithContext(CreateErrorContext(Nothing,|auftragnr: "| & auftragnr & |"| )) = RESUME_NEXT_LINE Then Resume Next
  Call RethrowError()
  Exit Function
  
wsErrorHandler:
  If HandleErrorWithContext(CreateErrorContext(Nothing,|auftragnr: "| & auftragnr & |"| )) = RESUME_NEXT_LINE Then Resume Next
  Call CreateWebServiceLogEntry(Me, |auftragnr: "| & auftragnr & |"|, Nothing)
  Call RethrowError()
End Function

Web Service Consumer Aufruf eines Document/literal Web Service Provider
Web Service Provider Document/literal Settings

Function checkout_status(auftragnr As String) As String
  If Not IsDebugMode Then On Error Goto errorHandler
  On Error lsERR_NOTES_WSENGINE_UNINIT_METHOD_ARG Goto wsErrorHandler
  On Error lsERR_NOTES_WSENGINE_NOTINIT Goto wsErrorHandler
  On Error lsERR_NOTES_WSENGINE_ERROR Goto wsErrorHandler
  On Error lsERR_NOTES_WSENGINE_METHOD_ERROR Goto wsErrorHandler
  On Error lsERR_NOTES_WSENGINE_METHOD_FAULT Goto wsErrorHandler
  
  Let checkout_status = Service.Invoke("CHECKOUT_STATUS", auftragnr)
  
  Exit Function
  
errorHandler:
  If HandleErrorWithContext(CreateErrorContext(Nothing,|auftragnr: "| & auftragnr & |"| )) = RESUME_NEXT_LINE Then Resume Next
  Call RethrowError()
  Exit Function
  
wsErrorHandler:
  If HandleErrorWithContext(CreateErrorContext(Nothing,|auftragnr: "| & auftragnr & |"| )) = RESUME_NEXT_LINE Then Resume Next
  Call CreateWebServiceLogEntry(Me, |auftragnr: "| & auftragnr & |"|, Nothing)
  Call RethrowError()
End Function

Sehen Sie den Unterschied? Ich nehme an, es ist leichter, nachdem ich Ihnen die Lösung verraten habe.

In der Document/literal Version muss die Zeile für den eigentlichen Aufruf des Web Services lauten
Let CHECKOUT_STATUS = Service.Invoke("CHECKOUT_STATUS", auftragnr)
Zu beachten ist die Großschreibung bei CHECKOUT_STATUS.

Ich habe es herausgefunden, weil ich den zunächst generierten LotusScript Code um Fehlerbehandlungsroutinen ergänzt habe. Kein Code ist vollständig ohne Fehlerbehandlung. Das gilt insbesondere für die Verwendung von Web Services.

Da ich ein fauler Programmierer bin, habe ich den Code von einem Web Service Consumer zum anderen kopiert, ohne auf die Groß- und Kleinschreibung zu achten. Dem entsprechend war ich sehr erstaunt, als der eine Web Service Consumer ohne Probleme funktionierte und der zweite eine java.lang.NullPointerException zurück lieferte.

Nachdem ich diverse Fehlerursachen ausgeschlossen hatte, habe ich einen neuen Web Service Consumer generieren lassen. Dabei ist mir der Unterschied aufgefallen.

Die Ursache liegt wie oben schon angedeutet in der internen Verwendung von Java. Während des Aufrufes von Service.Invoke wird im Hintergrund die Java Reflection API verwendet, um die zugehörige Methode zu finden und aufzurufen. Die zwei unterschiedlichen WSDL Typen führten zu zwei unterschiedlichen Methodennamen: checkout_status und CHECKOUT_STATUS. In LotusScript kann die Groß- und Kleinschreibung vernachlässigt werden. In Java kann man Stunden damit verbringen, nach einem Fehler zu suchen, wenn man nicht darauf achtet.

Selbstverständlich wäre ich dem Problem von vorne herein aus dem Weg gegangen, wenn ich gleich Java für die Web Service Consumer bzw. Provider verwendet hätte.

Aber das war nicht die Aufgabe. ;-)

Fachbeitrag JavaScript Java Entwicklung Sonstiges

Sie haben Fragen zu diesem Artikel? Kontaktieren Sie uns gerne: blog@assono.de

Sie wollen eine individuelle Lösung? Kontaktieren Sie uns

Weitere interessante Artikel

Sie haben Fragen? Wir sind für Sie da.

Wir verwenden Ihre Daten, um Sie einmalig per E-Mail zu kontaktieren. Wir geben Ihre Daten nicht an Dritte weiter. Siehe: Datenschutzhinweise
assono GmbH

Standort Kiel (Zentrale)
assono GmbH
Lise-Meitner-Straße 1–7
24223 Schwentinental

Standort Hamburg
assono GmbH
Bornkampsweg 58
22761 Hamburg

Telefonnummern:
Zentrale: +49 4307 900 407
Techn. Hotline: +49 4307 900 403
Vertrieb: +49 4307 900 402

E-Mail-Adressen:
kontakt@assono.de
bewerbung@assono.de