My BizTalk journey
Thursday, May 13, 2010
Exception has been thrown by the target of an invocation
You may get this error when you use BizTalk SAP adapter to call a BAPI in SAP. This error mostly doesn't occur in development machines and it usually happens when you migrate the code to higher tiers(staging server or Production).
The interesting part about SAP is we have got out of box components to generate Schema structures for IDOC and BAPI's. We also have SAP adapter to communicate with SAP. When we want to communicate with SAP using IDOC mode, we don't need to have any assemblies specific to the schemas. However, when we want BizTalk to call a BAPI in SAP, we need to have a dll in the below folder
[BizTalk SAP adapter Installed Directory]\Microsoft BizTalk Adapter v2.0 for mySAP Business Suite\Bin
Before you start sending messages from BizTalk to RFC, you need to first generate schemas from SAP. There are two modes where you can either generate a schema from an IDOC or RFC. When you given your criteria and proceed to generate the schema, the tool generates a dll and places it in the above mentioned folder. Then you go forward and implement your business process and deploy your artifacts and test the application. But you should remember to copy this dll to the target machine where you will deploy the application and where it will be used for testing or live production server.
Hope this will be helpfull for someone.
I didnt find a blog item anywhwere which could have saved me 2 hours of my time.
Vanakkam
Wednesday, November 18, 2009
Illegal use of identifier in expression - BizTalk Orchestration error
I had no idea why this error is popping.
You also get one more error along with this. The error would look something like
Cannot implicitly convert type '' to string.
Actually this gave me some idea where the error was appearing. The only place i had that string was in a variable. I went to that variable in Orchestration View and removed that string. I rebuilded the Project.
Bingo!!!
No errors.
So, the bottom line is, if you have to initialize a string in a variable, you must enclose the initial value in quotation marks in the Properties window. If you want the string to contain a quotation mark, use the backslash as an escape character, and use consecutive backslashes when you want a literal backslash in your string.
Tuesday, November 18, 2008
A message going to a one-way send port is being suspended.
configuration corresponding to the message was not found.
This usually
happens when a send port was deleted while it still had some active messages"
This is a very ackward error that you can't an answer in any of the microsoft documentations.
We found this error in our production system soon after the interface was redployed. We went crazy to think if the redeployment has deleted the send ports.
When we checked event log entries, we also found some SSO erros associated with this. So atleast this gave us a hint that the configuration information has not updated and the host instances thinks that the send ports is not available anymore.
To tackle this problem, we changed the send handler to run under different host instance and resumed the messages.
Hooray, it went through.
So,
1. The error description that microsoft has given is not clear enough to resolve the problem.
2. Even after the host intances that were used for the interface was bounced back, the messages were not going through. So the SSO needs to be restarted for the host instance to work properly. But in production environment, we can't do this. So this is a bug.
Vanakkam.
Wednesday, February 20, 2008
"MessageContextPropertyBase" Magnified
For each and every situation, we can deliver a precise BizTalk solution. Its up to the developer who develops the code. There are some tricks, wherein you get the solution with a less amount of code but is rather vague to a newbie. We were newbies once upon a time and it's time, we have to help them understand the mystical features to them in a easy manner. One of the complex stuff that i found was the MessageContextPropertyBase value in the property schema. So get ready to dive deep into that.
MessageContextPropertyBase
There is a property called Property Schema Base in the property schema. There are actually 3 values
1. MessageDataPropertyBase
2. MessageContextPropertyBase
3. PartContextPropertyBase
We will concentrate on MessageContextPropertyBase in this article. It will be easy if we explain this with an example. isn't?
A legacy application receives purchase orders from SAP and this message should be transformed through BizTalk. The problem here is based on some property different business process needs to be activated. Wait, there is one more catch. The idoc that is recieved from SAP is defined as a dependant schema which is already utilized by other interfaces. So we should design a solution so that the dependant schema project is not altered.
In this scenario, we can create an interface that has an orchestration that can route messages to other business process ( orchestrations ). We need to create a property schema and assign the namespace of the dependant schema. Most importantly , we need to set the value MessageContextPropertyBase to the Property Schema Base. This will actually promote the desired property in the incoming message. In this way we can easily route the incoming message to other business process.
I will upload a sample interface for better understanding.
Vanakkam.
Saturday, February 9, 2008
Maper Pipeline Component
Introduction to Mapping
In a traditional BizTalk project, we use the out of the box BizTalk mapper to map source messages to destination messages. The Biztalk mapper provides us a graphical interface for this mapping task. But sometimes, we hardly need only XSLT to transform the messages. So, we create a map with the source and destination messages. But the actual mapping will be taken from the XSLT file that is included with the project. In that case creating a map is long step in attaining a simple transform process. This gave me an idea of developing the tranform concept in a pipeline component, wherein you don't have to actually create a map for transforming the message.
Audience
- Nothing more complex is dealt here. A fair understanding of BizTalk pipeline component development
- A good knowledge in XML, XPath, XSLT programming in C#
A background of the pipeline component
I have made this component as simple as possible. If you can look into the code for developing a simple decoder pipeline component and then walk through my code, you will understand it better. There are many articles available for developing a
simple decoder pipeline component. So, I am not going in deeper to explain to you the basics of component development.
Actual Implementation
For the custom component development, as we all know by this time, we need to implement some interfaces. So for developing a decoder component we need to implement IComponent
, IBaseComponent
, IPersistPropertyBag
and IComponentUI
interfaces. In our scenario, we need to show a custom dialog box for feeding in the XSLT. This dialog box should be able to be triggerred from the Properties Window for the custom pipeline component in the custom receive pipeline. For implementing it, we need to design a class that derives from UITypeEditor
. The property grid you see in the pipeline editor is a .NET property grid. By default, the grid can only understand string values.
To notify the property grid that you need a dialog box rather than the default text editor, you must perform the following steps.
Implement the UITypEditor
class.
[System.Security.Permissions.PermissionSet
(System.Security.Permissions.SecurityAction.Demand, Name = "
class="code-string">FullTrust")]
class CustomXSLTUITypeEditor : UITypeEditor
{
}
Override the GetEditStyle
method to return a Modal
dialog box.
public override UITypeEditorEditStyle
GetEditStyle
(ITypeDescriptorContext context)
{
// Indicates that this editor can display a Form-based
interface.
return UITypeEditorEditStyle.Modal;
}
Here we override the EditValue
method and provide the implementation for showing up a custom dialog box.
public override
class="code-keyword">object EditValue(
ITypeDescriptorContext context,
IServiceProvider provider,
object value)
{
// Attempts to obtain an IWindowsFormsEditorService.
IWindowsFormsEditorService edSvc =
(IWindowsFormsEditorService)provider.GetService
(typeof(IWindowsFormsEditorService));
if (edSvc == null)
{
return null;
}
// Displays a StringInputDialog Form to get a
user-adjustable
// string value.
using (CustomXSLTPanel form = new
CustomXSLTPanel((string)value))
{
XmlDocument xdoc = new XmlDocument();
if (edSvc.ShowDialog(form) ==
System.Windows.Forms.DialogResult.OK)
{
try
{
xdoc.LoadXml(form.txtXSLT.Text);
return form.txtXSLT.Text.Replace(
class="code-string">"\n","
class="code-string">");
}
catch (XmlException ex)
{
System.Windows.Forms.MessageBox.Show
("The XSLT is invalid. Please try
again",
"Error",
System.Windows.Forms.MessageBoxButtons.OK,
System.Windows.Forms.MessageBoxIcon.Error);
return value;
}
}
}
// If OK was not pressed, return the original value
return value;
}
The CustomXSLTPanel
class is a custom Windows Form that contains a RichTextBox
control that can
be used to get the XSLT input from the user. This is a very simple Form.
Having provided all the basic things needed for our Custom component, we go deep into implementing it. The first thing in
proceeding to our component is to implement the basic interfaces. The code looks like this.
[ComponentCategory(CategoryTypes.CATID_PipelineComponent)]
[ComponentCategory(CategoryTypes.CATID_Decoder)]
[System.Runtime.InteropServices.Guid("
class="code-string">9d0e4103-4cce-4536-83fa-4a5040674ad6")]
public class MapperGUI : IBaseComponent,
IComponentUI,
Microsoft.BizTalk.Component.Interop.IComponent,
IPersistPropertyBag
{
}
We need to implement the IBaseComponent
members for the basic information of our component.
#region IBaseComponent Members
public string Description
{
get
{
return "
class="code-string">Pipeline component used as a BizTalk Mapper";
}
}
public string Name
{
get
{
return "
class="code-string">MapperComponent";
}
}
public string Version
{
get
{
return "
class="code-string">1.0.0.0";
}
}
#endregion
I have made it simple, as I have not created any icon nor added any validation logic. Go ahead if you want to play with
it.
#region IComponentUI Members
public IntPtr Icon
{
get
{
return new System.
class="code-SDKkeyword">IntPtr();
}
}
public System.Collections.IEnumerator Validate(
class="code-keyword">object projectSystem)
{
return null;
}
#endregion
We are going to have a property for getting the XSLT as a string
value.
So, we create a private
variable and a
property. There is a trick involved in creating the property. We need to add the
class="code-keyword">public EditorAttribute
class to the property. The actual purpose is that we need to invoke a dialog box for populating
this property. We pass our custom UITypeEditor
class as a paramter. Also we need to implement the Load
and Save
methods. I have not showed that here. But you can find it in the source code that I have
provided with this article.
#region IPersistPropertyBag Members
private string _customXSLT =
class="code-keyword">string.Empty;
[EditorAttribute(typeof(CustomXSLTUITypeEditor),
typeof(UITypeEditor))]
public string CustomXSLT
{
get
{
return _customXSLT;
}
set
{
_customXSLT = value;
}
}
public void GetClassID(
class="code-keyword">out Guid classID)
{
classID = new Guid("
class="code-string">655B591F-8994-4e52-8ECD-2D7E8E78B25C");
}
public void InitNew()
{
}
public void Load(IPropertyBag propertyBag,
class="code-keyword">int errorLog)
{
}
public void Save(IPropertyBag propertyBag,
class="code-keyword">bool clearDirty,
bool saveAllProperties)
{
}
#endregion
Here comes the most important part of our component development. We implement the only method of the Icomponent
interface. I have kept the implementation very simple. This actually involves some XML, XPath and XSLT coding to
transform the input message to the output message. I have used only memory stream
all over the code.
#region IComponent Members
public IBaseMessage Execute(IPipelineContext pContext,
IBaseMessage pInMsg)
{
IBaseMessagePart bodyPart = pInMsg.BodyPart;
Stream xmlData = bodyPart.Data;
Stream transformedMsg = TransformMessage(xmlData);
pInMsg.BodyPart.Data = transformedMsg;
pContext.ResourceTracker.AddResource(transformedMsg);
return pInMsg;
}
#endregion
This private
method takes in an input message as stream
and
processes the message. After transforming the message, it converts that into a stream
and
s back. If you walk through the code, you would find it very simple.
class="code-keyword">return
#region private members
private Stream TransformMessage(Stream inputMessage)
{
XslCompiledTransform transformer = new XslCompiledTransform();
byte[] outBytes = System.Text.Encoding.ASCII.GetBytes
(CustomXSLT);
MemoryStream memStream = new MemoryStream();
memStream.Write(outBytes, 0, outBytes.Length);
memStream.Position = 0;
XPathDocument xsltDoc = new XPathDocument((Stream)memStream);
MemoryStream destnStream = new MemoryStream();
transformer.Load(xsltDoc);
XPathDocument doc = new XPathDocument(inputMessage);
transformer.Transform(doc, null, destnStream);
return (Stream)destnStream;
}
#endregion
Is there any background to this article that may be useful such as an introduction to the basic ideas presented?
I found a whitepaper written by Saravanan regarding design time properties in custom pipeline component. You can find the
document here.
Points of Interest
As this is my very first presentation of an article, I might have missed something that is more important to explain.
Please bear with me. Alternatively you can email me at shankar.sekar@gmail.com so that it will help me to improve the
component development or the presentation. All your comments are welcome.
I also have to discuss the downside of using this control. As I have designed this control as a decoder component, we
can't use this to validate the XML message. So, we can only use a passthrough send pipeline in the send port. I have future
plans to extend this control to participate in all stages of the pipeline. Please provide your valuable comments to develop
further.
Thursday, February 7, 2008
Using nSoftware SFTP adapters in BizTalk
With the custom adapter framework there is lots of custom adapters around the space. nSoftware is one among them. They have provided lots of custom adapters and the main adapter that we use from them is SFTP.
Introduction to SFTP
Our interfaces mainly interfaces with SAP and legacy applications that are in windows environments. The SAP environment is deployed in the unix environment. So to bridge this gap, we use SFTP adapter in BizTalk to send/receive files from these systems. As you all know, there are lots of configuration that has to be specified in the SFTP adapter configuration dialog box. Together with nSoftware we use the OpenSSH for security purpose. There are 2 different types of configuration in SFTP. One is the Public/Private key combination and the other is simply a password. As we work towards security of our data, we use the former pattern for configuring SFTP.
The Public/Private pattern
The Public/Private pattern is very interesting. First from our system, we need to generate a public key and private key. There is an application available from OpenSSH to generate this. The public key has to be configured in the unix system(SAP). Also, we need to create a unix account and assign rights to that user for the remote path. This remote path will be used by BizTalk to send the files. The private key is the secret key and has to be retained in the BizTalk server itself. It shouldn't be shared among users.
In my next article I will explain with samples of how to configure the nSoftware SFTP adapter
Tuesday, February 5, 2008
BizTalk SQL JOBS
You would have been playing around BizTalk for a long time. If you have been staying close to the Production environment you would get a chance to see the real time issues of the SQL agent jobs that are used in BizTalk.
Me as a functional consultant in BizTalk have seen some interesting scenarios happening in our Production environment wherein our processing came to a halt. Do you believe if this is caused by these agent jobs? Yes it is :-)
I will give you a fair analysis of what I have done to understand these jobs. I have bundled it together with what i got from the internet and from my friends.
BizTalk Server 2006 includes the following SQL Server Agent jobs to assist you in managing the BizTalk Server databases:
SQL Agent should be running at all times.
The following is the list of Jobs that are used by BizTalk for internal processing.
1. Backup BizTalk Server - LogShipping
2. CleanupBTFExpiredEntriesJob_BizTalkMgmtDb
3. DTA Purge (BizTalkDTADb)
4. MessageBox_DeadProcesses_Cleanup_BizTalkMsgBoxDb
5. MessageBox_Message_Cleanup_BizTalkMsgBoxDb
6. MessageBox_Message_ManageRefCountLog_BizTalkMsgBoxDb
7. MessageBox_Parts_Cleanup_BizTalkMsgBoxDb
8. MessageBox_UpdateStats_BizTalkMsgBoxDb
9. Operations_OperateOnInstances_OnMaster_BizTalkMsgBoxDb
10. PurgeSubscriptionsJob_BizTalkMsgBoxDb
11. Rules_Database_Cleanup_BizTalkRuleEngineDb
12. TrackedMessages_Copy_BizTalkMsgBoxDb
JOB: Backup BizTalk Server - LogShipping
Criticality: Very High. Estimate 1-2 days of continuous outage will take down system as disk space will run out.
Functional description and purpose.
The most important job in the environment! This job performs full database and log backups of the BizTalk Server databases and ships the logs to a remote SQL server in DC1. It is important to make sure that all database backups are done transactionally so this job to goes to each database in the system and transactionally marks the log. It then takes a backup of all logs and truncates the logs [to control database growth].
You use the Backup BizTalk Server job to back up all of the databases in your BizTalk Server source system, except for some databases used by Business Activity Services (BAS) and Business Activity Monitoring (BAM). The source system is the server or group of servers that contain live data. Because the BAS and BAM databases have different backup and restore requirements, these databases are backed up and restored using other methods.
Additionally, the SQL job does not delete old backup files out of the box. You must manage those files to conserve disk space by backing them up and deleting them after new full backups have been created.
Frequency:
Occurs every 1 day(s), every 2 hour(s) between 12:00:00AM and 11:59:59 PM.
A full backup happens once a day at 12:00AM. Incrementals happen based on the schedule throughout the day every 2 hours.
Dependencies:
There is no dependency to other jobs. But the following databases are backed up by this job by default:
1. BAM Primary Import database (BAMPrimaryImport)
2. BizTalk Tracking database (BizTalkDTADB)
3. BizTalk Management database (BizTalkMgmtDB)
4. BizTalk MessageBox database (BizTalkMsgBoxDB)
5. Rule Engine database (BizTalkRuleEngineDB)
6. SSO database
7. BizTalk Base EDI database (R2 only)
Additional databases can be backed up by adding a reference in table BizTalkMgmt..adm_OtherBackupDatabases. The following have been added to the current list of backups:
1. BAM Archive Database (BAMArchive)
2. SSO database (SSODB)
Failure:
In case of any hardware failures, the backed up temporary logshipping database can be used to restore the system from last known logmark. Data that was processed during the problem occurrence will be lost. This can’t be avoided.
It is also important to note if the job fails consecutively for a long time, the BizTalk database “data files” and “log files” will continue to grow exponentially. This in turn will affect the performance of the whole BizTalk environment and eventually consume the entire disk space if not corrected immediately.
------
JOB: DTA Purge (BizTalkDTADb)
Criticality: Medium
Functional description and purpose
As BizTalk Server processes more and more data on your system, the BizTalk Tracking (BizTalkDTADb) database continues to grow in size. Unchecked growth decreases system performance and may generate errors in the Tracking Data Delivery Service (TDDS). In addition to general tracking data, tracked messages can also accumulate in the MessageBox database, causing poor disk performance.
While previous versions of BizTalk Server included sample scripts for archiving tracked messages and purging the BizTalk Tracking database, BizTalk Server 2006 automates both processes using the DTA Purge and Archive job. By archiving and purging data from the BizTalk Tracking database, you can maintain a healthy system, as well as keep your tracking data archived for future use. Because BizTalk Tracking database archives accumulate over time and consume disk space, it is a good idea to move the BizTalk Tracking database archives to secondary storage on a regular basis.
Frequency:
Occurs every 1 day(s), every 1 minute(s) between 12:00:00AM and 11:59:59 PM.
Dependencies:
There is no dependency for this job.
Failure:
As the job is scheduled to run every minute, there won’t be any problem if this fails once. But if the job keeps on running for a long time, then we have an issue. The BizTalkDTADB database file size will grow eventually, adding it to the load for the job. This in turn will affect the performance of the whole BizTalk environment.
--------
JOB: MessageBox_DeadProcesses_Cleanup_BizTalkMsgBoxDb
Criticality: High
Functional description and purpose
This job detects when a BizTalk Server host instance (NT service) has stopped and releases all work that was being done by that host instance so that it can be worked on by another host instance.
Frequency:
Occurs every 1 day(s), every 1 minute(s) between 12:00:00AM and 11:59:59 PM.
Dependencies:
There is no dependency for this job.
Failure:
Consider the case if ReceiveHost on machine_xx has been stopped due to some problems. Automatically all the messages that was previously handled by this instance would be transferred to machine_xy. If there were a problem with this job, then all the messages that were received by machine_xx would not be processed until the job is running again to re-assign the work.
-----
JOB: MessageBox_Message_Cleanup_BizTalkMsgBoxDb
Criticality: Very High. Estimate 1 day of continuous outage will have significant performance impact on system.
Functional description and purpose
Do not manually start this job.
This job removes all messages that are no longer being referenced by any subscribers in the BizTalk MessageBox (BizTalkMsgBoxDb) database tables.
This is an unscheduled job, which is started by the MessageBox_Message_ManageRefCountLog_BizTalkMsgBoxDb job.
Whenever a message is published in the BizTalkMsgBoxDB, a ref count is calculated. This would be the sum of all matching subscribers for this message. Whenever a subscriber subscribes a message, 1 is deducted from ref count. Finally when the ref count reaches 0 that message should be removed from the Message Box. This work is handled by this job.
Frequency:
This job is not scheduled. This job stems out from MessageBox_Message_ManageRefCountLog_BizTalkMsgBoxDb. Both the jobs are responsible for cleaning up the messages in the MessageBoxDB.
Dependencies:
This job depends on the job “MessageBox_Message_ManageRefCountLog_BizTalkMsgBoxDb”.
Failure:
As this job is run by the MessageBox_Message_ManageRefCountLog_BizTalkMsgBoxDb job, we actually don’t get any problems. But consider the case, if our environment is receiving more load when compared to the amount that it can process. In that case, the job would take some time to clean up the messages. As it takes a long time, more messages adds up to the load, making it to execute for a long time. This will have an impact of environment causing it to slow down the message that is received. The key point is that over a period of time, the MessageBoxDB increases in size and will make the environment to throttle.
------
JOB: MessageBox_Message_ManageRefCountLog_BizTalkMsgBoxDb
Criticality: Very High. Estimate 1 day of continuous outage will have significant performance impact on system.
Functional description and purpose
This job manages the reference count logs for messages and determines when any subscriber no longer references a message. Even thought this SQL Server Agent job is scheduled to run once per minute, the stored procedure that is called by this job contains logic to ensure that the stored procedure runs continually. This is by design behavior and should not be modified.
Frequency:
Occurs every 1 day(s), every 1 minute(s) between 12:00:00AM and 11:59:59 PM.
This will start the MessageBox_Message_Cleanup_BizTalkMsgBoxDb job. If that job completes, then this job will fail. But as per the design, even after its failure, it will automatically start. So it will resemble like a long running job (But actually there is no issue in that).
Dependencies:
This job depends on the job “MessageBox_Message_Cleanup_BizTalkMsgBoxDb”.
Failure:
Failure of this job doesn’t affect the environment. But it is actually the cleanup job that is more important. As previously mentioned the cleanup should complete as soon as possible, other wise we are gonna have a worse problem ahead.
-----
JOB: MessageBox_Parts_Cleanup_BizTalkMsgBoxDb
Criticality: Medium
Functional description and purpose
This job removes all message parts that are no longer being referenced by any messages in the BizTalk MessageBox (BizTalkMsgBoxDb) database tables. All messages are made up of one or more message parts, which contain the actual message data.
Frequency:
Occurs every 1 day(s), every 1 minute(s) between 12:00:00AM and 11:59:59 PM.
Dependencies:
There is no dependency on other jobs.
Failure:
As each message contains one or more message parts, they have to be removed when any subscribers no longer reference them. This job calls a stored procedure that truncates tables PartRefCountLog1 and PartRefCountLog2. The Stored procedure places a exclusive lock on both these tables. If there are any shared locks on these tables when this job is running, it would not be able to truncate the records, making the table record size to increase drastically. Due to heavy load, the job will take more time to complete affecting the overral performance.
Vanakkam