Mittwoch, 10. März 2010

BizTalk 2009, 64Bit und Custom Adapter (Wow6432Node Registry)

Wir haben einen eigenen Adapter für BizTalk geschrieben und bisher funktionierte dieser auch tadellos auch unter Windows 2008 64Bit. Nun hatten wir das Problem, das dieser Adapter nicht gefunden wurde bei einer Kundeninstallation, auch Windows 2008 64Bit.

Mit Process Monitor habe ich herausgefunden, das auf unserem Referenzsystem BizTalk 2009 die Adaptoren in der 32Bit Registry sucht (Wow6432Node). Bei dem Kundensystem war der Adapter dort nicht registriert, lediglich in der 64Bit Registry. Den Knoten habe ich dann herausexportiert und dann lediglich den Wow6432Node im Pfad ergänzt und wieder neu importiert in die Registry:

HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\...

wird zu:

HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Wow6432Node\CLSID

Und schon wurde der Adapter im BizTalk gefunden

Was mich irritiert ist, wieso wird unser dazugehöriges Registry File auf unserem Referenzsystem korrekt in den 32Bit Knoten importiert und auf dem Kundensystem nicht? Der Mechanismus dazu ist mir nicht wirklich klar.

Zum Hintergrund es gibt zwei Regedt32.exe. Eine ist für 64Bit Zugriffe zuständig und liegt (verwirrender Weise) im %windir%\System32 Verzeichnis. Das Regedt32.exe für den 32Bit Zugriff wiederum liegt im %windir%\SysWow64 Verzeichnis. Ein Ausführen des Registry Files explizit mit dieser führte zu keinem Ergebnis, lieferte allerdings auch keinen Fehler zurück...

Unter 64Bit ist der Registry Zugriff schon etwas verwirrend, aber prinzipiell logisch:
- x86 Appliktaion, 32Bit Platform: Zugriff auf 32Bit Registry
- x86 Applikation, 64Bit Platform: Zugriff auf 32Bit Registry (Wow6432Node)
- x64 Applikation, 32Bit Platform: geht nicht
- x64 Applikation, 64Bit Platform: Zugriff auf 64Bit Registry
- AnyCPU Applikation, 32Bit Platform: Zugriff auf 32Bit Registry
- AnyCPU Applikation, 64Bit Platform: Zugriff auf 64Bit Registry

Um auf die jeweilige nicht Standard Registry vom Programmcode zuzugreifen (Alternate Registry View) muss man dann mit RegOpenKeyEx arbeiten: http://msdn.microsoft.com/en-us/library/ms724897(VS.85).aspx (habe dazu dieses Example gefunden)

Mittwoch, 3. März 2010

BizTalk 2006 BAM EventBus Service Error Event

Fehlermeldung im BizTalk Application Event Log:

Event Type: Error
Event Source: BAM EventBus Service
Event Category: None
Event ID: 25
Date: 3/1/2010
Time: 6:44:58 PM
User: N/A
Computer: BES086.comlineag.cl.local
Description:
Either another TDDS is processing the same data or there is an orphaned session in SQL server holding TDDS lock.Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. SQLServer: BES082, Database: BizTalkDTADb.


Das Problem mit Lösungsvorschlägen ist beschrieben unter
http://support.microsoft.com/kb/841334 (Error Description dazu beachten)

In meinem Fall war die Lösung zu verwaisten Sessions angebracht:
http://msdn.microsoft.com/en-us/library/aa275788(SQL.80).aspx

Die Kurzfassung zur Lösung:

mit der Management Konsole sich auf die BizTalk SQL DB verbinden und exec sp_who als Query ausführen. Das listet die gegenwärtig Session mit ihrem jeweiligen Status und der jeweiligen spid auf. Die 'sa' Sessions interessieren nicht, alle anderen Sessions (bis auf die eigene) kann man dann gegebenenfalls mit dem kill Befehl abschießen (kill <spid>)
Dabei sollte natürlich sichergestellt sein, das der BizTalk in der Zeit nicht auf das System zugreift, bzw. ein anderer User Remote auf dem System arbeitet ;)

Montag, 1. März 2010

BizTalk 2009, SAP Adapter 2.0 und Windows 2008 (32Bit)

Der alte (d.h. nicht WCF) Microsoft SAP Adapter unter Windows 2008 (32Bit) in Verbindung mit BizTalk 2009 kann ganz schön bockig sein...


