How to communicate user defined objects and exceptions between Service and UI in JavaFX2? - service

How to communicate user defined objects and user defined (checked) exceptions between Service and UI in JavaFX2?
The examples only show String being sent in to the Service as a property and array of observable Strings being sent back to the UI.
Properties seem to be defined only for simple types. StringProperty, IntegerProperty, DoubleProperty etc.
Currently I have a user defined object (not a simple type), that I want Task to operate upon and update with the output data it produced. I am sending it through the constructor of Service which passes it on through the constructor of Task. I wondered about the stricture that parameters must be passed in via properties.
Also if an exception is thrown during Task's operation, How would it be passed from Service to the UI? I see only a getException() method, no traditional throw/catch.
Properties http://docs.oracle.com/javafx/2/binding/jfxpub-binding.htm
Service and Task http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm
Service javadocs http://docs.oracle.com/javafx/2/api/javafx/concurrent/Service.html#getException()
"Because the Task is designed for use with JavaFX GUI applications, it
ensures that every change to its public properties, as well as change
notifications for state, errors, and for event handlers, all occur on
the main JavaFX application thread. Accessing these properties from a
background thread (including the call() method) will result in runtime
exceptions being raised.
It is strongly encouraged that all Tasks be initialized with immutable
state upon which the Task will operate. This should be done by
providing a Task constructor which takes the parameters necessary for
execution of the Task. Immutable state makes it easy and safe to use
from any thread and ensures correctness in the presence of multiple
threads."
But if my UI only touches the object after Task is done, then it should be ok, right?

Service has a signature Service<V> the <V> is a generic type parameter used to specify the type of the return object from the service's supplied task.
Let's say you want to define a service which returns a user defined object of type Foo, then you can do it like this:
class FooGenerator extends Service<Foo> {
protected Task createTask() {
return new Task<Foo>() {
protected Foo call() throws Exception {
return new Foo();
}
};
}
}
To use the service:
FooGenerator fooGenerator = new FooGenerator();
fooGenerator.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override public void handle(WorkerStateEvent t) {
Foo myNewFoo = fooGenerator.getValue();
System.out.println(myNewFoo);
}
});
fooGenerator.start();
If you want to pass an input value into the service each time before you start or restart it, you have to be a little bit more careful. You can add the values you want to input to the service as settable members on the service. These setters can be called from the JavaFX application thread, before the service's start method is invoked. Then, when the service's task is created, pass the parameters through to the service's Task's constructor.
When doing this it is best to make all information passable back and forth between threads immutable. For the example below, a Foo object is passed as an input parameter to the service and a Foo object based on the input received as an output of the service. But the state of Foo itself is only initialized in it's constructor - the instances of Foo are immutable and cannot be changed once created and all of it's member variables are final and cannot change. This makes it much easier to reason about the program, as you never need worry that another thread might overwrite the state concurrently. It seems a little bit complicated, but it does make everything very safe.
class FooModifier extends Service<Foo> {
private Foo foo;
void setFoo(Foo foo) { this.foo = foo; }
#Override protected Task createTask() {
return new FooModifierTask(foo);
}
private class FooModifierTask extends Task<Foo> {
final private Foo fooInput;
FooModifierTask(Foo fooInput) { this.fooInput = fooInput; }
#Override protected Foo call() throws Exception {
Thread.currentThread().sleep(1000);
return new Foo(fooInput);
}
}
}
class Foo {
private final int answer;
Foo() { answer = random.nextInt(100); }
Foo(Foo input) { answer = input.getAnswer() + 42; }
public int getAnswer() { return answer; }
}
There is a further example of providing input to a Service in the Service javadoc.
To return a custom user exception from the service, just throw the user exception during the service's task call handler. For example:
class BadFooGenerator extends Service<Foo> {
#Override protected Task createTask() {
return new Task<Foo>() {
#Override protected Foo call() throws Exception {
Thread.currentThread().sleep(1000);
throw new BadFooException();
}
};
}
}
And the exception can be retrieved like this:
BadFooGenerator badFooGenerator = new BadFooGenerator();
badFooGenerator.setOnFailed(new EventHandler<WorkerStateEvent>() {
#Override public void handle(WorkerStateEvent t) {
Throwable ouch = badFooGenerator.getException();
System.out.println(ouch.getClass().getName() + " -> " + ouch.getMessage());
}
});
badFooGenerator.start();
I created a couple of executable samples you can use to try this out.

