I use an embedded Grizzly web server to host RESTful web-services with Jersey. This is all working correctly.
My question is how to force the web application context to eagerly initialise when I start the server rather than waiting for the first incoming client request. This is a minor problem, but one I would like to solve.
I start the embedded server like this:
public final class TestApplication {
public TestApplication() throws Exception {
HttpServer httpServer = GrizzlyHttpServerFactory.createHttpServer(
"http://0.0.0.0:8888",
new ResourceConfig()
.registerInstances(
new TestBinder(),
)
.registerClasses(
JacksonJsonProvider.class,
)
.packages(
AbstractResource.class.getPackage().getName()
),
true
);
}
}
The "TestBinder" configures the dependency injection that I need and that class looks like this:
final class TestBinder extends AbstractBinder {
#Override
protected void configure() {
bind(CatalogManager.class).to(CatalogManager.class).in(Singleton.class);
}
}
Finally, "CatalogManager" is a singleton that is used to pre-load and cache all of the static data that my application exposes via the RESTful web-services.
The essence of "CatalogManager" is this:
public final class CatalogManager {
#PostConstruct
public void initialise() {
// Load and cache a large application data-set here...
}
}
So the problem is that the dependency injection and consequently the #PostConstruct method do not run when the server starts up, instead it waits until the first application request and the first user of my application gets a long delay.
Related
I am building a library that is supposed to add features into an aspnetcore WebApp.
My goal is to add Controllers written in the library to respond to requests on specific routes on the WebApp itself.
The first thing I've done is to write an extension method as such:
public static IApplicationBuilder UseCustomLibrary(this IApplicationBuilder app)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
//Here I want to hookup the routes to respond using my controller
}
Given that piece of code, I can now run app.UseCustomLibrary() from Program.cs.
Now, hooking up the actual controller to respond turns out to be not an easy task.
Things I've tried:
Using Custom Middleware:
public class MyCustomMiddleware
{
private readonly RequestDelegate _next;
public MyCustomMiddleware(RequestDelegate next)
{
_next = next ?? throw new ArgumentNullException(nameof(next));
}
public async Task Invoke(HttpContext context)
{
if (context.Request.Path.Value.Contains("expectedpath"))
{
//Manually handle the request.
}
await _next(context);
}
}
Even though that kind of works, that doesn't really hookup the controller. Instead I can handle the request manually. I dislike that because I now have to rewrite the controller into some kind of handler. That forces to abandon the nice controller structure of automatically determining the route using area/controller/action pattern. So this is currently my plan B.
Using Custom IApplictionFeatureProviders:
internal class MyCustomFeatureProvider : IApplicationFeatureProvider<ControllerFeature>
{
public void PopulateFeature(IEnumerable<ApplicationPart> parts, ControllerFeature feature)
{
if (!feature.Controllers.Contains(typeof(CustomController).GetTypeInfo()))
{
feature.Controllers.Add(typeof(CustomController).GetTypeInfo());
}
}
}
Then I would slightly modify the extension method to be call that provider as such:
public static IApplicationBuilder UseCustomLibrary(this IApplicationBuilder app)
{
app.Services.AddMvc().PartManager.FeatureProviders.Add(new MyCustomFeatureProvider());
return builder;
}
I was trying to copy what Microsoft.Identity library does in how it adds the "AccountController". Unfortunately that also doesn't work. The controller actions are never called for some reason.
I have also tried using that in conjunction with the middleware, by replacing the invoke method of the middleware with the following:
public async Task Invoke(HttpContext context)
{
context.Features.Set<IApplicationFeatureProvider<ControllerFeature>>(new MyCustomFeatureProvider());
await _next(context);
}
Again, that simply does nothing and the controller actions are never called.
I've also tried calling app.MapControllerRoute from my extension method, but it doesn't work as well for a reason that I cannot understand. It seems the controller is not even registered so it is never called.
I am willing to provide more details. I know there must be a way to do that, since it is used all the time in Microsoft.Identity and Microsoft.AspNetCore.Authentication to respond to authentication callbacks from IdPs for example. So there must be a way to do what I want.
I am trying to implement Data Protection in my .net core application. The implementation is pretty straightforward, use IXmlRepository and store the Keys in Postgres DB. This works fine when I run it on my local system, the key gets stored in the DB and with every request it gets checked.
The problem surfaces when I trying to run it in Docker. The key still gets stored in the DB but as soon as I launch the application it throws this error
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
An unhandled exception has occurred while executing the request.
System.IO.DirectoryNotFoundException: C:\App\locale\
From the looks of it, it seems like the application is not looking for the key in the DB but in C:\App\locale\ and I am not sure why the implementation resorts to the default implementation PersistKeysToFileSystem. Below is the code snippet
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
... other services.....
services.ConfigureDataProtectionService();
}
ServiceExtension.cs
public static class DataProtectionsServiceExtension
{
public static void ConfigureDataProtectionService(this IServiceCollection services)
{
services.ConfigureDataProtection();
}
private static void ConfigureDataProtection(this IServiceCollection services)
{
var builder = services.AddDataProtection();
builder.Services.AddSingleton<IConfigureOptions<KeyManagementOptions>>(
serviceProvider =>
{
var xmlRepository = serviceProvider.Resolve<IXmlRepository>();
return new ConfigureOptions<KeyManagementOptions>(options => options.XmlRepository = xmlRepository);
});
}
}
Could anyone help me with this. Thanks
I use Unity in an MVC5 project (.net461) for DI and I want to register a service with multiple lifetimes.
With the classic core DI I would use RegisterScoped and that's it. Whenever the service is resolved within an Http Request I would reuse the same instance for the duration of the request. If I want to fire a background task, that background task should open a service scope, and I would resolve a new instance for the service for the duration of that scope. No need to have different registrations for the service. In the first case, the scope is created by the runtime, and in the second it is manually created by the developer. In both cases, the service provider only knows that the service is scoped, it doesn't care about where and how the scope has opened.
With Unity the first case is solved with PerRequestLifetimeManager. The second case is solved with a HierarchicalLifetimeManager.
But how should I have a combination of the two?
Whenever a service is resolved within an HttpRequest (in a controller constructor for instace) it should use the PerRequestLifetimeManager and wherever it is resolved in a child container (within the constructor of another service that is instantiated in the child container) it should use HierarchicalLifetimeManager.
How can I register the service with both managers?
At the end of the day, I had to implement my own solution which is based on (but not using) Unity.Mvc, Unity.WebApi packages, and the HierarchicalLifetimeManager.
None of the solutions I found online worked for my case. Most of them covered only the per request part, but not the per custom user scope part.
The key of the solution is not the lifetime manager but the dependency resolver. The lifetime manager for my requirements should always be HierarchicalLifetimeManager because that is what I truly need. A new container for each scope, which is covered by child containers and HierarchicalLifetimeManager.
Using Integrating ASP.NET Core Dependency Injection in MVC 4 as an example on how to implement your own dependency resolver, I came up with the solution below.
What I had to do, is to make sure a new scope is created on the beginning of the Http Request, and Disposed at the end of the Http Request. This part is covered by implementing a simple HttpModule. This part is similar to the HttpModule used by the official Unity Per Request Lifetime implementation.
Per Http Request Module
This is the module implementation
internal class UnityPerHttpRequestModule : IHttpModule
{
private static IUnityContainer _rootContainer;
public void Init(HttpApplication context)
{
context.BeginRequest += (s, e) =>
((HttpApplication)s).Context.Items[typeof(UnityPerHttpRequestModule)]
= _rootContainer.CreateChildContainer();
context.EndRequest += (s, e) =>
(((HttpApplication)s).Context.Items[typeof(UnityPerHttpRequestModule)]
as IUnityContainer)?.Dispose();
}
public static void SetRootContainer(IUnityContainer rootContainer)
{
_rootContainer = rootContainer ?? throw new ArgumentNullException(nameof(rootContainer));
}
public void Dispose() { }
}
On Beginning the request we create a new child container and place it in the HttpRequest Items dictionary.
On Ending the request we retrieve the child container from the Items dictionary and dispose it.
The static method SetRootContainer should be called once at the startup of the application to pass in the initial root Unity container, the one that services are registered on.
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
UnityPerHttpRequestModule.SetRootContainer(UnityConfig.Container); // pass here the root container instance
...
}
}
We also need to register the module with owin.
using Microsoft.Owin;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Owin;
[assembly: OwinStartup(typeof(MyApp.Startup))]
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(MyApp.Startup), nameof(MyApp.Startup.InitScopedServicesModule))]
namespace MyApp
{
public partial class Startup
{
public static void InitScopedServicesModule()
{
DynamicModuleUtility.RegisterModule(typeof(UnityPerHttpRequestModule));
}
public void Configuration(IAppBuilder app)
{
}
}
}
MVC Dependency Resolver
Now the http module is registered and we have a new scope created on each request. Now we need to instruct MVC and WebApi to use that scope. For this, we need to create the appropriate dependency resolvers. I created one dependency resolver for MVC and one for WebApi since they need to implement different interfaces (I could have implemented both in the same class though).
The dependency resolver for MVC is this:
internal class UnityMvcPerHttpRequestDependencyResolver : IDependencyResolver
{
private readonly IUnityContainer rootContainer;
internal UnityMvcPerHttpRequestDependencyResolver(IUnityContainer rootContainer)
{
this.rootContainer = rootContainer;
}
internal IUnityContainer Current => (HttpContext.Current?.Items[typeof(UnityPerHttpRequestModule)] as IUnityContainer) ?? this.rootContainer;
public void Dispose() { }
public object GetService(Type serviceType)
{
try
{
return Current.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return Current.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
}
What the resolver does is that it checks for an HTTP Context and gets the unity container in the Context's item dictionary and uses this container to resolve the services. So effectively, if the service requested is registered with a Hierarchical Lifetime, a new instance of that service will be created within the child container (aka within the context of the request). Since the child container is disposed at the end of the request by the http module, any services instantiated in the child container are also disposed.
Things to notice here:
The IDependencyResolver interface here is the System.Web.Mvc.IDependencyResolver. This is the interface expected by the MVC. The WebApi expects a difference IDependencyResolver (same name, different namespaces)
Catching ResolutionFailedException. If you don't catch those exceptions, the application will crash.
Now that we have the MVC dependecy resolver, we need to instruct MVC to use this resolver.
public static class UnityMvcActivator
{
public static void Start()
{
FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(UnityConfig.Container));
//DependencyResolver.SetResolver(new UnityDependencyResolver(UnityConfig.Container));
DependencyResolver.SetResolver(new UnityMvcPerHttpRequestDependencyResolver(UnityConfig.Container));
// TODO: Uncomment if you want to use PerRequestLifetimeManager
//Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
}
Things to notice here:
Do not register the official UnityPerRequestHttpModule since we implement our own. ( I could probably use that module but my implementation would depend on the inner implementation of the official module and I don't want that, since it may change later)
Web Api Dependency Resolver
Simlilar to MVC dependency resolver, we need to implement one for the Web Api
internal class UnityWebApiPerHttpRequestDependencyResolver : IDependencyResolver
{
private readonly IUnityContainer rootContainer;
internal UnityWebApiPerHttpRequestDependencyResolver(IUnityContainer rootContainer)
{
this.rootContainer = rootContainer;
}
internal IUnityContainer Current => (HttpContext.Current?.Items[typeof(UnityPerHttpRequestModule)] as IUnityContainer) ?? this.rootContainer;
public IDependencyScope BeginScope() => this;
// Dispose, GetService and GetServices are the same as MVC dependency resolver
}
Things to notice here:
IDependencyResolver here is of type System.Web.Http.Dependencies.IDependencyResolver. It is not the same as MVC's IDependencyResolver.
This Dependency resolver interface implements one more method: BeginScope. This is important here. WebApi pipeline is different that MVC pipeline. WebApi engine, by default, calls BeginScope to open a new scope for each web api request, and uses that scope to resolve controllers and services. So, Web api has already a scoped mechanism. BUT we have already created a scope ourselves with our per request module and we want to use that scope. So what we have to do here is to not create a new scope again. It already exists. So calling BeginScope on our resolver should return the same resolver scope, thus we return this.
Now that we have created the WebApi resolver, we have to also register it to web api.
using System.Web.Http;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(MyApp.UnityWebApiActivator), nameof(MyApp.UnityWebApiActivator.Start))]
namespace MyApp
{
/// <summary>
/// Provides the bootstrapping for integrating Unity with WebApi when it is hosted in ASP.NET.
/// </summary>
public static class UnityWebApiActivator
{
/// <summary>
/// Integrates Unity when the application starts.
/// </summary>
public static void Start()
{
// Use UnityHierarchicalDependencyResolver if you want to use
// a new child container for each IHttpController resolution.
// var resolver = new UnityHierarchicalDependencyResolver(UnityConfig.Container);
var resolver = new UnityWebApiPerHttpRequestDependencyResolver(UnityConfig.Container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
}
}
}
Registering services
Now that we have set up and registered all our Resolvers and modules, the last thing to do is to remember to register each scoped service with HierarchicalLifetimeManager. Since our scoped solution depends on child containers, registering our scoped services that way will suffice.
Conclusion
And with that, I managed to implement a working scoped DI solution with Unity. The example below did not work with the official Per Request Lifetime solution, but worked with my custom implementation.
class TestController{
private readonly IMyScopedService service;
private readonly IUnityContainer container;
public TestController(IUnityContainer container, IMyScopedService service){
this.service = service;
this.container = container;
}
public ActionResult Post( ... ){
var childContainer = this.container.CreateChildContainer();
var scopedService = childContainer.GetService<IMyScopedService>()
HostingEnviroment.QueueBackgroundWorkItem(() => {
using(childContainer){
scopedService.DoWork();
}
});
}
}
With the official PerRequestLifetimeManager solution, this.service and scopedService were the same instance. The scoped service was instantiated in the http context, then the same instance was fetched again from the child container (since it was registerd with PerRequestLifetimeManager and not HierarchicalLifetimeManager) and passed to the background Job. The background job outlives the http request. The instance is disposed when the Http requests ends, but it is still being used in the background job which probably runs in another thread. Concurrency issues (and more) arise. For instance you can't use the same instance of an EF DbContext in multiple threads.
With the custom implementation above, the example works. scopedService is a different instance since it is registered with a HierarchicalLifetimeManager. this.services is disposed when the http request ends but scopedService lives during the whole execution of the background Job.
What we effectively do is control the lifetime of the services by controlling the lifetime of child containers. And I have the impression that this is the solution for every scoped service scenario.
Register all scoped services with HierarchicalLifetimeManager
Control the lifetime of services by controlling the lifetime of the child containers.
I am currently building a Dropwizard + Guice + Jersey-based application where the database access is being handled by JDBI for the time being.
What I am trying to achieve is to have your typical enterprise architecture, where Resources access Service classes accessing a DAO class that in turn accesses the database. It would be nice to get all this wired up in a proper DI way, although I guess I can build my object graph in the run() method of the application if all else fails.
So, I'm running into this problem that has been mentioned here before: Getting a DBIFactory requires both the Environment and the Configuration, which somehow need to be available at the time when Guice does its injection magic and not at run()-time.
Being a Dropwizard and Guice noob, what I've managed to put together so far is that I need a Provider for my DAO objects, something to the tune of
public class UserDAOProvider implements Provider<UserDAO> {
#Inject
Environment environment;
#Inject
Configuration configuration;
#Override
public UserDAO get() {
final DBIFactory factory = new DBIFactory();
final (MyConfiguration) config = (MyConfiguration) configuration;
DBI jdbi = null;
try {
jdbi = factory.build(environment, config.getDataSourceFactory(),
"mysql");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return jdbi.onDemand(UserDAO.class);
}
}
Registering this as a singleton provider should let me then inject the UserDAO into my Services.
Now, how do we actually get the environment injected into the Provider? Currently I am stuck at Guice complaining about not finding a suitable constructor for the Environment, so it is trying to instantiate it and not grab it from Dropwizard itself.
It seems like this is doable; there is the dropwizard-guice package whose DropWizardEnvironmentModule is, I think, what I need. But I feel like I'm just missing some piece of the puzzle here for an understanding of how to put things together. I've not managed to find a complete working example so far...
I had the same issue as OP but using Hibernate rather than JDBI. My simple solution is applicable to JDBI, though - just switch DBIFactory for SessionFactory.
First add an injection provider for a singleton SessionFactory in your Guice module:
public class MyModule extends AbstractModule {
private SessionFactory sessionFactory;
#Override
protected void configure() {
}
#Provides
SessionFactory providesSessionFactory() {
if (sessionFactory == null) {
throw new ProvisionException("The Hibernate session factory has not yet been set. This is likely caused by forgetting to call setSessionFactory during Application.run()");
}
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
You need to set the singleton SessionFactory from your application's run() method. In your case, using JDBI, this is where you would create and configure your DBIFactory before handing it over to the Guice module:
public void run(MyConfiguration configuration, Environment environment) {
myModule.setSessionFactory(hibernateBundle.getSessionFactory());
...
}
Now SessionFactory can be injected wherever it is needed. I now use implicit binding for my DAO classes by just annotating the constructor with #Inject and injecting the SessionFactory singleton. I don't explicitly create providers for DAO classes:
#Singleton
public class WidgetDAO extends AbstractDAO<App> {
#Inject
public WidgetDAO(SessionFactory factory) {
super(factory);
}
public Optional<Widget> findById(Long id) {
return Optional.fromNullable(get(id));
}
...
}
Now I can inject my DAO singleton instances into resources:
#Path("/widgets")
#Produces(MediaType.APPLICATION_JSON)
public class WidgetsResource {
private final WidgetDAO widgetDAO;
#Inject
public WidgetsResource(WidgetDAO widgetDAO) {
this.widgetDAO = widgetDAO;
}
...
}
Note that this approach follows the Guice recommendation of injecting direct dependencies only. Don't try to inject Envrionment and Configuration just so that you can create a DBI factory - inject the prebuilt DBI factory itself.
This is how I use Guice with Dropwizard. Inside your run() method add the line
Guice.createInjector(new ConsoleModule());
You cannot inject Environ
Create the class ConsoleModule
public class ConsoleModule extends AbstractModule {
//configuration and env variable declaration
public ConsoleModule(ConsoleConfiguration consoleConfig, Environment env)
{
this.consoleConfig = consoleConfig;
this.env= env;
}
protected void configure()
{
//You should not inject Configuration and Environment in your provider since you are mixing
//dropwizard framework stuff with Guice.Neverthless you will have to bind them in the below order
bind(Configuration.class).toInstance(consoleConfig.class);
bind(Environment.class).toInstance(env.class);
bind(UserDAO.class).toProvider(UserDAOProvider.class).in(Singleton.class);
}
}
We have the same configuration (dw-jdbi-guice) and also an abstract 'base' Application class which complicates things even more.
Since a lot of things happen during run method, and many things depend on the configuration objects we ended up creating the injector in the run method. But since we need objects from bootsrap also (e.g. ObjectMapper), we ended up having a List<Module> field in the Application class. Not the prettiest solution but can handle variety of scenarios.
We have an application with a plugin which contains a service:
public class TaskService {
public void doSomething( Task task ) {
// do something with task
task.save();
}
}
This works fine.
For our "special" customer with his special requirements we have a second application which contains the plugin from the first application and another plugin with a special service for this customer which extends the original service and overrides some methods:
public class SpecialTaskService extends TaskService{
#Override
public void doSomething( Task task ) {
// do something special with task
task.save();
}
}
In every place in the second application where taskService is injected we want to have the SpecialTaskService now (also in the plugin from the first application). So we have added the special service to the resources.groovy under grails-app/conf/spring:
beans = {
taskService( SpecialTaskService )
}
But now we get an HibernateException when we call "task.save()" in the special service:
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
We know that we could inject a SessionFactory into the SpecialService, but when we call sessionFactory.currentSession we get the same Exception.
The exception also occurs when we configure a service in resources.groovy which does not extend another one.
Is there a way to make the special service some kind of "hibernateSessionAware" so that we can call save() and merge() on domain objects?
The original service is transactional, so it keeps a Hibernate session open for the duration of the method call (unless one is already active and it has joined that). So you need to make yours transactional too since you're just telling Spring to create a plain new instance with taskService(SpecialTaskService)
The simplest thing to do is annotate the class (or individual methods if you prefer):
import org.springframework.transaction.annotation.Transactional
#Transactional
class SpecialTaskService extends TaskService {
#Override
void doSomething(Task task) {
// do something special with task
task.save()
}
}
but you can also wrap code blocks or entire methods in withTransaction blocks:
class SpecialTaskService extends TaskService {
#Override
void doSomething(Task task) {
Task.withTransaction { status ->
// do something special with task
task.save()
}
}
}