Our system, when serializing one message using protobuf-net, sometimes, but not every time, raises the error exposed below. What are the reasons for the error and how can I mitigate it?
Please notice that we are using DeserializeWithLengthPrefix
already.
UPDATE: the relevant code is here
private const PrefixStyle PrefixStyleInPlace = PrefixStyle.Fixed32;
public static byte[] SerializeObjectToByteArray<TSerializable>(TSerializable source) where TSerializable : class
{
byte[] result;
using (var memoryStream = SerializeObjectToStream(source))
{
result = memoryStream.ToArray();
}
return result;
}
public static TResult DeserializeObject<TResult>(byte[] source)
{
TResult result;
using (var memoryStream = new MemoryStream(source))
{
memoryStream.Position = 0;
result = Serializer.DeserializeWithLengthPrefix<TResult>(memoryStream,PrefixStyleInPlace);
}
return result;
}
public static MemoryStream SerializeObjectToStream<TSerializable>(TSerializable source) where TSerializable : class
{
var memoryStream = new MemoryStream();
Serializer.SerializeWithLengthPrefix(memoryStream, source,PrefixStyleInPlace);
memoryStream.Position = 0;
return memoryStream;
}
public static TResult DeserializeObject<TResult>(MemoryStream sourceStream)
{
TResult result;
result = DeserializeObject<TResult>(sourceStream.ToArray());
return result;
}
MESSAGE:
System.IO.EndOfStreamException : Attempted to read past the end of the
stream.
+++++++++++++++++++ STACK TRACE: at ProtoBuf.ProtoReader.Ensure(Int32 count, Boolean trict) in
c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 234 at
ProtoBuf.ProtoReader.ReadString() in
c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 471 at
proto_15(Object , ProtoReader ) at
ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object
value, ProtoReader source) in
c:\Dev\protobuf-net\protobuf-net\Serializers\CompiledSerializer.cs:line
49 at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object
value, ProtoReader source) in
c:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 721 at
ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key,
ProtoReader reader, Type type) in
c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 556 at
proto_16(Object , ProtoReader ) at
ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object
value, ProtoReader source) in
c:\Dev\protobuf-net\protobuf-net\Serializers\CompiledSerializer.cs:line
49 at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object
value, ProtoReader source) in
c:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 721 at
ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key,
ProtoReader reader, Type type) in
c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 556 at
proto_11(Object , ProtoReader ) at
ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object
value, ProtoReader source) in
c:\Dev\protobuf-net\protobuf-net\Serializers\CompiledSerializer.cs:line
49 at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object
value, ProtoReader source) in
c:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 721 at
ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key,
ProtoReader reader, Type type) in
c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 556 at
proto_16(Object , ProtoReader ) at
ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object
value, ProtoReader source) in
c:\Dev\protobuf-net\protobuf-net\Serializers\CompiledSerializer.cs:line
49 at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object
value, ProtoReader source) in
c:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 721 at
ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key,
ProtoReader reader, Type type) in
c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 556 at
proto_13(Object , ProtoReader ) at
ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object
value, ProtoReader source) in
c:\Dev\protobuf-net\protobuf-net\Serializers\CompiledSerializer.cs:line
49 at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object
value, ProtoReader source) in
c:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 721 at
ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key,
ProtoReader reader, Type type) in
c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 556 at
proto_16(Object , ProtoReader ) at
ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object
value, ProtoReader source) in
c:\Dev\protobuf-net\protobuf-net\Serializers\CompiledSerializer.cs:line
49 at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object
value, ProtoReader source) in
c:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 721 at
ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key,
ProtoReader reader, Type type) in
c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 556 at
proto_2(Object , ProtoReader ) at
ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object
value, ProtoReader source) in
c:\Dev\protobuf-net\protobuf-net\Serializers\CompiledSerializer.cs:line
49 at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object
value, ProtoReader source) in
c:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 721 at
ProtoBuf.Meta.TypeModel.DeserializeWithLengthPrefix(Stream source,
Object value, Type type, PrefixStyle style, Int32 expectedField,
TypeResolver resolver, Int32& bytesRead, Boolean& haveObject,
SerializationContext context) in
c:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 351 at
ProtoBuf.Serializer.DeserializeWithLengthPrefix[T](Stream source,
PrefixStyle style, Int32 fieldNumber) in
c:\Dev\protobuf-net\protobuf-net\Serializer.cs:line 303 at
ProtoBuf.Serializer.DeserializeWithLengthPrefix[T](Stream source,
PrefixStyle style) in
c:\Dev\protobuf-net\protobuf-net\Serializer.cs:line 288 at
ermeX.Common.ObjectSerializer.DeserializeObject[TResult](Byte[]
source) in
[ProtoContract(SkipConstructor = true)]
[ProtoInclude(100, typeof(BusMessage))]
[ProtoInclude(200, typeof(TransportMessage))]
[ProtoInclude(300, typeof(BizMessage))]
Code here
internal abstract class SystemMessage : ISystemMessage, IEquatable<SystemMessage>
{
protected SystemMessage():this(Guid.NewGuid(),DateTime.UtcNow)
{
}
protected SystemMessage(Guid messageId,DateTime createdTimeUtc)
{
MessageId = messageId;
CreatedTimeUtc = new DateTime(createdTimeUtc.Ticks);//TODO: UNTIL PROTOBUF-NET FIXES ISSUE 335
}
[ProtoMember(1)]
public Guid MessageId{get;private set;}
[ProtoMember(2)]
public DateTime CreatedTimeUtc { get; private set; }
...
}
[ProtoContract(SkipConstructor = true)]
internal sealed class TransportMessage : SystemMessage, ISystemMessage<BusMessage>
{
//just for the serializer, remove in the future
private TransportMessage()
{
}
public TransportMessage(Guid recipient, BusMessage data)
: this(data.MessageId, data.CreatedTimeUtc, recipient, data)
{
}
public TransportMessage(Guid messageId, DateTime createdTimeUtc, Guid recipient, BusMessage data)
: base(messageId, createdTimeUtc)
{
if (data == null) throw new ArgumentNullException("data");
if (recipient.IsEmpty()) throw new ArgumentException("recipient cannot be an empty value");
Recipient = recipient;
Data = data;
}
[ProtoMember(1)]
public Guid Recipient { get; private set; }
[ProtoMember(2)]
public BusMessage Data { get; private set; }
}
[ProtoContract(SkipConstructor = true)]
internal sealed class BusMessage: SystemMessage, ISystemMessage<BizMessage>,IEquatable<BusMessage>
{
private BusMessage()
{
}
public BusMessage(Guid publisher,BizMessage data)
: this(data.MessageId,data.CreatedTimeUtc,publisher, data)
{
}
public BusMessage(Guid messageId, DateTime createdTimeUtc, Guid publisher, BizMessage data) : base(messageId,createdTimeUtc)
{
if (data == null) throw new ArgumentNullException("data");
Publisher = publisher;
Data = data;
}
[ProtoMember(1)]
public Guid Publisher { get; protected set; }
[ProtoMember(2)]
public BizMessage Data { get; protected set; }
}
[ProtoContract(SkipConstructor = true)]
internal sealed class BizMessage : SystemMessage, IEquatable<BizMessage>
{
private string _jsonMessage;
private object _data = null;
public BizMessage(object data) : base()
{
if (data == null) throw new ArgumentNullException("data");
_data = data;
}
private BizMessage(){}
public static BizMessage FromJson(string jsonData)
{
if(string.IsNullOrEmpty(jsonData))
throw new ArgumentException();
return new BizMessage(){JsonMessage = jsonData};
}
[ProtoMember(75)]
internal string JsonMessage
{
get
{
if(string.IsNullOrEmpty(_jsonMessage))
{
if (_data == null)
throw new ApplicationException(
"One of both, _data or the serialized json message must have a value");
_jsonMessage = JsonSerializer.SerializeObjectToJson(_data);
}
return _jsonMessage;
}
private set { _jsonMessage = value; }
}
public Type MessageType
{
get
{
UpdateData();
if (_data == null)
return typeof(void);
return _data.GetType();
}
}
public object RawData
{
get
{
UpdateData();
return _data;
}
}
private void UpdateData()
{
if (_data == null)
{
if (string.IsNullOrEmpty(_jsonMessage))
throw new ApplicationException(
"One of both, _data or the serialized json message must have a value");
_data = JsonSerializer.DeserializeObjectFromJson<object>(_jsonMessage);
}
}
}
I've seen this error when the "type" that I specify to deserialize to is not the same as the originating type that was serialized. I suppose this could also happen if your object has changed and you're attempting to deserialize an older version of your object (i.e. old byte array) that is incompatible with the new version.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With