Derived types are not published to consumers in MassTransit -
i having issues publishing generic messages derived types , having handler invoked using masstransit v2.8.0.
if publish message of type htmlblocknewmessage
, consumer never invoked. if publish servicebusmessage
object , change consumer consumes<servicebusmessage>.context
, consumer invoked.
the code fails derived type. works parent type (servicebusmessage).
types:
[serializable] public class servicebusmessage { } [serializable] public class servicebusresponse { public int resultcode { get; set; } } // request [serializable] public class contentitemmessage : servicebusmessage { public string siteid { get; set; } public string pageid { get; set; } public string contentitemid { get; set; } } [serializable] public class htmlblocknewmessage : contentitemmessage { public string htmldata { get; set; } } // response [serializable] public class contentitemmessageresponse : servicebusresponse { public string name { get; set; } public string itemtype { get; set; } public string itemhandler { get; set; } } [serializable] public class htmlblocknewmessageresponse : contentitemmessageresponse { public string dataid { get; set; } }
consumer:
public class htmlblockconsumer : consumes<htmlblocknewmessage>.context { private ihtmldataservice htmldataservice; public static ilogger logger { get; set; } public htmlblockconsumer() : this(null) { } public htmlblockconsumer(ihtmldataservice htmldataservice) { logger = log4netlogger.getlogger(); this.htmldataservice = htmldataservice ?? ioc.container.resolve<ihtmldataservice>(); } public void consume(iconsumecontext<htmlblocknewmessage> message) { // stuff message.respond(new htmlblocknewmessageresponse() { resultcode = 1 } ); }
}
bus registration publisher side:
var bus = servicebusfactory.new(sbc => { sbc.enablemessagetracing(); sbc.usemsmq(); sbc.verifymsmqconfiguration(); sbc.usemulticastsubscriptionclient(); sbc.setnetwork("test"); sbc.usexmlserializer(); sbc.usecontrolbus(); sbc.receivefrom("msmq://localhost/auctioncms.web.publisher"); mtservicebus.validatebus(sbc); }); ioc.container.registerinstance(bus);
bus registration consumer side:
var bus = servicebusfactory.new(sbc => { sbc.enablemessagetracing(); sbc.usemsmq(); sbc.verifymsmqconfiguration(); sbc.usemulticastsubscriptionclient(); sbc.setnetwork("test"); sbc.usexmlserializer(); sbc.usecontrolbus(); sbc.receivefrom("msmq://localhost/auctioncms.consumer"); sbc.subscribe(subs => { // these being manually registered due issues getting // structuremap scan assemblies subs.instance(new htmlblockconsumer()); subs.instance(new browserconsumer()); subs.instance(new offerconsumer()); }); }); ioc.container.registerinstance(bus);
my publish extension:
public static tr publish<t, tr>(this iservicebus bus, t message) t : servicebusmessage tr : servicebusresponse { tr response = null; ioc.container.resolve<iservicebus>().publishrequest(message, callback => { callback.settimeout(10.seconds()); try { callback.handle<tr>(m => { response = m; / }); } catch (exception ex) { throw; } }); return response; }
calling code:
// first create message specific type of action performing var message = new htmlblocknewmessage() { htmldata = "hello" }; // call function accepts contentitemmessage , calls publish public void addcontentitem(contentitemmessage message) { // preprocessing // call times out var response = this.auctioncmsservices.bus.publish<contentitemmessage, contentitemmessageresponse>(message); // more processing }
this exception
[requesttimeoutexception: timeout waiting response, requestid: 54910000-307f-20cf-c0c2-08d06b31cf6f] masstransit.requestresponse.requestimpl`1.wait() in d:\buildagent-03\work\aa063b4295dfc097\src\masstransit\requestresponse\requestimpl.cs:124 masstransit.requestresponseextensions.publishrequest(iservicebus bus, trequest message, action`1 configurecallback) in d:\buildagent-03\work\aa063b4295dfc097\src\masstransit\requestresponseextensions.cs:31 auctioncms.framework.servicebus.mtservicebus.publish(iservicebus bus, t message) in c:\users\rick\documents\visual studio 2012\projects\auctioncms\auctioncms.framework\servicebus\mtservicebus.cs:24 auctioncms.framework.entity.page.addcontentitem(isite site, string zone, int32 location, contentitemmessage message) in c:\users\rick\documents\visual studio 2012\projects\auctioncms\auctioncms.framework\entity\page.cs:48 auctioncms.framework.entity.site.setdefaultcontent() in c:\users\rick\documents\visual studio 2012\projects\auctioncms\auctioncms.framework\entity\site.cs:117 auctioncms.web.controllers.adminsitescontroller.newsite(sitenewmodel model, httppostedfilebase file) in c:\users\rick\documents\visual studio 2012\projects\auctioncms\auctioncms.web\controllers\adminsitescontroller.cs:69 lambda_method(closure , controllerbase , object[] ) +179 system.web.mvc.reflectedactiondescriptor.execute(controllercontext controllercontext, idictionary`2 parameters) +261 system.web.mvc.controlleractioninvoker.invokeactionmethod(controllercontext controllercontext, actiondescriptor actiondescriptor, idictionary`2 parameters) +39 system.web.mvc.async.<>c__displayclass42.<begininvokesynchronousactionmethod>b__41() +34 system.web.mvc.async.<>c__displayclass39.<begininvokeactionmethodwithfilters>b__33() +124 system.web.mvc.async.<>c__displayclass4f.<invokeactionmethodfilterasynchronously>b__49() +838059 system.web.mvc.async.<>c__displayclass4f.<invokeactionmethodfilterasynchronously>b__49() +838059 system.web.mvc.async.<>c__displayclass4f.<invokeactionmethodfilterasynchronously>b__49() +838059 system.web.mvc.async.<>c__displayclass4f.<invokeactionmethodfilterasynchronously>b__49() +838059 system.web.mvc.async.<>c__displayclass37.<begininvokeactionmethodwithfilters>b__36(iasyncresult asyncresult) +15 system.web.mvc.async.<>c__displayclass2a.<begininvokeaction>b__20() +33 system.web.mvc.async.<>c__displayclass25.<begininvokeaction>b__22(iasyncresult asyncresult) +838644 system.web.mvc.<>c__displayclass1d.<beginexecutecore>b__18(iasyncresult asyncresult) +28 system.web.mvc.async.<>c__displayclass4.<makevoiddelegate>b__3(iasyncresult ar) +15 system.web.mvc.controller.endexecutecore(iasyncresult asyncresult) +65 system.web.mvc.async.<>c__displayclass4.<makevoiddelegate>b__3(iasyncresult ar) +15 system.web.mvc.controller.endexecute(iasyncresult asyncresult) +51 system.web.mvc.<>c__displayclass8.<beginprocessrequest>b__3(iasyncresult asyncresult) +42 system.web.mvc.async.<>c__displayclass4.<makevoiddelegate>b__3(iasyncresult ar) +15 system.web.mvc.mvchandler.endprocessrequest(iasyncresult asyncresult) +51 system.web.callhandlerexecutionstep.system.web.httpapplication.iexecutionstep.execute() +606 system.web.httpapplication.executestep(iexecutionstep step, boolean& completedsynchronously) +288
edit:
i went generic approach solve this. it's ugly caller's perspective, works.
public tr addcontentitem<t, tr>(t message) t : contentitemmessage tr : contentitemmessageresponse { var response = this.auctioncmsservices.bus.publish<t, tr>(message); return response; }
the calling code looks this:
page.addcontentitem(new htmlblocknewmessage() { htmldata = "this html" });
eugene's comment correct. what's happening here publishing message of type contentitemmessage
. consumer of htmlblocknewmessage
not executed since message published contentitemmessage
, servicebusmessage
. masstransit message mis-typing 1 of number of things out there on how works.
your options:
- change addcontentitem use generic, perhaps constraint
- used reflection invoke publish right type information
- restructure how publish things isn't issue more
the bottom line should publish type want received. polymorphism in messaging tricky.
Comments
Post a Comment