I have a problem with executing a receive pipeline which I hope you can help.
I am getting the following exception.
Microsoft.XLANGs.Pipeline.XLANGPipelineManagerException: The pipeline
manager could not prepare the message(s) for processing pipeline
"Decillion.MAPS.SGX.Pipelines.RECEIVE_FlatFile_MT202_ATC_DP_DS_EPSDR_EPSFC_EPSCR_RTS".
Error Details: "System.IO.Stream" ---> System.InvalidCastException:
System.IO.Stream
at Microsoft.XLANGs.Core.CustomFormattedPart.ProtectedRetrieveAs(Type t)
at Microsoft.XLANGs.Core.Part.RetrieveAs(Type t)
at Microsoft.XLANGs.Pipeline.PipelineXPart.ToBaseMessagePart()
at Microsoft.XLANGs.Pipeline.PipelineXMessage.ToBaseMessage()
at
Microsoft.XLANGs.Pipeline.XLANGPipelineManager.ExecutePipeline(ReceivePipeline p, XLANGMessage inMsg)
--- End of inner exception stack trace ---
at
Microsoft.XLANGs.Pipeline.XLANGPipelineManager.ExecutePipeline(ReceivePipeline p, XLANGMessage inMsg)
at
Microsoft.XLANGs.Pipeline.XLANGPipelineManager.ExecuteReceivePipeline(Type
receivePipelineType, XLANGMessage inMsg)
at
Decillion.MAPS.SGX.Orchestration.SGX_TO_SWIFT_MTXXX_ATC_DP_DS_EPSDR_EPSFC_EPSCR_RTS.segment3(StopConditions stopOn)
at Microsoft.XLANGs.Core.SegmentScheduler.RunASegment(Segment s,
StopConditions stopCond, Exception& exp)
Microsoft.XLANGs.Pipeline.XLANGPipelineManagerException
Scoped@
SGX_TO_SWIFT_MTXXX_ATC_DP_DS_EPSDR_EPSFC_EPSCR_RTS.??__scope34
SGX_TO_SWIFT_MTXXX_ATC_DP_DS_EPSDR_EPSFC_EPSCR_RTS.??__scope33
SGX_TO_SWIFT_MTXXX_ATC_DP_DS_EPSDR_EPSFC_EPSCR_RTS.SGX_TO_SWIFT_MTXXX_ATC_DP_DS_EPSDR_EPSFC_EPSCR_RTS
170625e1-a1b3-4fbd-ac5a-6026e6ecabd0
--------------------------------------------------------------------------------
I am using a Message of type RAWSTRING which is where I think the problem is.
Here is the code below which I copied from the Microsoft Web Site.
Note it has a CustomFormatter called
[CustomFormatter(typeof(RawStringFormatter))]
--------------------------------------------------------------------------------
namespace Microsoft.Samples.BizTalk.XlangCustomFormatters
{
public abstract class BaseFormatter : IFormatter
{
public virtual SerializationBinder Binder
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
}
public virtual StreamingContext Context
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
}
public virtual ISurrogateSelector SurrogateSelector
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
}
public abstract void Serialize( Stream stm, object obj );
public abstract object Deserialize( Stream stm );
}
public class RawStringFormatter : BaseFormatter
{
public override void Serialize(Stream s, object o)
{
RawString rs = (RawString)o;
byte[] ba = rs.ToByteArray();
s.Write( ba, 0, ba.Length );
}
public override object Deserialize(Stream stm)
{
StreamReader sr = new StreamReader( stm, true );
string s = sr.ReadToEnd();
return new RawString( s );
}
}
[CustomFormatter(typeof(RawStringFormatter))]
[Serializable]
public class RawString
{
[XmlIgnore]
string _val;
public RawString(string s )
{
if (null==s)
throw new ArgumentNullException();
_val = s;
}
public RawString()
{
}
public byte[] ToByteArray()
{
return Encoding.UTF8.GetBytes( _val );
}
public override string ToString()
{
return _val;
}
}
}
--------------------------------------------------------------------------------
Can anyone please help it would be greatly appreciated.
Thanks
Angelo Laris
Hi.
Unfortunately, you can't execute inline pipeline from orchestration
with custom formatted CLR object.
This restriction is because of the engine is creating IBaseMessage
from the XLangMessage before executing the pipeline.
In this process, the engine is retrieving the parts as
System.IO.Stream.
You can find the code under Microsoft.XLANGs.Pipeline.PipelineXPart of
assembly Microsoft.XLANGs.Pipeline (with reflector of course).
Stream dataStream = (Stream) this.xpart.RetrieveAs(typeof(Stream));
Just look inside Microsoft.XLANGs.Core.CustomFormattedPart of assembly
Microsoft.XLANGs.Engine
You'll see the method ProtectedRetrieveAs(Type t) this method will
throw casting exception if the CLR object is not the same type as t.
So, in this case, the object must be of type Stream.
The only thing I can think of is to add implicitly conversion of the
object into Stream.
Hope I helped.
Pinhas Kolsky
http://pinhask.blogspot.com
Thanks for your help so far.
This is the code for the RAWSTRING note it has public static implicit
operator Stream(RawString rwstring)
This is still not working what have I done wrong
Thanks in advance
Angelo Laris
[CustomFormatter(typeof(RawStringFormatter))]
[Serializable]
public class RawString
{
[XmlIgnore]
string _val;
public RawString(string s )
{
if (null==s)
throw new ArgumentNullException();
_val = s;
}
public RawString()
{
}
public byte[] ToByteArray()
{
return Encoding.UTF8.GetBytes( _val );
}
public override string ToString()
{
return _val;
}
public static implicit operator Stream(RawString rwstring)
{
return ((Stream)new MemoryStream(rwstring.ToByteArray()));
The construction helper will be like this:
public static void Cunstruct(XLANGMessage msg, RawString rwstring)
{
byte[] buffer = rwstring.ToByteArray();
Stream s = new MemoryStream(buffer, 0, buffer.Length,
true, true);
s.Seek(0, SeekOrigin.Begin);
msg[0].LoadFrom(s);
}
After that in a construct shape construct the XmlDocument message like
this:
msgXRawString = new System.Xml.XmlDocument;
Helper.Cunstruct(msgXRawString, varRawString);
Then pass msgXRawString to the ExecutePipeline method.
I tried this approach and it worked for me.
Ps.
When creating MemoryStream in the helper class - be aware to set the
poblicityVisible parameter to true like this:
Stream s = new MemoryStream(buffer, 0, buffer.Length, true, true);
In case you won't set it explicitly the stream will throw exception
when the XLANG's engine will call GetBuffer() method.
Best regards.
Pinhas Kolsky
[BizTalk Server 2006 MCTS]
http://pinhask.blogspot.com
Thank you for your help so far.
I solved my problem after looking at the code for a while
This is the code
protected override object ProtectedRetrieveAs(Type t)
{
object customFormattedObject =
base.Value.GetCustomFormattedObject(this.GetFormatter());
if (!t.IsInstanceOfType(customFormattedObject))
{
throw new InvalidCastException(t.FullName);
}
return customFormattedObject;
}
t.IsInstanceOfType kept on returning false because it was not of type
System.IO.Stream.
So I used
class RawString : MemoryStream
And modify
public RawString (string s) : base( MemoryStream(s))
Only problem now is if I use a custom pipeline component MemoryStream does
not support Seek.
Does your solution allow Seek?
Thanks for your help
Regards
Angelo Laris