0
votes

I have a very simple setup where producer is publishing events and have a single subscriber for handling. Both roles are hosted in Azure using Storage Queues as transport. This is producer config:

public class EndpointConfig : IConfigureThisEndpoint, AsA_Worker, UsingTransport<AzureStorageQueue>, IWantCustomInitialization
{
   public void Init()
   {
       Configure.Transactions.Disable();
       Configure.With()
                .DefaultBuilder()
                .UnicastBus();

   }
}

This is subscriber config:

public class EndpointConfig : IConfigureThisEndpoint, AsA_Worker, UsingTransport<AzureStorageQueue>, IWantCustomInitialization
{
    public void Init()
    {
        Configure.Transactions.Disable();
        Configure.With()
                 .DefaultBuilder()
                 .UnicastBus()
                 .LoadMessageHandlers();


    }
}

and app.config:

<connectionStrings>
  <add name="NServiceBus/Transport" connectionString="UseDevelopmentStorage=true" />
</connectionStrings>

<AzureProfileConfig Profiles="NServiceBus.Development" />
<AzureSubscriptionStorageConfig ConnectionString="UseDevelopmentStorage=true" />

<AuditConfig QueueName="audit" />
<UnicastBusConfig>
  <MessageEndpointMappings>
    <add Assembly="Interfaces" Type="Interfaces.SumbitOrder" Endpoint="Producer" />
  </MessageEndpointMappings>
</UnicastBusConfig>

Event is defined as usual:

public class SumbitOrder : IEvent
{
    public string Name { get; set; }
}

Publishing of the event is nothing more as just like any other:

Bus.Publish(Bus.CreateInstance<SumbitOrder>(m => { m.Name = "sample order"; }));

So browsing throught IntelliSense stream I can see following messages output to the console:

Console:"Received message with ID 0d46873c-102e-4d2a-b2a8-a3290097836a from sender Subscriber1@UseDevelopmentStorage=true" Console Output "Received message with ID 0d46873c-102e-4d2a-b2a8-a3290097836a from sender Subscriber1@UseDevelopmentStorage=true" Time: 12.05.2014 9:11:40 Thread:[4892]

Console:"Subscribing Subscriber1@UseDevelopmentStorage=true to message type Interfaces.SumbitOrder, Interfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" Console Output "Subscribing Subscriber1@UseDevelopmentStorage=true to message type Interfaces.SumbitOrder, Interfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null". Time: 12.05.2014 9:11:40 Thread:[4892]

And also I can see the same message on Producer input queue:

{
  "IdForCorrelation": null,
  "Id": "0d46873c-102e-4d2a-b2a8-a3290097836a",
  "MessageIntent": 3,
  "ReplyToAddress": "Subscriber1@UseDevelopmentStorage=true",
  "TimeToBeReceived": "10675199.02:48:05.4775807",
  "Headers": {
    "NServiceBus.MessageId": "0d46873c-102e-4d2a-b2a8-a3290097836a",
    "NServiceBus.CorrelationId": "0d46873c-102e-4d2a-b2a8-a3290097836a",
    "NServiceBus.OriginatingEndpoint": "Subscriber1",
    "$.diagnostics.originating.hostid": "3814ca7177296375c232c8d0293664dc",
    "NServiceBus.MessageIntent": "Subscribe",
    "NServiceBus.Version": "4.6.1",
    "NServiceBus.TimeSent": "2014-05-12 06:11:38:591761 Z",
    "NServiceBus.OriginatingMachine": "VALDIS-MAC",
    "NServiceBus.ControlMessage": "True",
    "SubscriptionMessageType": "Interfaces.SumbitOrder, Interfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
  },
  "Body": null,
  "CorrelationId": "0d46873c-102e-4d2a-b2a8-a3290097836a",
  "Recoverable": true
}

Subscriber is written down to Subscriptions storage table. However event handler never gets invoked:

namespace Subscriber1
{
    public class SubmitOrderHandler : IHandleMessages<SumbitOrder>
    {
        public void Handle(SumbitOrder message)
        {
            // logic
        }
    }
}