Properties seem to be defined only for simple types. StringProperty, IntegerProperty, DoubleProperty etc. Currently I have a user defined object (not a simple type), that I want Task to operate upon and update with the output data it produced
If you want a property that can be used for your own classes try SimpleObjectProperty where T could be Exception, or whatever you need.
Also if an exception is thrown during Task's operation, How would it be passed from Service to the UI?
You could set an EventHandler on the Task#onFailedProperty from the UI with the logic with what to do on failure.
But if my UI only touches the object after Task is done, then it should be ok, right?
If you call it from your UI you are sure to be on the javaFX thread so you will be OK. You can assert that you're on the javaFX thread by calling Platform.isFxApplicationThread().

Related

How does the logging module for Autofac and NLog work?

I am still fairly new to Autofac and Nlog and I need some help in understanding what is taking place in my Autofac LoggingModule for Nlog. It works as expected thanks to following the injecting-nlog-with-autofacs-registergeneric. But rather than just copy paste, I would like to make sure I understand what is occurring in each method (Load & AttachToComponentRegistration). If you could review my thoughts and further clarify anything I have incorrect (quite a bit I am sure), I would greatly appreciate it. Thank you in advance!
Database Target using Nlog
Dependency Injection using Autofac
ASP.NET MVC web app for learning
Dvd Libary app (DvdAdd, DvdEdit, DvdDelete, DvdList)
LoggingModule
public class LoggingModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder
.Register((c, p) => new LogService(p.TypedAs<Type>()))
.AsImplementedInterfaces();
}
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
{
registration.Preparing +=
(sender, args) =>
{
var forType = args.Component.Activator.LimitType;
var logParameter = new ResolvedParameter(
(p, c) => p.ParameterType == typeof(ILog),
(p, c) => c.Resolve<ILog>(TypedParameter.From(forType)));
args.Parameters = args.Parameters.Union(new[] { logParameter });
};
}
}
My understanding of the code within Load()
c - The parameter c, provided to the expression, is the component context(an IComponentContext object) in which the component is being created. The context in which a service can be accessed or a component's dependencies resolved.
p - An IEnumerable with the incoming parameter set
AsImplementedInterfaces - Autofac allows its users to register the types explicitly or implicitly. While "As" is used for explicit registrations, "AsImplementedInterfaces" and "AsSelf" are used for implicit ones. In other words, the container automatically registers the implementation against all the interfaces it implements.
Thoughts: The Load method code registers a new LogService class (which represents "c") with the type of logger (which represents "p") as the constructor parameter for the LogService class
Questions:
Are my thoughts above correct?
Should it be SingleInstance or should it / will it only live as long as the calling classes scope? (I am thinking about my Unit Of Work)
My understanding of the code within AttachToComponentRegistration()
AttachToComponentRegistration method - Override to attach module-specific functionality to a component registration.
AttachToComponentRegistration Parameters:
IComponentRegistry componentRegistry - Provides component registrations according to the services they provide.
IComponentRegistration registration - Describes a logical component within the container.
registration.Preparing - Fired when a new instance is required. The instance can be provided in order to skip the regular activator, by setting the Instance property in the provided event arguments.
var forType = args.Component.Activator.LimitType;
args = Autofac.Core.PreparingEventArgs - Fired before the activation process to allow parameters to be changed or an alternative instance to be provided.
Component = PreparingEventArgs.Component Property - Gets the component providing the instance being activated
Activator = IComponentRegistration.Activator Property - Gets the activator used to create instances.
LimitType = IInstanceActivator.LimitType Property - Gets the most specific type that the component instances are known to be castable to.
Thoughts on forType - As I understand it, this variable holds the Name and FullName of the calling class from where the logging service is being called?
forType Debugger Image
Questions:
Are my thoughts forType correct?
var logParameter = new ResolvedParameter(
(p, c) => p.ParameterType == typeof(ILog),
(p, c) => c.Resolve<ILog>(TypedParameter.From(forType)));
ResolvedParameter - can be used as a way to supply values dynamically retrieved from the container,
e.g. by resolving a service by name.
Thoughts on logParameter - This is where I start to get lost. So does, it check that the Parameter is of Type ILog and if so it will then resolve it with the constructor parameter and pass in forType variable?
Questions:
Are my thoughts on logParameter above correct?
args.Parameters = args.Parameters.Union(new[] { logParameter });
args.Parameters = PreparingEventArgs.Parameters Property - Gets or sets the parameters supplied to the activator.
args.Parameters.Union = Produces the set union of two sequences by using the default equality comparer. Returns an System.Collections.Generic.IEnumerable`1 that contains the elements from both input sequences, excluding duplicates.
Thoughts on args.Parameters - I really do not know at this point other than to guess that it returns a collection of Parameters and removes duplicates?
Questions:
Could you help talk me through what is going on in args.Parameters?
logParameter Debugger Image
Nlog Database Table Image
LogService class
public class LogService : ILog
{
private readonly ILogger _log;
public LogService(Type type)
{
_log = LogManager.GetLogger(type.FullName);
}
public void Debug(string message, params object[] args)
{
Log(LogLevel.Debug, message, args);
}
public void Info(string message, params object[] args)
{
Log(LogLevel.Info, message, args);
}
public void Warn(string message, params object[] args)
{
Log(LogLevel.Warn, message, args);
}
public void Error(string message, params object[] args)
{
Log(LogLevel.Error, message, args);
}
public void Error(Exception ex)
{
Log(LogLevel.Error, null, null, ex);
}
public void Error(Exception ex, string message, params object[] args)
{
Log(LogLevel.Error, message, args, ex);
}
public void Fatal(Exception ex, string message, params object[] args)
{
Log(LogLevel.Fatal, message, args, ex);
}
private void Log(LogLevel level, string message, object[] args)
{
_log.Log(typeof(LogService), new LogEventInfo(level, _log.Name, null, message, args));
}
private void Log(LogLevel level, string message, object[] args, Exception ex)
{
_log.Log(typeof(LogService), new LogEventInfo(level, _log.Name, null, message, args, ex));
}
}
ILog interface
public interface ILog
{
void Debug(string message, params object[] args);
void Info(string message, params object[] args);
void Warn(string message, params object[] args);
void Error(string message, params object[] args);
void Error(Exception ex);
void Error(Exception ex, string message, params object[] args);
void Fatal(Exception ex, string message, params object[] args);
}
There's a lot to unpack here. You're not really asking for an answer to a specific question so much as a code walkthrough and explanation of an existing solution that works, so I might suggest posting to StackExchange Code Review if you need much more than what I'm going to give you here. Not trying to be unhelpful, but, like, if your question is, "Is my thinking right?" and the answer is "sort of," there's a lot of discussion on each individual point to explain why "sort of" is the answer (or "no," or "yes," as the case may be). It can turn into a lengthy answer, followed up by additional questions for clarification, which require yet additional answers... and StackOverflow isn't really a discussion forum capable of those sorts of things.
[i.e., I'll take probably an hour and write up an answer here... but I can't promise I'll actually be back to follow up on anything because there are other questions to answer and other things I need to allocate time to. StackOverflow is really more about "How do I...?" or other things that have a single, reasonably concrete answer.]
First, I recommend diving in yourself with a debugger on some breakpoints to actually see what's going on. For example, you asked what's in LimitType in one area - you could pretty easily answer that one by just sticking a breakpoint on that line and looking at the value. This will be a good way to follow up for additional clarification yourself - breakpoints for the win.
Second, I recommend spending some time with the Autofac docs. There's a lot of documentation out there that can answer questions.
The NLog module here appears to be based on the log4net module in the documentation which has a bit more explanation of what's going on.
There's an explanation of parameters (like TypedParameter) and how they're used.
Given the docs can round out some things that may not be clear, rather than try to address each "are my thoughts correct" item, let me just heavily annotate the module and hope that clarifies things.
// General module documentation is here:
// https://autofac.readthedocs.io/en/latest/configuration/modules.html
public class LoggingModule : Module
{
// Load basically registers types with the container just like
// if you were doing it yourself on the ContainerBuilder. It's
// just a nice way of packaging up a set of registrations so
// they're not all in your program's "Main" method or whatever.
protected override void Load(ContainerBuilder builder)
{
// This is a lambda registration. Docs here:
// https://autofac.readthedocs.io/en/latest/register/registration.html#lambda-expression-components
// This one uses both the component context (c) and the incoming
// set of parameters (p). In this lambda, the parameters are NOT the set of constructor
// parameters that Autofac has resolved - they're ONLY things that
// were MANUALLY specified. In this case, it's assuming a TypedParameter
// with a System.Type value is being provided manually. It's not going
// to try resolving that value from the container. This is going hand-in-hand
// with the logParameter you see in AttachToComponentRegistration.
// Parameter docs are here:
// https://autofac.readthedocs.io/en/latest/resolve/parameters.html
// In general if you resolve something that has both manually specified parameters
// and things that can be resolved by Autofac, the manually specified parameters
// will take precedence. However, in this lambda it's very specifically looking
// for a manually specified parameter.
// You'll want to keep this as a default InstancePerDependency because you probably
// want this to live as long as the thing using it and no longer. Likely
// NLog already has object pooling and caching built in so this isn't as
// expensive as you think, but I'm no NLog expert. log4net does handle
// that for you.
builder
.Register((c, p) => new LogService(p.TypedAs<Type>()))
.AsImplementedInterfaces();
}
// This method attaches a behavior (in this case, an event handler) to every
// component registered in the container. Think of it as a way to run a sort
// of "global foreach" over everything registered.
protected override void AttachToComponentRegistration(
IComponentRegistry componentRegistry,
IComponentRegistration registration)
{
// The Preparing event is called any time a new instance is needed. There
// are docs for the lifetime events but Preparing isn't on there. Here are the
// docs and the issue I filed on your behalf to get Preparing documented.
// https://autofac.readthedocs.io/en/latest/lifetime/events.html
// https://github.com/autofac/Documentation/issues/69
// You can see the Preparing event here:
// https://github.com/autofac/Autofac/blob/6dde84e5b0a3f82136a0567a84da498b04e1fa2d/src/Autofac/Core/IComponentRegistration.cs#L83
// and the event args here:
// https://github.com/autofac/Autofac/blob/6dde84e5b0/src/Autofac/Core/PreparingEventArgs.cs
registration.Preparing +=
(sender, args) =>
{
// The Component is the thing being resolved - the thing that
// needs a LogService injected. The Component.Activator is the
// thing that is actually going to execute to "new up" an instance
// of the Component. The Component.Activator.LimitType is the actual
// System.Type of the thing being resolved.
var forType = args.Component.Activator.LimitType;
// The docs above explain ResolvedParameter - basically a manually
// passed in parameter that can execute some logic to determine if
// it satisfies a constructor or property dependency. The point of
// this particular parameter is to provide an ILog to anything being
// resolved that happens to have an ILog constructor parameter.
var logParameter = new ResolvedParameter(
// p is the System.Reflection.ParameterInfo that describes the
// constructor parameter that needs injecting. c is the IComponentContext
// in which the resolution is being done (not used here). If this
// method evaluates to true then this parameter will be used; if not,
// it will refuse to provide a value. In this case, if the parameter
// being injected is an ILog, this ResolvedParameter will tell Autofac
// it can provide a value.
(p, c) => p.ParameterType == typeof(ILog),
// p and c are the same here, but this time they're used to actually
// generate the value of the parameter - the ILog instance that should
// be injected. Again, this will only run if the above predicate evaluates
// to true. This creates an ILog by manually resolving from the same
// component context (the same lifetime scope) as the thing that
// needs the ILog. Remember earlier that call to p.AsTyped<Type>()
// to get a parameter? The TypedParameter thing here is how that
// value gets poked in up there. This Resolve call will effectively
// end up calling the lambda registration.
(p, c) => c.Resolve<ILog>(TypedParameter.From(forType)));
// The thing being resolved (the component that consumes ILog) now
// needs to be told to make use of the log parameter, so add it into
// the list of parameters that can be used when resolving that thing.
// If there's an ILog, Autofac will use this specified parameter to
// fulfill the requirement.
args.Parameters = args.Parameters.Union(new[] { logParameter });
};
}
}
Something missing from this that's present in the log4net module example is the ability to do property injection for the logger. However, I'm not going to solve that here; you can look at the example right in the documentation and take that as an exercise to work on if you need that functionality.
I hope that helps. I'll probably not be coming back to follow up on additional questions, so if this isn't enough, I very, very much recommend setting some breakpoints, maybe setting up some tiny minimal-repro unit tests, that sort of thing, and do some deeper exploration to get clarity. Honestly, it's one thing to have someone else explain it, but it's another to actually see it in action and dive into the source of various projects. You'll come out with a fuller understanding with the latter approach, even if it's potentially not as fast.

opencensus - explicit context management

I am implementing an opencensus tracing in my (asynchronous) JVM app.
However I don't understand how is the context passed.
Sometimes it seems to work fine, sometimes traces from different requests appear nested for no reason.
I also have this warning appearing in the logs along with a stacktrace:
SEVERE: Context was not attached when detaching
How do I explicitly create a root span, and how can I explicitly pass a parent/context to the child spans?
In OpenCensus we have a concept of context independent of the "Span" or "Tags". It represents a Map that is propagated with the request (it is implemented as a thread-local so in sync calls automatically gets propagated). For callbacks/async calls just for propagation (we are using io.grpc.Context as the implementation of the context) use the wrap functions defined here https://github.com/grpc/grpc-java/blob/master/context/src/main/java/io/grpc/Context.java#L589. This will ensure just the context propagation, so entries in the context map will be propagated between different threads.
If you want to start a Span in one thread and end it in a different thread, use the withSpan methods from the tracer https://www.javadoc.io/doc/io.opencensus/opencensus-api/0.17.0 :
class MyClass {
private static Tracer tracer = Tracing.getTracer();
void handleRequest(Executor executor) {
Span span = tracer.spanBuilder("MyRunnableSpan").startSpan();
// do some work before scheduling the async
executor.execute(Context.wrap(tracer.withSpan(span, new Runnable() {
#Override
public void run() {
try {
sendResult();
} finally {
span.end();
}
}
})));
}
}
A bit more information about this here https://github.com/census-instrumentation/opencensus-specs/blob/master/trace/Span.md#span-creation

Pattern for using properly MongoClient in Vert.x

I feel quite uncomfortable with the MongoClient class, certainly because I don't exactly understand what it is and how it works.
The first call to MongoClient.createShared will actually create the
pool, and the specified config will be used.
Subsequent calls will return a new client instance that uses the same
pool, so the configuration won’t be used.
Does that mean that the pattern should be:
In startup function, to create the pool, we make a call
mc = MongoClient.createShared(vx, config, "poolname");
Is the returned value mc important for this first call if it succeeds? What is its value if the creation of the pool fails? The documentations doesn't say. There is a socket exception if mongod is not running, but what about the other cases?
In another place in the code (another verticle, for example), can we write mc = MongoClient.createShared(vx, new JsonObject(), "poolname"); to avoid to systematically need to access shared objects.
Again, In another verticle where we need to access the database, should we define MongoClient mc
as a class field in which case it will be released to the pool only in the stop() method, or
shouldn't it be a variable populated with MongoClient.createShared(...) and de-allocated with mc.close() once we don't need the connection any more in order release it again to the pool ?
What I would write is as follows
// Main startup Verticle
import ...
public class MainVerticle extends AbstractVerticle {
...
#Override
public void start(Future<Void> sf) throws Exception {
...
try {
MongoClient.createShared(vx, config().getJsonObject("mgcnf"), "pool");
}
catch(Exception e) {
log.error("error error...");
sf.fail("failure reason");
return;
}
...
sf.complete();
}
...some other methods
}
and then, in some other place
public class SomeVerticle extends AbstractVerticle {
public void someMethod(...) {
...
// use the database:
MongoClient mc = MongoClient.createShared(vx, new JsonObject(), "pool");
mc.save(the_coll, the_doc, res -> {
mc.close();
if(res.succeeded()) {
...
}
else {
...
}
}
...
}
...
}
Does that make sense ? Yet, this is not what is in the examples that I could find around the internet.
Don't worry about pools. Don't use them. They don't do what you think they do.
In your start method of any verticle, set a field (what you call a class field, but you really mean instance field) on the inheritor of AbstractVerticle to MongoClient.createShared(getVertx(), config). Close the client in your stop method. That's it.
The other exceptions you'll see are:
Bad username/password
Unhealthy cluster state
The Java driver has a limit of 500 or 1,000 connections (depending on version), you'll receive an exception if you exceed this connection count
Both will be propagated up from the driver wrapped in a VertxException.

How to resolve InstancePerLifetimeScope component from within SingleInstace component via Func?

The idea is just simple and works in the other containers, not limited with .Net:
Singleton component being referenced from within request context references transient component which in turn references request-scoped component (some UnitOfWork).
I expected that Autofac would resolve the same scoped component in both cases:
- when I request it directly from request scope
- when I request it by invoking Func<>
Unfortunately the reality is quite a bit different - Autofac sticks SingleInstance component to the root scope and resolves InstancePerLifetimeScope component on
the root component introducing memory leak (!!!) as UnitOfWork is disposable and becomes tracked by root scope (attempt to use matching web request scope would just fail finding request scope which is yet more misleading).
Now I'm wondering whether such behavior is by design or just a bug? If it is by design I'm not sure what are the use cases and why it differs from the other containers.
The example is as follows (including working SimpleInjector case):
namespace AutofacTest
{
using System;
using System.Linq;
using System.Linq.Expressions;
using Autofac;
using NUnit.Framework;
using SimpleInjector;
using SimpleInjector.Lifestyles;
public class SingletonComponent
{
public Func<TransientComponent> Transient { get; }
public Func<ScopedComponent> Scoped { get; }
public SingletonComponent(Func<TransientComponent> transient, Func<ScopedComponent> scoped)
{
Transient = transient;
Scoped = scoped;
}
}
public class ScopedComponent : IDisposable
{
public void Dispose()
{
}
}
public class TransientComponent
{
public ScopedComponent Scoped { get; }
public TransientComponent(ScopedComponent scopedComponent)
{
this.Scoped = scopedComponent;
}
}
class Program
{
static void Main(string[] args)
{
try
{
AutofacTest();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
try
{
SimpleInjectorTest();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static void AutofacTest()
{
var builder = new ContainerBuilder();
builder.RegisterType<ScopedComponent>().InstancePerLifetimeScope();
builder.RegisterType<SingletonComponent>().SingleInstance();
builder.RegisterType<TransientComponent>();
var container = builder.Build();
var outerSingleton = container.Resolve<SingletonComponent>();
using (var scope = container.BeginLifetimeScope())
{
var singleton = scope.Resolve<SingletonComponent>();
Assert.That(outerSingleton, Is.SameAs(singleton));
var transient = scope.Resolve<TransientComponent>();
var scoped = scope.Resolve<ScopedComponent>();
Assert.That(singleton.Transient(), Is.Not.SameAs(transient));
// this fails
Assert.That(singleton.Transient().Scoped, Is.SameAs(scoped));
Assert.That(transient.Scoped, Is.SameAs(scoped));
Assert.That(singleton.Scoped(), Is.SameAs(scoped)); // this fails
Assert.That(singleton.Transient(), Is.Not.SameAs(transient));
}
}
private static void SimpleInjectorTest()
{
var container = new SimpleInjector.Container();
container.Options.AllowResolvingFuncFactories();
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
container.Register<ScopedComponent>(Lifestyle.Scoped);
container.Register<SingletonComponent>(Lifestyle.Singleton);
container.Register<TransientComponent>(Lifestyle.Transient);
container.Verify();
var outerSingleton = container.GetInstance<SingletonComponent>();
using (var scope = AsyncScopedLifestyle.BeginScope(container))
{
var singleton = container.GetInstance<SingletonComponent>();
Assert.That(outerSingleton, Is.SameAs(singleton));
var transient = container.GetInstance<TransientComponent>();
var scoped = container.GetInstance<ScopedComponent>();
Assert.That(singleton.Transient(), Is.Not.SameAs(transient));
Assert.That(singleton.Transient().Scoped, Is.SameAs(scoped));
Assert.That(transient.Scoped, Is.SameAs(scoped));
Assert.That(singleton.Scoped(), Is.SameAs(scoped));
Assert.That(singleton.Transient(), Is.Not.SameAs(transient));
}
}
}
public static class SimpleInjectorExtensions
{
public static void AllowResolvingFuncFactories(this ContainerOptions options)
{
options.Container.ResolveUnregisteredType += (s, e) =>
{
var type = e.UnregisteredServiceType;
if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(Func<>))
{
return;
}
Type serviceType = type.GetGenericArguments().First();
InstanceProducer registration = options.Container.GetRegistration(serviceType, true);
Type funcType = typeof(Func<>).MakeGenericType(serviceType);
var factoryDelegate = Expression.Lambda(funcType, registration.BuildExpression()).Compile();
e.Register(Expression.Constant(factoryDelegate));
};
}
}
}
The short version what you're seeing is not a bug, you're just misunderstanding some of the finer points of lifetime scopes and captive dependencies.
First, a couple of background references from the Autofac docs:
Controlling Scope and Lifetime explains a lot about how lifetime scopes and that hierarchy works.
Captive Dependencies talks about why you don't generally shouldn't take an instance-per-lifetime or instance-per-dependency scoped item into a singleton.
Disposal talks about how Autofac auto-disposes IDisposable items and how you can opt out of that.
Implicit Relationship Types describes the Owned<T> relationship type used as part of the IDisposable opt-out.
Some big key takeaways from these docs that directly affect your situation:
Autofac tracks IDisposable components so they can be automatically disposed along with the lifetime scope. That means it will hold references to any resolved IDisposable objects until the parent lifetime scope is resolved.
You can opt out of IDisposable tracking either by registering the component as ExternallyOwned or by using Owned<T> in the constructor parameter being injected. (Instead of taking in an IDependency take in an Owned<IDependency>.)
Singletons live in the root lifetime scope. That means any time you resolve a singleton it will be resolved from the root lifetime scope. If it is IDisposable it will be tracked in the root lifetime scope and not released until that root scope - the container itself - is disposed.
The Func<T> dependency relationship is tied to the same lifetime scope as the object in which it's injected. If you have a singleton, that means the Func<T> will resolve things from the same lifetime scope as the singleton - the root lifetime scope. If you have something that's instance-per-dependency, the Func<T> will be attached to whatever scope the owning component is in.
Knowing that, you can see why your singleton, which takes in a Func<T>, keeps trying to resolve these things from the root lifetime scope. You can also see why you're seeing a memory leak situation - you haven't opted out of the disposal tracking for the things that are being resolved by that Func<T>.
So the question is, how do you fix it?
Option 1: Redesign
Generally speaking, it would be better to invert the relationship between the singleton and the thing you have to resolve via Func<T>; or stop using a singleton altogether and let that be a smaller lifetime scope.
For example, say you have some IDatabase service that needs an IPerformTransaction to get things done. The database connection is expensive to spin up, so you might make that a singleton. You might then have something like this:
public class DatabaseThing : IDatabase
{
public DatabaseThing(Func<IPerformTransaction> factory) { ... }
public void DoWork()
{
var transaction = this.factory();
transaction.DoSomethingWithData(this.Data);
}
}
So, like, the thing that's expensive to spin up uses a Func<T> to generate the cheap thing on the fly and work with it.
Inverting that relationship would look like this:
public PerformsTransaction : IPerformTransaction
{
public PerformsTransaction(IDatabase database) { ... }
public void DoSomethingWithData()
{
this.DoSomething(this.Database.Data);
}
}
The idea is that you'd resolve the transaction thing and it'd take the singleton in as a dependency. The cheaper item could easily be disposed along with child lifetime scopes (i.e., per request) but the singleton would remain.
It'd be better to redesign if you can because even with the other options you'll have a rough time getting "instance per request" sorts of things into a singleton. (And that's a bad idea anyway from both a captive dependency and threading standpoint.)
Option 2: Abandon Singleton
If you can't redesign, a good second choice would be to make the lifetime of the singleton... not be a singleton. Let it be instance-per-scope or instance-per-dependency and stop using Func<T>. Let everything get resolved from a child lifetime scope and be disposed when the scope is disposed.
I recognize that's not always possible for a variety of reasons. But if it is possible, that's another way to escape the problem.
Option 3: Use ExternallyOwned
If you can't redesign, you could register the disposable items consumed by the singleton as ExternallyOwned.
builder.RegisterType<ThingConsumedBySingleton>()
.As<IConsumedBySingleton>()
.ExternallyOwned();
Doing that will tell Autofac to not track the disposable. You won't have the memory leak. You will be responsible for disposing the resolved objects yourself. You will also still be getting them from the root lifetime scope since the singleton is getting a Func<T> injected.
public void MethodInsideSingleton()
{
using(var thing = this.ThingFactory())
{
// Do the work you need to and dispose of the
// resolved item yourself when done.
}
}
Option 4: Owned<T>
If you don't want to always manually dispose of the service you're consuming - you only want to deal with that inside the singleton - you could register it as normal but consume a Func<Owned<T>>. Then the singleton will resolve things as expected but the container won't track it for disposal.
public void MethodInsideSingleton()
{
using(var ownedThing = this.ThingFactory())
{
var thing = ownedThing.Value;
// Do the work you need to and dispose of the
// resolved item yourself when done.
}
}

How can I schedule a child activity to execute *before* the parent is completed?

I have a WF (4.5) workflow activity that creates a child workflow (evaluating a VisualBasicValue expression). I need the result before I complete the parent workflow.
I add the expression to the metadata like this:
private VisualBasicValue<string> _expression;
protected override void CacheMetadata(NativeActivityMetadata metadata)
{
base.CacheMetadata(metadata);
var visualBasicValue = (VisualBasicValue<string>)(_childActivity.Text.Expression);
var expressionText = visualBasicValue.ExpressionText;
_expression = new VisualBasicValue<string>(expressionText);
metadata.AddChild(_expression);
}
I tried scheduling the activity in the Execute method like this:
protected override void Execute(NativeActivityContext context)
{
context.ScheduleActivity(context, _expression, OnCompleted);
Result.Set(context, _value);
}
With a callback of:
private void OnCompleted(NativeActivityContext context, ActivityInstance completedInstance, string result)
{
_value = result;
}
Unfortunately, the _expression activity is only executed after the parent's execution method returns. Adding it as an implementation child doesn't work (it cannot work as an implementation child, as it is supposed to evaluate an expression that contains variables external to the parent).
Any ideas how to overcome this and execute within the execution context?
In code, as in real life, you can't schedule something to the past (yet :).
ScheduleActivity() will place the activity within an execution queue and execute it as soon as it can. As the parent activity is still running, _expression will only execute after it. Bottom-line, it's an asynchronous call.
If you want to control when _expression is called, just use WorkflowInvoker to execute it, synchronously, whenever you want.
public class MyNativeActivity : NativeActivity
{
private readonly VisualBasicValue<string> _expression;
public MyNativeActivity()
{
// 'expression' construction logic goes here
_expression = new VisualBasicValue<string>("\"Hi!\"");
}
protected override void Execute(NativeActivityContext context)
{
var _value = WorkflowInvoker.Invoke(_expression);
Console.WriteLine("Value returned by '_expression': " + _value);
// use '_value' for something else...
}
}
Took me a few days but I managed to resolve my own issue (without breaking the normal of how WF works).
What I ended up doing is, using reflection, iterated over the child's properties and created a LinkedList of evaluation expressions (using VisualBasicValue) of each of its arguments, in the CacheMetadata method. Then in the execution phase, I scheduled the execution of the first evaluation. In its callback I iterate over the remaining evaluations, scheduling the execution of the next evaluations, adding the result to a dictionary, until its done.
Finally, if there are no more evaluations to schedule, I schedule a final activity that takes the dictionary as its argument, and can do whatever it wants with it. Upon its own, it optionally returns the final result to the container's OutArgument.
What I previously failed to understand, is that even though the scheduling occurs after the instantiating activity's execution, the callback runs before control is returned to the host workflow application, and in that space I could work.