Exception in NHibernate persistence: The invoked member is not supported in a dynamic assembly.

232 views
Skip to first unread message

Francesc Castells

unread,
Apr 13, 2016, 11:02:23 AM4/13/16
to Particular Software
Helpful information to include
Product name: NServiceBus.NHibernate
Version: 6.2.7
Stacktrace:

Exception! System.NotSupportedException: The invoked member is not supported in a dynamic assembly.
   at System.Reflection.Emit.InternalAssemblyBuilder.GetManifestResourceNames()
   at NHibernate.Cfg.Configuration.GetAllHbmXmlResourceNames(Assembly assembly)
   at NHibernate.Cfg.Configuration.AddAssembly(Assembly assembly)
   at NServiceBus.Features.NHibernateSagaStorage.ApplyMappings(ReadOnlySettings settings, Configuration configuration) in C:\BuildAgent\work\5135de308b2f3016\src\NServiceBus.NHibernate\SagaPersisters\NHibernateSagaStorage.cs:line 42
   at NServiceBus.Features.NHibernateSagaStorage.<>c__DisplayClass1_0.<Setup>b__0(Configuration c) in C:\BuildAgent\work\5135de308b2f3016\src\NServiceBus.NHibernate\SagaPersisters\NHibernateSagaStorage.cs:line 29
   at NServiceBus.Features.SharedMappings.<>c__DisplayClass1_0.<ApplyTo>b__0(Action`1 m) in C:\BuildAgent\work\5135de308b2f3016\src\NServiceBus.NHibernate\SharedSession\SharedMappings.cs:line 15
   at System.Collections.Generic.List`1.ForEach(Action`1 action)
   at NServiceBus.Features.SharedMappings.ApplyTo(Configuration configuration) in C:\BuildAgent\work\5135de308b2f3016\src\NServiceBus.NHibernate\SharedSession\SharedMappings.cs:line 15
   at NServiceBus.Features.NHibernateStorageSession.Setup(FeatureConfigurationContext context) in C:\BuildAgent\work\5135de308b2f3016\src\NServiceBus.NHibernate\SharedSession\NHibernateStorageSession.cs:line 31
   at NServiceBus.Features.FeatureActivator.ActivateFeature(FeatureState featureState, IEnumerable`1 featuresToActivate, FeatureConfigurationContext context) in C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Features\FeatureActivator.cs:line 240
   at NServiceBus.Features.FeatureActivator.SetupFeatures(FeatureConfigurationContext context) in C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Features\FeatureActivator.cs:line 116
   at NServiceBus.Configure.Initialize() in C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Configure.cs:line 115
   at NServiceBus.Bus.Create(BusConfiguration configuration) in C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Bus.cs:line 17
   at Parlam.TMS.SharedKernel.NServiceBus.EndpointBase.Run() in G:\tfs\parlam\Parlam\TMS\Features\Workflows\Source\Parlam.TMS.Web\Shared Kernel\Parlam.TMS.SharedKernel.NServiceBus\EndpointBase.cs:line 68
   at Parlam.TMS.Workflows.Host.Program.<AsyncMain>d__1.MoveNext() in G:\tfs\parlam\Parlam\TMS\Features\Workflows\Source\Parlam.TMS.Web\Workflows\Parlam.TMS.Workflows.Host\Program.cs:line 41
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()

Description:

I have an endpoint using NHibernate persistence, SqlTransport and Outbox. The endpoint was correctly handling and sending messages. Now I've added a saga with a simple saga data class (a unique int property and a Guid property) and when the endpoint starts it throws the shown exception. I've used Sagas with NHibernate persistence on another project and it worked fine and I can't see any relevant difference in the configuration. 

So, as far as I can tell, NHibernate is calling GetManifestResourceNames on a dynamic Assembly, which it seems it's not supported. But I don't know what Assembly this is because there is no logging for this.
It seems that the assemblies come from the types in NServiceBus.SettingsExtentions.GetAvailableTypes(settings), but I don't know how to access this list in order to find the offending assembly.

Does anyone know what this error is about or how to print the list of assemblies?

Thanks,

Francesc





Francesc Castells

unread,
Apr 14, 2016, 4:47:54 AM4/14/16
to particula...@googlegroups.com
I finally found the issue. The endpoint host was initializing the endpoint twice for dev purposes: first running the installers and creating queues (with a db owner user in the connection string) and disposing it, and then without the installers and not creating queues (with a non privileged user), leaving the endpoint running.
In the first run, NSB was creating a couple of dynamic assemblies and the second run, it was blowing up due to these assemblies. 

My workaround now is to run the host twice with a command line parameter, to instruct if it has to run the installers or not. But it seems to me that this is an NSB (or NH Persistence) bug, because if dynamic assemblies cannot be scanned, it should ignore them instead of crashing.

Francesc


Tim

unread,
Apr 14, 2016, 8:31:04 AM4/14/16
to Particular Software
Hi Francesc,

NServiceBus indeed creates a dynamic assembly for proxy message types (e.g. when using interfaces as message contract). This proxy assembly is named NServiceBusMessageProxies. Usually this assembly should not be included in the assembly scanning process and therefore not be picked up for NHibernate initialization.

Could you share the code you mentioned which does your endpoint initialization?

Cheers,
Tim

Francesc Castells

unread,
Apr 14, 2016, 9:59:47 AM4/14/16
to particula...@googlegroups.com
Hi Tim,
Here you can see the host program:

class Program
    {
        static void Main(string[] args)
        {
            try
            {
                AsyncMain(true).GetAwaiter().GetResult();
                AsyncMain(false).GetAwaiter().GetResult();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception! " + ex);
                Console.WriteLine("Press a key to exit");
                Console.ReadLine();
            }
        }

        static async Task AsyncMain(bool installOnly)
        {
            using (var workflowsEndpoint = new WorkflowsEndpoint(installOnly))
            using (var workflowsBackgroundEndpoint = new WorkflowsBackgroundEndpoint(installOnly))
            {
                workflowsEndpoint.Configure(AllAssemblies.Except("Parlam.TMS.Workflows.Endpoint.Background.dll"));
                workflowsBackgroundEndpoint.Configure(AllAssemblies.Except("Parlam.TMS.Workflows.Endpoint.dll"));

                await workflowsEndpoint.Run();
                await workflowsBackgroundEndpoint.Run();

                if (!installOnly)
                {
                    Console.WriteLine("Close the window to exit");
                    while (true) Console.ReadLine();
                }
            }
        }



The only thing that the Endpoint classes do with the installOnly flag is the following:

  if (_installOnly)
            {
                configuration.EnableInstallers();
            }
            else
            {
                configuration.DoNotCreateQueues();
            }

Otherwise the initialization code is the same.


I considered two workarounds:
- Subclass AllAssemblies to filter out the dynamic assemblies
- Run the install only endpoint on a separate appdomain and unload it.

At the end, as I mentioned, what I did is to optionally pass an "install" parameter in the command line.


Tim

unread,
Apr 14, 2016, 11:02:24 AM4/14/16
to Particular Software
Hi Francesc,

I was able to reproduce your issue. It seems that NServiceBus includes already loaded AppDomain assemblies. On the second run it then contains several dynamic assemblies which will cause NHibernate to fail. I will raise an issue on the NServiceBus repository about this.

In the meantime, can you try whether excluding the following dynamic assemblies resolves your issues until this is fixed:
AllAssemblies[.....].Except("NServiceBusMessageProxies").And("Anonymously Hosted DynamicMethods Assembly").And("Microsoft.GeneratedCode")

Francesc Castells

unread,
Apr 14, 2016, 11:18:28 AM4/14/16
to particula...@googlegroups.com
Hi Tim,
ok, sure I can try that.

Although, the offending lines are in the GetEnumerator in AllAssemblies, right?

    public IEnumerator<Assembly> GetEnumerator()
    {
      AssemblyScanner assemblyScanner = new AssemblyScanner(this.directory);
      assemblyScanner.IncludeAppDomainAssemblies = true;
      List<string> list1 = this.assembliesToInclude;
      assemblyScanner.AssembliesToInclude = list1;
      List<string> list2 = this.assembliesToExclude;
      assemblyScanner.AssembliesToSkip = list2;
      assemblyScanner.MustReferenceAtLeastOneAssembly.Add(typeof (IHandleMessages<>).Assembly);
      return (IEnumerator<Assembly>) assemblyScanner.GetScannableAssemblies().Assemblies.GetEnumerator();
    }


Maybe it be safer to create my own implementation of AllAssemblies with a fix? The fix could be:
1.- Use      assemblyScanner.IncludeAppDomainAssemblies = false;
2.- Or filter out the dynamic assemblies ,like Assemblies.Where(a=>!a.IsDynamic).GetEnumerator();




Tim

unread,
Apr 14, 2016, 12:01:39 PM4/14/16
to Particular Software
> Although, the offending lines are in the GetEnumerator in AllAssemblies, right?

Well that depends. It's NHibernate which can't handle dynamic assemblies. That's why I raised the issue on the NHibernate repository: https://github.com/Particular/NServiceBus.NHibernate/issues/183

You're right that the IncludeAppDomainAssemblies is the reason why the dynamic assemblies are included in the first place. But this also a behavior which may not cause issues for other persistence options.

Of course you can try to write your custom AllAssemblies alternative in the meantime. Setting IncludeAppDomainAssemblies to false should do the trick in your case. Please let me know if that approach worked out for you!

Cheers,
Tim

Francesc Castells

unread,
May 9, 2016, 6:40:04 AM5/9/16
to particula...@googlegroups.com
Hi Tim, 
sorry for the delay, I was on paternity leave :)

At the end I used your initial suggestion of explicitly excluding the NSB dynamic assemblies instead of setting IncludeAppDomainAssemblies to false as I suggested, because I think that's a better solution. 

Everything seems to work correctly now. 

Thanks,

Francesc

Reply all
Reply to author
Forward
0 new messages