Als erstes müssen folgende Vorraussetzungen erfüllt sein, damit der Adapter überhaupt funktioniert (unabhängig von BizTalk Version und Betriebssystem):
1. Installation der SAP eigenen DLLs, enthalten im SAP Frontend Package
2. Installation des Microsoft SAP .NET Connectors 1.0.3 (!Nicht 2.0!)
3. Installation des Microsoft BizTalk Adapter 2.0 for MySAP SP1 (unbedingt die SP 1 Version)
und das muss zudem in genau dieser Reihenfolge passieren!

Dann sollte man in einer restriktiven Umgebung unbedingt abprüfen, ob der SAP Adapter seine Datenbanktabelle und Stored Procedures angelegt hat:
1. In der Datenbank BizTalkMsgBoxDb muss eine SAPTid Table angelegt worden sein
2. Zudem müssen in der gleichen Datenbank folgende Stored Procedures existieren:
mp_sap_check_tid
mp_sap_delete_tid
mp_sap_insert_tid

sollte das nicht der Fall sein, muss mit einem geeigneten User nochmals die BizTalkSAPConfig.exe über Kommandozeile mit /i aufgerufen werden. Diese ist recht schweigsam und meldet sich nur im Fehlerfall mit einem Error Fenster.

Ist das geschehen muss sichergestellt sein, das Execution Rechte des BizTalk Users in der Datenbank auf vom SAP Adapter angelegten Stored Procedures existieren (BTS_HOST_USERS)

Ist das alles geschehen sollten zumindestens die RFC Aufrufe reibungslos passieren, sowie das Abrufen der Schemas für IDOCs und BAPI Bausteine funktionieren.


Was uns dann noch Kopfzerbrechen bereitete war, das IDOCs nicht empfangen werden konnten. Im SAP wurde unter der Transaktion SM58 ein "TARGET_METHOD_EXCEPTION raised by external server" Fehler zurückgemeldet. Unter BizTalk passierte gar nichts. Keine Fehlermeldung und keine sonstigen Einträge z.B. im Eventlog.

Nach einer Studie der Logs mit dem Process Monitor von Microsoft kam mir die Vermutung das BizTalk seine "Microsoft.BizTalk.SAPAdapterProperties.dll" nicht finden kann. D.h. er findet sie schon, allerdings sucht er sie zuerst immer im GAC_32, obwohl er seinen Adapter später im GAC findet, scheint dies trotzdem im weiteren Verlauf zu Problemen zu führen (z.B. unzählige Buffer Overflows, in den Pipeline Komponenten)

Als Problemlösung habe ich die "Microsoft.BizTalk.SAPAdapterProperties.dll" schlichtweg in den Ressourcen meines BizTalk 2009 Projekt referenziert (so wie ich es schon früher bei diesem Problem getan habe: http://justacodeblog.blogspot.com/2008/09/biztalk-und-sap-adapter-error.html). Danach funktionierte der IDOC Empfang wieder reibungslos. Ich vermute es reicht auch aus, die SAP Adapter Installation einfach vom GAC ins GAC_32 Verzeichnis manuell zu verschieben.

Nachtrag: Der Fehler TARGET_METHOD_EXCEPTION raised by external server tritt auch auf wenn das aus SAP abgerufene Schema nicht auf dem aktuellsten Stand ist.

Dienstag, 9. Februar 2010

BizTalk 2009 Issues unter VS2008

Seit wir mit BizTalk 2009 unter Visual Studio 2008 entwickeln, haben wir immer wieder heftige Probleme mit referenzierten Projekten. Und zwar vornehmlich dann, wenn sich diese innerhalb der gleichen Solution befinden. Nach unseren letzten Problemen hab ich mich auf die Suche gemacht und Blogeinträge mit den gleichen Erfahrungen gefunden:

Freitag, 22. Januar 2010

BizTalk dynamischer Sendport - uninitialized dynamic port

Beim kompilieren eines BizTalk Projektes unter VS2008 mit einem dynamischen Send Port, bekam ich die Fehlermeldung "uninitialized dynamic port"

Eine google Recherche ergab, dass dies auf das nicht gesetztes Property des Send Ports Microsoft.XLANGs.BaseTypes.Address hinweist. Das dumme nur war es ist gesetzt gewesen, aber in der falschen (!) Reihenfolge.

Zuerst hatte ich nämlich das Property Microsoft.XLANGs.BaseTypes.TransportType gesetzt und dann Microsoft.XLANGs.BaseTypes.Address.

Also:
myDynamicSendPort(Microsoft.XLANGs.BaseTypes.TransportType) = "My Type" myDynamicSendPort(Microsoft.XLANGs.BaseTypes.Address) = "My UNC"

-> build failed: uninitialized dynamic port

Aber:

myDynamicSendPort(Microsoft.XLANGs.BaseTypes.Address) = "My UNC" myDynamicSendPort(Microsoft.XLANGs.BaseTypes.TransportType) = "My Type"

-> build succeded


...its not a bug, its a feature :P

Montag, 5. Oktober 2009

Bool-Shit

if (request.getParameter("x") != null && ( (String) request.getParameter("x")).equalsIgnoreCase("1") || request.getParameter("x") == null ) {[...]}

Dienstag, 15. September 2009

java.lang.NoSuchMethodError: java/lang/String.isEmpty()Z

Die Methode String.isEmpty() ist (wie in der JavaDoc unschwer ersichtlich) zwar erst ab Java 1.6 verfügbar, dennoch ist es möglich, Programme mit Compiler compliance level 1.5 (bei einem 1.6er JDK) zu compilieren, ohne dass der Compiler die Methode ankreidet. Erst beim versuch, die Methode in einer Umgebung mit Java 5 laufen zu lassen äußert sich der Fehler durch die, in der Überschrift genannte Exception. Sollte man also nicht 100%ig sicher sein, welche JRE auf der Zielumgebung läuft so ist weiterhin das gute alte .equals("") bzw. das ab prüfen über die Länge die sicherere Variante.

Freitag, 31. Juli 2009

Anwendung nicht im Alt + Tab - Fenster anzeigen

Manches mal hat man die Anforderung, dass eine Applikation nicht in dem Fenster angezeigt werden soll, das aktiv wird, wenn man die Tastenkombination Alt + Tab verwendet, um zwischen den laufenden Applikationen umzuschalten.

Eine kurze, prägnante und gute Anleitung dazu ist mir unter http://www.csharp411.com/hide-form-from-alttab/ über den Weg gelaufen. Das soll hier einfach mal für den Fall vermerkt werden, dass ich mal in die Verlegenheit kommen sollte. Zudem hilft es ja vielleicht auch dem ein oder anderen weiter.

Dienstag, 14. Juli 2009

MSDN Webcast

Da mittlerweile stattliche 750 MSDN-Webcasts abrufbar sind, wollte ich darauf einmal aufmerksam machen falls es jemand noch nicht kennen sollte :) MSDN-Webcasts

