Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@
<version>3.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>r09</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand Down
36 changes: 33 additions & 3 deletions src/main/java/org/nnsoft/guice/guartz/InjectorJobFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import javax.inject.Inject;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.spi.JobFactory;
Expand All @@ -33,7 +35,7 @@ final class InjectorJobFactory
implements JobFactory
{

/**
/**
* The delegated {@link Injector}.
*/
@Inject
Expand All @@ -55,8 +57,36 @@ public void setInjector( Injector injector )
public Job newJob( TriggerFiredBundle bundle, Scheduler scheduler )
throws SchedulerException
{
Class<? extends Job> jobClass = bundle.getJobDetail().getJobClass();
return this.injector.getInstance( jobClass );
final Class<? extends Job> jobClass = bundle.getJobDetail().getJobClass();

Job decorator = new JobScopeDecorator(jobClass);

return decorator;
}

private final class JobScopeDecorator implements Job {

private final Class<? extends Job> decoratedJobClass;

Job decorated;

private JobScopeDecorator(Class<? extends Job> jobClass) {
this.decoratedJobClass = jobClass;
}

public void execute(JobExecutionContext context) throws JobExecutionException
{
// See http://code.google.com/p/google-guice/wiki/CustomScopes#Triggering_the_Scope
final QuartzJobScope scope = InjectorJobFactory.this.injector.getInstance( QuartzJobScope.class );
scope.enter();
try
{
decorated = InjectorJobFactory.this.injector.getInstance( decoratedJobClass );
decorated.execute( context );
} finally {
scope.exit();
}
}
}

}
91 changes: 91 additions & 0 deletions src/main/java/org/nnsoft/guice/guartz/QuartzJobScope.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package org.nnsoft.guice.guartz;

import static com.google.common.base.Preconditions.checkState;
import com.google.common.collect.Maps;
import com.google.inject.Key;
import com.google.inject.OutOfScopeException;
import com.google.inject.Provider;
import com.google.inject.Scope;
import java.util.Map;

/**
* Scopes a Quartz Job Execution.
*
* Based on: http://code.google.com/p/google-guice/wiki/CustomScopes#Implementing_Scope
*
* @author Bruno Medeiros
*/
public class QuartzJobScope implements Scope
{

private static final Provider<Object> SEEDED_KEY_PROVIDER =
new Provider<Object>() {
public Object get() {
throw new IllegalStateException("If you got here then it means that" +
" your code asked for scoped object which should have been" +
" explicitly seeded in this scope by calling" +
" SimpleScope.seed(), but was not.");
}
};

private final ThreadLocal<Map<Key<?>, Object>> values
= new ThreadLocal<Map<Key<?>, Object>>();

public void enter() {
checkState(values.get() == null, "A scoping block is already in progress");
values.set(Maps.<Key<?>, Object>newHashMap());
}

public void exit() {
checkState(values.get() != null, "No scoping block in progress");
values.remove();
}

public <T> void seed(Key<T> key, T value) {
Map<Key<?>, Object> scopedObjects = getScopedObjectMap(key);
checkState(!scopedObjects.containsKey(key), "A value for the key %s was " +
"already seeded in this scope. Old value: %s New value: %s", key,
scopedObjects.get(key), value);
scopedObjects.put(key, value);
}

public <T> void seed(Class<T> clazz, T value) {
seed(Key.get(clazz), value);
}

public <T> Provider<T> scope(final Key<T> key, final Provider<T> unscoped) {
return new Provider<T>() {
public T get() {
Map<Key<?>, Object> scopedObjects = getScopedObjectMap(key);

@SuppressWarnings("unchecked")
T current = (T) scopedObjects.get(key);
if (current == null && !scopedObjects.containsKey(key)) {
current = unscoped.get();
scopedObjects.put(key, current);
}
return current;
}
};
}

private <T> Map<Key<?>, Object> getScopedObjectMap(Key<T> key) {
Map<Key<?>, Object> scopedObjects = values.get();
if (scopedObjects == null) {
throw new OutOfScopeException("Cannot access " + key
+ " outside of a scoping block");
}
return scopedObjects;
}

/**
* Returns a provider that always throws exception complaining that the object
* in question must be seeded before it can be injected.
*
* @return typed provider
*/
@SuppressWarnings({"unchecked"})
public static <T> Provider<T> seededKeyProvider() {
return (Provider<T>) SEEDED_KEY_PROVIDER;
}
}
21 changes: 21 additions & 0 deletions src/main/java/org/nnsoft/guice/guartz/QuartzJobScoped.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.nnsoft.guice.guartz;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.google.inject.ScopeAnnotation;

/**
* Apply this to implementation classes when you want one instance per quartz job.
*
* @author Bruno Medeiros
*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@ScopeAnnotation
public @interface QuartzJobScoped
{
//nothing
}
2 changes: 2 additions & 0 deletions src/main/java/org/nnsoft/guice/guartz/QuartzModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ protected final void configure()

try
{
bindScope(QuartzJobScoped.class, QuartzScopes.QUARTZ_JOB);
bind(QuartzJobScope.class).toInstance(QuartzScopes.QUARTZ_JOB);
schedule();
bind( JobFactory.class ).to( InjectorJobFactory.class ).in( SINGLETON );
bind( Scheduler.class ).toProvider( SchedulerProvider.class ).asEagerSingleton();
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/org/nnsoft/guice/guartz/QuartzScopes.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.nnsoft.guice.guartz;


public class QuartzScopes {

/**
* Quartz Job scope.
*/
public static final QuartzJobScope QUARTZ_JOB = new QuartzJobScope();

}