However, ordinary messaging is working (Bus.Send) - so connection between these 2 Azure roles is up and running. I'm not sure where is the problem and I dunno whether this is related to the issue but while debugging I can see following exception on Bus.Publish line:

    Microsoft.Data.OData.ODataException: Cannot convert a primitive value to the expected type 'Edm.DateTime'. See the inner exception for more details. ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at System.Xml.Schema.XsdDateTime.Parser.ParseTime(Int32& start)
   at System.Xml.Schema.XsdDateTime.Parser.ParseTimeAndZoneAndWhitespace(Int32 start)
   at System.Xml.Schema.XsdDateTime.Parser.Parse(String text, XsdDateTimeFlags kinds)
   at System.Xml.Schema.XsdDateTime..ctor(String text, XsdDateTimeFlags kinds)
   at System.Xml.XmlConvert.ToDateTime(String s, XmlDateTimeSerializationMode dateTimeOption)
   at Microsoft.Data.OData.PlatformHelper.ConvertStringToDateTime(String text)
   at Microsoft.Data.OData.JsonLight.ODataJsonLightReaderUtils.ConvertStringValue(String stringValue, Type targetType)
   at Microsoft.Data.OData.JsonLight.ODataJsonLightReaderUtils.ConvertValue(Object value, IEdmPrimitiveTypeReference primitiveTypeReference, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, Boolean validateNullValue, String propertyName)
   --- End of inner exception stack trace ---
   at Microsoft.Data.OData.JsonLight.ODataJsonLightReaderUtils.ConvertValue(Object value, IEdmPrimitiveTypeReference primitiveTypeReference, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, Boolean validateNullValue, String propertyName)



Inner exceptoin:
System.NullReferenceException: Object reference not set to an instance of an object.
   at System.Xml.Schema.XsdDateTime.Parser.ParseTime(Int32& start)
   at System.Xml.Schema.XsdDateTime.Parser.ParseTimeAndZoneAndWhitespace(Int32 start)
   at System.Xml.Schema.XsdDateTime.Parser.Parse(String text, XsdDateTimeFlags kinds)
   at System.Xml.Schema.XsdDateTime..ctor(String text, XsdDateTimeFlags kinds)
   at System.Xml.XmlConvert.ToDateTime(String s, XmlDateTimeSerializationMode dateTimeOption)
   at Microsoft.Data.OData.PlatformHelper.ConvertStringToDateTime(String text)
   at Microsoft.Data.OData.JsonLight.ODataJsonLightReaderUtils.ConvertStringValue(String stringValue, Type targetType)
   at Microsoft.Data.OData.JsonLight.ODataJsonLightReaderUtils.ConvertValue(Object value, IEdmPrimitiveTypeReference primitiveTypeReference, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, Boolean validateNullValue, String propertyName)

Which results into InvalidOperationException in NServiceBus.Core assembly. But calling final public method from the stack trace manually it's successful:

XmlConvert.ToDateTime("2014-05-11T20:42:01.15Z", XmlDateTimeSerializationMode.RoundtripKind);

The last method from NServiceBus which is on the call stack is: NServiceBus.Azure.dll!NServiceBus.Unicast.Subscriptions.AzureSubscriptionStorage.NServiceBus.Unicast.Subscriptions.MessageDrivenSubscriptions.ISubscriptionStorage.Subscribe(NServiceBus.Address address = {unknown}, System.Collections.Generic.IEnumerable<NServiceBus.Unicast.Subscriptions.MessageType> messageTypes = {unknown}).

I can verify that the same setup with Azure storage queues as transport just hosted on-premises works great. So my guess that there should be something related how roles are hosting in emulator or how storage emulator is working.

Please help to diagnose this as currently pub/sub scenario is failing and this is show-stopper for us to demo full sample to management for decision making process!

1

1 Answers

0
votes

From the stacktrace it looks like there is a null reference exception inside Microsoft.Data.OData library when reading the subscription data from table storage.

What version are you on? And maybe have a look at the table content see if there is a null value in one of the date time fields?