Dienstag, 7. Juli 2009

Microsoft Message Queue MSMQ

Vor einigen Wochen habe ich einen Crashkurs innerhalb weniger Stunden in Sachen MSMQ durchlaufen müssen, an dessen Ende eine Biztalk Lösung stand. Da ich auf einige Hindernisse gestoßen war, fasse ich mal meine Erfahrungen zusammen.

Kurz gesagt, MQ dient der asynchronen Kommunikation zweier Applikationen. Und das auch über Rechnergrenzen, oder gar Domänengrenzen hinweg. Dazu legt nach dem FIFO Prinzip eine Anwendung auf ihrem System Nachrichten ab, und eine andere lauscht auf die Adresse und greift die Nachricht ab. MSMQ kann sich dabei verschiedener Kommunikations Protokolle bedienen. (engl. Einführung in MSMQ)

MSMQ unterstützt gegenwärtig drei Queue Typen:
- Public Queues (benötigt Active Directory, Adressen werden dort direkt veröffentlich und sind von allen in der selben AD erreichbar, bzw. über Domängrenzen über Replikation)
- Private Queues (benötigt kein AD, die Adresse muss der empfangenden Anwendung daher aber auch bekannt sein, selbst mit AD!)
- Transaktions Queues (Sicherheit verbunden mit hohen Overhead Kosten)

Zum Entwickeln empfehlen sich Hilfstools, denn das größte Problem meines Erachtens (eigentlich das Einzige das ich hatte) ist die Kommunikationsinfrastruktur zu konfigurieren, solange man nicht eine sehr simple Netzwerkstrutur vor sich hat.

Zu einem gibt es dafür von MS das MQBench Paket und dann noch von Cogin ein freies MSMQ First Aid Kit.

Im bin Verzeichnis von MQBench gibt es 2 Tools: MSMQRecv bzw. MSMQSend, mit denen man über die Kommandozeile das Empfangen und Senden testen kann. Zum Vorgehen empfiehlt es sich zuerst einmal lokal zu testen, ob die MQ korrekt eingerichtet wurde. Funktioniert das, kann man zum eigentlichen Empfangsrechner über gehen der die Messages später abgreifen soll. Diese Tools haben aber einen Nachteil, sie unterstützen nur den Typ Public Queue, da sie nur das Pathnamen Format beherrschen. Aber der Pathname MUSS im AD nachgeschlagen werden, sobald es über Rechnergrenzen hinweg geht, d.h. Lokal funktionieren Pathnamen auch wunderbar mit Privat Queues!

