Wednesday, November 10, 2010
Registering multiple adapter types within the same process is not a supported configuration
The Messaging Engine failed to register an adapter "WCF-WSHttp". Details: "Registering multiple adapter types within the same process is not a supported configuration. For e.g. HTTP and SOAP receive adapters cannot co-exist in the same process"
What seemed to be the issue was that different BizTalk Transport Types (one being WCF-WSHttp and the other being WCF-BasicHttp) were being associated to the same IIS App Pool. Creating a new App Pool for a particular Transport Type (or properly re-assigning the web-site's App Pool designation) should do the trick.
Make sure when you set up your BizTalk web apps (web sites in IIS) that you separate your App Pools based on your BizTalk Transport Types properly.
Wednesday, June 9, 2010
BAM WebServices authentication
One of the things that I did was to use the identity (credentials) from the BAM app pool configuration within Computer Management console and used that as the owner of the database.
use BAMPrimaryImport
go
sp_changedbowner 'domain\user' -- Identity from BAM app pool
go
Also, depending on how you installed BizTalk, you may get your own user account (or more exact, the individual who installed BizTalk) set as owner for all BizTalk databases, which was also the case for me. Those databases outside of BAMPrimaryImport should be set to sa.
At that point, you can use the BM.exe command line to add the proper accounts to each view, as stated on Microsoft's site. In this case, I added the BizTalk Administrator group for each view. You can expand on that on a case by case scenario.
Bruce
Friday, February 26, 2010
BizTalk 2009 and SQL Server Database Aliases
We are in the middle of installing BizTalk 2009 at my current company. Our database guru decided that all future databases would use database CNames, making the databases a little more flexible if future changes are needed. Flexibility is always a good thing.
A bit of background:
- We have a clustered SQL Server 2008 environment (Active/Passive failover) that BizTalk is using.
- We are installing most of the BizTalk install options.
- We are installing UDDI 3.0 and ESB 2.0 as well (LOTS of blog material on these two to come).
Unfortunately, we ran into problems with the BizTalk Server Configuration tool, as it's not consistent with itself. The Enterprise SSO and BizTalk Rules Engine configurations accept the CName just fine. However, the Group and BAM Tools don't recognize the CName at all... Maybe there were different developers between these sections?
Our database admin came up with another idea: use an alias in the SQL Server Configuration Manager, as shown below. We acknowledge that it wasn't the best solution, but it does allow us to have a single place where we can change the database name if needed.
That worked just fine for the BizTalk Configuration itself.
However, we ran into problems with this with the UDDI and ESB installs. Neither CNames nor Aliases worked - we had to put in the actual SQL Server name!
If anything, it's VERY inconsistent at best. Hopefully Microsoft will recognize this and make changes so that all setups/installers are consistent with each other.
There's also some more entries from Andy Morrison, who is helping me with the install.
Tuesday, January 26, 2010
BizTalk 2009 BAM Installation Frustration - SSIS jobs installed in wrong location with named database instances
This leads to problems when installing BAM – in particular the SSIS packages.
Background: SSIS does not install on instances – meaning it is installed at the root of the SQL Server servername structure. Therefore, if you install the BizTalk databases on its own SQL instance (servername\biztalk for example), you won’t see the BAM SSIS packages.
The problem is that SSIS doesn’t recognize instances, so you get an error much like below if you try:
The BizTalk 2009 installer doesn’t give you the option to configure the locations for these, so there's no way to fix this up front.
The packages DO get installed to SQL Server, but to the folder structure of the database instance rather than the root servername. If you log onto Integration Services using your root servername, you will get in, BUT you won’t see the SSIS packages.
The solution is to manually(!) migrate the packages to the proper (folder) instance – the root servername (not the instance), as shown below:
You may need to verify/validate the connection strings of the packages – I don’t think there were any changes, but you may want to do this to be safe.
Thursday, September 3, 2009
BizTalk ESB Exception Notification, ESB UDDI Publishing services won't start on boot
After each time I would boot up the machine, I would get the almighty "At least on service has failed" message. After looking into the event viewer, I noticed two outstanding errors:
'Microsoft.Practices.ESB.AlertService.AlertException' occurred and was caught.
and
Cannot open database "ESBAdmin" requested by the login. The login failed.
However, if I manually started the BizTalk ESB Exception Notification and BizTalk ESB UDDI Publishing services after all services completely started, they would start up just fine.
Both appeared to be database errors. To a degree they are, but I think it's because the MSSQLSERVER service hasn't completely finished "starting up".
It also seemed to me that the ESB services were starting before the BizTalk Server services, which didn't make much sense to me.
My solution was to create two entries in the registry:
1)Navigate to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\BizTalk ESB Exception Notification
2) Create a new multi-string value called DependOnService (case-sensitive)
3) Add entry to this value: BTSSvc$BizTalkServerApplication
Do the same thing with HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\BizTalk ESB UDDI Publishing. I also added MSSQLSERVER and SQLSERVERAGENT values to the two, just to be safe.
Now my services are starting like they should when a restart/bootup occurs on the BizTalk server.
Wednesday, May 27, 2009
Happy Belated Memorial Day
B
Thursday, October 16, 2008
Figuring it all out: Replacing an XML node with a different node using XmlNode.ReplaceChild and .ImportNode
I'm working on a project that needed to do a seemingly simple thing: based on a parent node element, do a SQL query (results as xml) and then replace the result set into the existing message.
In other words, I needed to update a message with xml from a database call result.
The original xml message had the structure, but not the data. I thought it would be inefficient to loop through all nodes.
My findings on how to do this were slightly ambiguous, and most examples I looked and put into my code usually resulted in the infamous "The node to be removed is not a child of this node" error or some other ambiguous object error message.
The XmlNode.ReplaceChild(new child, old child) assumes that both child nodes are from the same document (I think - maybe the experts out there can input on this). In my case, this wasn't true, since the "new child" was a result from a SQL query.
Here's the original message, in simplified terms:
<internal>
<routing>
<step>
</step>
</routing>
</internal>
My SQL query resulted in:
<routing>
<step>
<sequence>1</sequence>
<time>12:00</time>
</step>
<step>
<sequence>2</sequence>
<time>12:30</time>
</step>
</routing>
And I needed to get to:
<internal>
<routing>
<step>
<sequence>1</sequence>
<time>12:00</time>
</step>
<step>
<sequence>2</sequence>
<time>12:30</time>
</step>
</routing>
</internal>
The code to complete this isn't exactly straightforward, but the important code is short. Here's how I did it:
// load XML from file and assign xPath location for node
XmlDocument docOriginal = new XmlDocument();
docOriginal.Load("C:\\test.xml");
string strNode = "/request/internal/routing";
// now get SQL from stored procedure
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@ID", strTPID));
cmd.Parameters.Add(new SqlParameter("@Process", strTPP));
conn.Open();
// load returned XML SQL into XmlDocument
XmlDocument docSQL = new XmlDocument();
using (XmlReader reader = cmd.ExecuteXmlReader())
{
docSQL.Load(reader);
}
The next three lines of code are what actually do the magic:
XmlNode oldNode = docOriginal.SelectSingleNode(strNode);
XmlNode newNode = docOriginal.ImportNode(docSQL.DocumentElement, true);
oldNode.ParentNode.ReplaceChild(newNode, oldNode);
return docOriginal;
There's a little bit going on here to fully understand and appreciate this:
- The first line explains itself – get the node that I want out of the xml document I loaded from file.
- This piece initially was a little hard for me to comprehend, which was the crux of my frustration. The .ReplaceChild in the next line of code seemingly must have the child nodes from the same xmlDocument. Therefore I could not just take any xml and slap it in. The .ImportNode command assigns the SQL result to a new node via docOriginal. So effectively we are saying: take the SQL result and create a new node based on the docOriginal XmlDocument.
- Step 3 is now self-explanitory and now you don't get those darn error messages.