KCB
KCB

Reputation: 11

How to change EntityNameAttribute to custom NameAttribute in Masstransit (RabbitMq)

in my Applications I use different Interfaces to handle Messages. To avoid multiple Implementations and to reduce the maintenance of the same DTO, I want to use a Custom Attribute to handle the Exchange name of the Masstransit part. Also I want to reduce the dependencies to Masstransit in these common software parts.

So my Question is " How to change the EntityNameAttribute to a custom NameAttribute in Masstransit. (RabbitMq Version 7.3.1) "

I Have tried to Overwrite the EntityNameFormatter for the MessageTopology.

cfg.MessageTopology.SetEntityNameFormatter(new CustomExchangeNameFormatter(cfg.MessageTopology.EntityNameFormatter));  

If the Application publish a Message an error occurs.

_asyncApi.PublishMessage<CustomMessage>(new CustomMessage(){Content = "TestMessage"});

... RabbitMQ.Client.Exceptions.OperationInterruptedException: The AMQP operation was interrupted: AMQP close-reason, initiated by Peer, code=403, text='ACCESS_REFUSED - operation not permitted on the default exchange', classId=40, methodId=10 ...

public class CustomExchangeNameFormatter: IEntityNameFormatter
{
    private IEntityNameFormatter _original;

    public CustomExchangeNameFormatter(IEntityNameFormatter original)
    {
        _original = original;
    }

    //Used to rename the exchanges
    public string FormatEntityName<T>()
    {
        string entityName;

        var exchangeNameAttribute = typeof(T).GetCustomAttribute<ExchangeNameAttribute>();
        if (exchangeNameAttribute != null)
        {
            entityName = exchangeNameAttribute.ExchangName;
        }
        else
        {
            entityName = _original.FormatEntityName<T>();
        }

        return entityName;
    }
}

Upvotes: 0

Views: 985

Answers (2)

KCB
KCB

Reputation: 11

Hi fixed the Problem by moving the SetEntityNameFormatter method call under the line cfg.SetMessageSerializer(.. and cfg.AddMessageDeserializer(... I don't know why, but if the method is called before these two lines it throws the described error.

   public static IServiceCollection AddRabbitMqApi(this IServiceCollection services, IConfiguration configuration)
    {
        return services.AddMassTransit(busCfg =>
            {
                busCfg.UsingRabbitMq((ctx, cfg) =>
                {
                    cfg.Host(...); 

                    //Setup the NamespaceSpecificStrings
                    var (nssMappingForSerialization, nssMappingForDeserialization) = GetNssMappings(assemblies);

                    //serialization and deserialization
                    cfg.SetMessageSerializer(() => new CustomJsonMessageSerializer(nssMappingForSerialization));
                    cfg.AddMessageDeserializer(CustomJsonMessageSerializer.JsonContentType, () => new CustomJsonMessageDeserializer(CustomJsonMessageSerializer.Deserializer, nssMappingForDeserialization));

                    //entity name formatter
                    cfg.MessageTopology.SetEntityNameFormatter(new CustomExchangeNameFormatter(cfg.MessageTopology.EntityNameFormatter));

                    cfg.ConfigureJsonSerializer(settings =>
                    {
                        settings.DefaultValueHandling = DefaultValueHandling.Include;
                        return settings;
                    });
                    
                    cfg.Publish<CustomMessage>(x => { x.ExchangeType = ExchangeType.Topic; });
                });
            })
            .AddMassTransitHostedService();
    }

Upvotes: 1

Chris Patterson
Chris Patterson

Reputation: 33278

If I were to guess, your custom entity name formatter is returning an empty name for an entity. That entirely based on the fact that the error says default exchange, which is "".

Upvotes: 0

Related Questions