Beispiel lokaler(!) Zugriff auf private MQ:
msmqrecv .\private$\MeineTestNachrichten

Remote Zugriff:
msmqrecv <rechnername>\private$\MeineTestNachrichten
-> Error: 0xc00e0003 (= Queue Not Found)
(geht nicht, Path wurde nicht in AD publiziert, da privat!)


Anmerkung: ein Versuch das ganze mit einem Formatname anstatt Pathname aufzurufen führt zu einem 0xc00e0014 (= Illegal Queue Pathname), die Tools können nur Pathname!

Das selbe gilt leider auch für das FirstAidKit!

Wie aber Eingangs erwähnt, unterstützt MSMQ unterschiedliche Kommunikationprotokolle, wie z.B. TCP. Dadurch hat man also die Möglichkeit ohne AD Lookup direkt auf die MQ eines anderen Rechners zuzugreifen. Um aber den Protokoll Zugriff beschreiben zu können, benötigt man das Direct Format Name Format. Da ich kein freies Tool kenne das einem das abnimmt, hab ich mir kurzerhand was in .NET zusammengecoded.

(Eine Anmerkung zum MSMQ Biztalk Adapter, dieser unterstützt das "Direct Format Name" Format ebenfalls von Haus aus.)

Unter System.Messaging gibt es im .NET Framework das richtige Werkzeug dazu:

...
MessageQueue mq = null;
bool cr = false;
string strFormatnameaddress = @"FormatName:DIRECT=TCP:192.168.1.114\test";
 
try
{
   msg.Priority = MessagePriority.Normal;
   mq = new MessageQueue(strFormatnameaddress);
 
   cr = mq.CanRead;
}
catch (System.Messaging.MessageQueueException ex)
{
   Console.WriteLine("MSMQ Error: " + ex.ToString());
}
catch (Exception ex)
{
   Console.WriteLine("Error: " + ex.ToString());
}
finally
{
   mq.Close();
}
 
return cr;
...

Das CanRead Flag gibt uns auf jeden Fall Informationen dazu, ob wir nun überhaupt auf die MQ zugreifen können, oder nicht. Jedenfalls ist die Programmierung sehr simpel, das gilt auch für das empfangen, bzw. senden von Messages:
...
// empfang aller Messages in der MQ
Message[] msgs = mq.GetAllMessages(); 
 
...
 
// senden einer Message in die MQ
Message msg = new Message();
msg.Label = "Test Message";
msg.Body = "Das ist nur ein Test";
mq.Send(msg);
...

Das eigentliche Problem fängt nun da an, wenn man keinen Zugriff auf die Message Queue bekommt. Das läßt sich in der Regel auf Security Einstellungen zurückführen. Was kein großes Problem ist, solange man sich am gleichen AD befindet und man über den Pathnamen zugreifen will (Es reicht in der Regel dem User des lesenden Rechners einfach die Zugriffsrechte auf die MQ zu gewähren, notfalls den Anonymus Access erlauben). Befindet man sich in unterschiedlichen AD (aber noch unter dem gleichen Forrest) benötigt man eigentlich nur noch zusätzlich eine funktionierende AD Replikation für den Pathnamen Zugriff. Ansonsten sollte in der Regel der Direct Format Name Zugriff funktionieren.

Was aber wenn sich die Rechner in unterschiedlichen Forrests befinden? Die unterschiedlichen Forrests müßen sich diese Vertrauen, und das bedeutet entweder Zertifikate, oder die "Umsonst"-Variante: ein Loch in die "Mauer schlagen". Dazu benötigt es nicht viel mehr als eines zusätzlichen Eintrages in die Registry des MQ Servers:
http://msdn.microsoft.com/en-us/library/cc236138(PROT.10).aspx
1.) HKLM\Software\Microsoft\MSMQ\Parameters\security\NewRemoteReadServerAllowNoneSecurityClient dword = 1
2.) Zugriffsrechte für Anonymus

Das gibt dem Admin sicherlich richtige Magenschmerzen ;)


Dazu hat John Breakwell von Microsoft, der einem auch bei einem Microsoft Call Support leistet, ein ausführliches Blog verfasst. Folgende Einträge beschäftigen sich mit MSMQ und Rechnern in unterschiedlichen Forrests: http://blogs.msdn.com/johnbreakwell/archive/2008/02/14/how-do-i-send-msmq-messages-between-domains.aspx http://blogs.msdn.com/johnbreakwell/archive/2008/06/27/cross-forest-msmq-you-need-to-be-trusting.aspx http://blogs.msdn.com/johnbreakwell/archive/2008/10/13/authenticating-msmq-messages-between-forests.aspx