Is it possible to run Quartz.NET jobs in a separate AppDomain? If so, how can this be achieved?
Disclaimer: I've not tried this, it's just an idea. And none of this code has been compiled, even.
Create a custom job factory that creates a wrapper for your real jobs. Have this wrapper implement the Execute method by creating a new app domain and running the original job in that app domain.
In more detail: Create a new type of job, say IsolatedJob : IJob. Have this job take as a constructor parameter the type of a job that it should encapsulate:
internal class IsolatedJob: IJob
{
private readonly Type _jobType;
public IsolatedJob(Type jobType)
{
_jobType = jobType ?? throw new ArgumentNullException(nameof(jobType));
}
public void Execute(IJobExecutionContext context)
{
// Create the job in the new app domain
System.AppDomain domain = System.AppDomain.CreateDomain("Isolation");
var job = (IJob)domain.CreateInstanceAndUnwrap("yourAssembly", _jobType.Name);
job.Execute(context);
}
}
You may need to create an implementation of IJobExecutionContext that inherits from MarshalByRefObject and proxies calls onto the original context object. Given the number of other objects that IJobExecutionContext provides access to, I'd be tempted to implement many members with a NotImplementedException as most won't be needed during job execution.
Next you need the custom job factory. This bit is easier:
internal class IsolatedJobFactory : IJobFactory
{
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
return NewJob(bundle.JobDetail.JobType);
}
private IJob NewJob(Type jobType)
{
return new IsolatedJob(jobType);
}
}
Finally, you will need to instruct Quartz to use this job factory rather than the out of the box one. Use the IScheduler.JobFactory property setter and provide a new instance of IsolatedJobFactory.
Related
I'm trying to add Dagger to an existing web application and am running into a design problem.
Currently our Handlers are created in a dispatcher with something like
registerHandler('/login', new LoginHandler(), HttpMethod.POST)
Inside the login handler we might call a function like
Services.loginService.login('username', 'password');
I want to be able to inject the loginService into the handler, but am having trouble figuring out the best approach. There is a really long list of handlers in the dispatcher, and injecting them all as instance variables seems like a large addition of code.
Is there a solution to this type of problem?
Based on your comment about having different services to inject. I would propose next solution.
ServicesProvider:
#Module(injects = {LoginHandler.class, LogoutHandler.class})
public class ServicesProvider {
#Provides #Singleton public LoginService getLoginService() {
return new LoginService();
}
}
LoginHandler.java:
public class LoginHandler extends Handler {
#Inject LoginService loginService;
}
HttpNetwork.java
public class HttpNetwork extends Network {
private ObjectGraph objectGraph = ObjectGraph.create(new ServicesProvider());
public registerHandler(String path, Handler handler, String methodType) {
getObjectGraph().inject(handler);
}
}
There is one week point in this solution - you can't easily change ServiceProvider for test purpose (or any other kind of purpose). But if you inject it also (for example with another object graph or just through constructor) you can fix this situation.
In my Grails app I've installed the Quartz plugin. I want to intercept calls to every Quartz job class' execute method in order to do something before the execute method is invoked (similar to AOP before advice).
Currently, I'm trying to do this interception from the doWithDynamicMethods closure of another plugin as shown below:
def doWithDynamicMethods = { ctx ->
// get all the job classes
application.getArtefacts("Job").each { klass ->
MetaClass jobMetaClass = klass.clazz.metaClass
// intercept the methods of the job classes
jobMetaClass.invokeMethod = { String name, Object args ->
// do something before invoking the called method
if (name == "execute") {
println "this should happen before execute()"
}
// now call the method that was originally invoked
def validMethod = jobMetaClass.getMetaMethod(name, args)
if (validMethod != null) {
validMethod.invoke(delegate, args)
} else {
jobMetaClass.invokeMissingMethod(delegate, name, args)
}
}
}
}
So, given a job such as
class TestJob {
static triggers = {
simple repeatInterval: 5000l // execute job once in 5 seconds
}
def execute() {
"execute called"
}
}
It should print:
this should happen before execute()
execute called
But my attempt at method interception seems to have no effect and instead it just prints:
execute called
Perhaps the cause of the problem is this Groovy bug? Even though the Job classes don't explicitly implement the org.quartz.Job interface, I suspect that implicitly (due to some Groovy voodoo), they are instances of this interface.
If indeed this bug is the cause of my problem, is there another way that I can do "before method interception"?
Because all the job classes are Spring beans you can solve this problem using Spring AOP. Define an aspect such as the following (adjust the pointcut definition so that it matches only your job classes, I've assumed they are all in a package named org.example.job and have a class name that ends with Job).
#Aspect
class JobExecutionAspect {
#Pointcut("execution(public * org.example.job.*Job.execute(..))")
public void executeMethods() {}
#Around("executeMethods()")
def interceptJobExecuteMethod(ProceedingJoinPoint jp) {
// do your stuff that should happen before execute() here, if you need access
// to the job object call jp.getTarget()
// now call the job's execute() method
jp.proceed()
}
}
You'll need to register this aspect as a Spring bean (it doesn't matter what name you give the bean).
You can have your customized JobListener registered in the application to handle logics before execute() is triggered. You can use something like:-
public class MyJobListener implements JobListener {
public void jobToBeExecuted(JobExecutionContext context) {
println "Before calling Execute"
}
public void jobWasExecuted(JobExecutionContext context,
JobExecutionException jobException) {}
public void jobExecutionVetoed(JobExecutionContext context) {}
}
Register the customized Job Listener to Quartz Scheduler in Bootstrap:-
Scheduler scheduler = ctx.getBean("quartzScheduler") //ctx being application context
scheduler.getListenerManager().addJobListener(myJobListener, allJobs())
resources.groovy:-
beans = {
myJobListener(MyJobListener)
}
One benefit I see here using this approach is that we don't need the second plugin used for method interception any more.
Second, we can register the listener to listen all jobs, specific jobs, and jobs in a group. Refer Customize Quartz JobListener and API for JobListener, TriggerListener, ScheduleListener for more insight.
Obviously, AOP is another approach if we do want want to use Quartz API.
You are not getting the job classes like that. If you refer to the Quartz plugin, you can get them by calling jobClasses:
application.jobClasses.each {GrailsJobClass tc -> ... }
see https://github.com/nebolsin/grails-quartz/blob/master/QuartzGrailsPlugin.groovy
If you actually look, you can see that they are almost doing what you are trying to acheive without the need to use aop or anything else.
For method interception implement invokeMethod on the metaclass. In my case the class was not of third party so I can modify the implementation.
Follow this blog for more information.
Job class must implement the Job interface."I created simple job using Quartz.Net 1.0.3
public class SimpleTestJob : IJob
{
public virtual void Execute(JobExecutionContext context)
{
System.Diagnostics.EventLog.WriteEntry("QuartzTest", "This is a test run");
}
}
Then I am tried dynamically add the job above to the Quartz server
First I received a Type using reflection
string jobType = "Scheduler.Quartz.Jobs.SimpleTestJob,Scheduler.Quartz,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null";
var schedType= Type.GetType(jobType, false, true);
It's working.Then I am trying to create JobDetail object
JobDetail job = job = new JobDetail(jobName, groupName, schedType.GetType());
But I am receiving an error from Quartz.Net framework.
"Job class must implement the Job interface."
Please help
Try removing the virtual keyword and you might also want to try using the typeof operator where you have schedType.GetType(). I'm not sure what the type of schedType ends up being given it is defined as var.
I am using Quartz 1.0.3 it's compiled with .net 3.5.
But schedType.GetType
returned type with attribute RunTime version 4.
Really I do not need to use GetType function because I alread have a type, that I received before
var schedType= Type.GetType(jobType, false, true);
So my fix was
JobDetail job = new JobDetail(jobName, groupName, schedType);
Let's say we have class:
public class WithDependencies
{
public WithDependencies(IAmDependencyOne first, IAmDependencyTwo second)
// ...
}
Now the question. How do you create objects of WithDependencies class in an application?
I know there are many ways.
new WithDependencies(new DependencyOne(), new DependencyTwo());
new WithDependencies(IoC.Resolve(IDependencyOne), IoC.Resolve(IDependencyTwo());
// register IDependencyOne, IDependencyTwo implementations at app start
IoC.Resolve(WithDependencies);
// register IDependencyOne, IDependencyTwo implementations at app start
// isolate ourselves from concrete IoC Container
MyCustomWithDependenciesFactory.Create();
and so on...
What do you think is the way to do it?
Edit:
Because I don't get answers or I don't understand them I'll try to ask again. Let's say that on some event (button, timer, whatever) I need new object WithDependencies(). How do I create it? Assume IoC container is already configured.
It depends on the context, so it's impossible to provide a single answer. Conceptually you'd be doing something like this from the Composition Root:
var wd = new WithDependencies(new DependencyOne(), new DependencyTwo());
However, even in the absence of a DI Container, the above code isn't always unambiguously the correct answer. In some cases, you might want to share the same dependency among several consumers, like this:
var dep1 = new DependencyOne();
var wd = new WithDependencies(dep1, new DependencyTwo());
var another = AnotherWithDependencies(dep1, new DependencyThree());
In other cases, you might not want to share dependencies, in which case the first option is more correct.
This is just a small glimpse of an entire dimension of DI concerned with Lifetime Management. Many DI Containers can take care of that for you, which is one excellent argument to prefer a DI Container over Poor Man's DI.
Once you start using a DI Container, you should follow the Register Resolve Release pattern when resolving types, letting Auto-wiring take care of the actual composition:
var wd = container.Resolve<WithDependencies>();
The above example assumes that the container is already correctly configured.
If you need to create a dependency which has its own dependencies, you can either A) do it yourself, or B) ask something else to do it for you. Option A negates the benefits of dependency injection (decoupling, etc.), so I would say option B is a better starting point. Now, we have chosen to use the factory pattern, no matter whether it takes the form of a service locator (i.e. IoC.Resolve), a static factory, or an instance factory. The point is that we have delegated that responsibility to an external authority.
There are a number of trade-offs required for static accessors. (I went over them in another answer, so I won't repeat them here.) In order to avoid introducing a dependency on the infrastructure or the container, a solid option is to accept a factory for creating WithDependencies when we need an instance somewhere else:
public class NeedsWithDependencies
{
private readonly IWithDependenciesFactory _withDependenciesFactory;
public NeedsWithDependencies(IWithDependenciesFactory withDependenciesFactory)
{
_withDependenciesFactory = withDependenciesFactory;
}
public void Foo()
{
var withDependencies = _withDependenciesFactory.Create();
...Use the instance...
}
}
Next, we can create a container-specific implementation of the factory:
public class WithDependenciesFactory : IWithDependenciesFactory
{
private readonly IContainer _container;
public WithDependenciesFactory(IContainer container)
{
_container = container
}
public WithDependencies Create()
{
return _container.Resolve<WithDependencies>();
}
}
Now NeedsWithDependencies is completely isolated from any knowledge of how WithDependencies gets created; it also exposes all its dependencies in its constructor, instead of hiding dependencies on static accessors, making it easy to reuse and test.
Defining all those factories can get a little cumbersome, though. I like Autofac's factory relationship type, which will detect parameters of the form Func<TDependency> and automatically inject a function which serves the same purpose as the hand-coded factory above:
public class NeedsWithDependencies
{
private readonly Func<WithDependencies> _withDependenciesFactory;
public NeedsWithDependencies(Func<WithDependencies> withDependenciesFactory)
{
_withDependenciesFactory = withDependenciesFactory;
}
public void Foo()
{
var withDependencies = _withDependenciesFactory();
...Use the instance...
}
}
It also works great with runtime parameters:
public class NeedsWithDependencies
{
private readonly Func<int, WithDependencies> _withDependenciesFactory;
public NeedsWithDependencies(Func<int, WithDependencies> withDependenciesFactory)
{
_withDependenciesFactory = withDependenciesFactory;
}
public void Foo(int x)
{
var withDependencies = _withDependenciesFactory(x);
...Use the instance...
}
}
Sometimes I try to get rid of factories or at least not depend directly on them, so Dependency Injection (without factories) is useful of course.
Therefore I use Google Juice, cause its a small little framework using Java Annotations and you can quickly change your injections / dependencies. Just take a look at it:
http://code.google.com/p/google-guice/
We are trying to figure out how to setup Dependency Injection for situations where service classes can have different dependencies based on how they are used. In our specific case, we have a web app where 95% of the time the connection string is the same for the entire Request (this is a web application), but sometimes it can change.
For example, we might have 2 classes with the following dependencies (simplified version - service actually has 4 dependencies):
public LoginService (IUserRepository userRep)
{
}
public UserRepository (IContext dbContext)
{
}
In our IoC container, most of our dependencies are auto-wired except the Context for which I have something like this (not actual code, it's from memory ... this is StructureMap):
x.ForRequestedType().Use()
.WithCtorArg("connectionString").EqualTo(Session["ConnString"]);
For 95% of our web application, this works perfectly. However, we have some admin-type functions that must operate across thousands of databases (one per client). Basically, we'd want to do this:
public CreateUserList(IList<string> connStrings)
{
foreach (connString in connStrings)
{
//first create dependency graph using new connection string
????
//then call service method on new database
_loginService.GetReportDataForAllUsers();
}
}
My question is: How do we create that new dependency graph for each time through the loop, while maintaining something that can easily be tested?
To defer the creation of an object until runtime, you can use a factory:
public interface ILoginServiceFactory
{
ILoginService CreateLoginService(string connectionString);
}
Usage:
public void CreateUserList(IList<string> connStrings)
{
foreach(connString in connStrings)
{
var loginService = _loginServiceFactory.CreateLoginService(connString);
loginService.GetReportDataForAllUsers();
}
}
Within the loop, do:
container.With("connectionString").EqualTo(connString).GetInstance<ILoginService>()
where "connectionString" is the name of a string constructor parameter on the concrete implementation of ILoginService.
So most UserRepository methods use a single connection string obtained from session, but several methods need to operate against a list of connection strings?
You can solve this problem by promoting the connection string dependency from IContext to the repository and adding two additional dependencies - a context factory and a list of all the possible connections strings the repository might need to do its work:
public UserRepository(IContextFactory contextFactory,
string defaultConnectionString,
List<string> allConnectionStrings)
Then each of its methods can build as many IContext instances as they need:
// In UserRepository
public CreateUserList() {
foreach (string connString in allConnectionStrings) {
IContext context = contextFactory.CreateInstance(connString);
// Build the rest of the dependency graph, etc.
_loginService.GetReportDataForAllUsers();
}
}
public LoginUser() {
IContext context = contextFactory.CreateInstance(defaultConnectionString);
// Build the rest of the dependency graph, etc.
}
We ended up just creating a concrete context and injecting that, then changing creating a wrapper class that changed the context's connection string. Seemed to work fine.