Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hangfire 1.5.3 System.MissingMethodException on all our jobs

Tags:

c#

hangfire

We just updated hangfire from 1.3.4 to 1.5.3.

Our startup has changed from this:

    private static void DoHangfire(IAppBuilder app)
    {
        var options = new BackgroundJobServerOptions
        {
            // Set thread count to 1
            WorkerCount = 1
        };

        app.UseHangfire(config =>
        {
            config.UseSqlServerStorage(ConfigurationManager.ConnectionStrings["JobsDB"].ConnectionString);
            config.UseAuthorizationFilters(new HangfireDashboardAuthorizationFilter());
            config.UseServer(options);
        });

        // Set retries to zero
        GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 0 });

        JobActivator.Current = new WindsorJobActivator(Container.Kernel);
    }

to this:

    private static void DoHangfire(IAppBuilder app)
    {
        var options = new BackgroundJobServerOptions
        {
            // Set thread count to 1
            WorkerCount = 1
        };

        GlobalConfiguration.Configuration.UseSqlServerStorage(
            ConfigurationManager.ConnectionStrings["JobsDB"].ConnectionString);

        app.UseHangfireDashboard("/hangfire", new DashboardOptions()
                                                  {
                                                      AuthorizationFilters = new List<IAuthorizationFilter>
                                                                                 {
                                                                                     new HangfireDashboardAuthorizationFilter()
                                                                                 }
                                                  });

        app.UseHangfireServer(options);

        // Set retries to zero
        GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 0 });

        JobActivator.Current = new WindsorJobActivator(Container.Kernel);
    }

Now all our jobs (we have 4 different kinds of jobs) fail immediately with this error:

System.MissingMethodException: No parameterless constructor defined for this object. at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(Type type, Boolean nonPublic) at System.Activator.CreateInstance(Type type) at Hangfire.JobActivator.SimpleJobActivatorScope.Resolve(Type type) at Hangfire.Server.CoreBackgroundJobPerformer.Perform(PerformContext context) at Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass3.b__0() at Hangfire.Server.BackgroundJobPerformer.InvokePerformFilter(IServerFilter filter, PerformingContext preContext, Func1 continuation) at Hangfire.Server.BackgroundJobPerformer.PerformJobWithFilters(PerformContext context, IEnumerable1 filters) at Hangfire.Server.BackgroundJobPerformer.Perform(PerformContext context) at Hangfire.Server.Worker.PerformJob(BackgroundProcessContext context, IStorageConnection connection, String jobId)

like image 380
tom redfern Avatar asked Dec 05 '25 05:12

tom redfern


1 Answers

Well the problem had to do with some magic in how the new version of Hangfire interacted with the Hangfire.Windsor package, which simply provides a custom JobActivator with a windsor container for service location.

By moving the

JobActivator.Current = new WindsorJobActivator(Container.Kernel);

above the call to app.UseHangfireServer() we were able to uncover the real exception message, which was a Castle.MicroKernel.ComponentNotFoundException informing us that it couldn't wire in the dependency containing the method we wanted hangfire to run.

Suffice to say, in 1.3.4, to run a job you can do this:

BackgroundJob.Enqueue(() => thingWhichDoesStuff.DoStuff()); 

where thingWhichDoesStuff is injected into the containing class and the hangfire.windsor JobActivator is just magically able to resolve to the type.

However in 1.5.3 this magic resolution no longer happens, so you must explicitly tell the JobActivator the interface of the type containing the method you want hangfire to run:

BackgroundJob.Enqueue<IDoStuff>(x => x.DoStuff());  

This causes all our jobs to start working again.

like image 54
tom redfern Avatar answered Dec 07 '25 18:12

tom redfern



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!