Skip to content

Commit

Permalink
#208 Support for meta annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
lukas-krecan-lt committed Mar 25, 2020
1 parent 9284ede commit aa99ebd
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 5 deletions.
Expand Up @@ -18,29 +18,38 @@
import net.javacrumbs.shedlock.core.LockConfiguration;
import net.javacrumbs.shedlock.core.LockingTaskExecutor;
import net.javacrumbs.shedlock.core.LockingTaskExecutor.TaskResult;
import net.javacrumbs.shedlock.core.SchedulerLock;
import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.jetbrains.annotations.NotNull;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.AbstractPointcutAdvisor;
import org.springframework.aop.support.ComposablePointcut;
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;

import java.lang.annotation.Annotation;
import java.util.Optional;

import static org.springframework.aop.support.annotation.AnnotationMatchingPointcut.forMethodAnnotation;

class MethodProxyScheduledLockAdvisor extends AbstractPointcutAdvisor {
private final Pointcut pointcut = new ComposablePointcut(forMethodAnnotation(SchedulerLock.class))
.union(forMethodAnnotation(net.javacrumbs.shedlock.spring.annotation.SchedulerLock.class));
private final Pointcut pointcut = new ComposablePointcut(methodPointcutFor(net.javacrumbs.shedlock.core.SchedulerLock.class))
.union(methodPointcutFor(SchedulerLock.class));

private final Advice advice;

MethodProxyScheduledLockAdvisor(SpringLockConfigurationExtractor lockConfigurationExtractor, LockingTaskExecutor lockingTaskExecutor) {
this.advice = new LockingInterceptor(lockConfigurationExtractor, lockingTaskExecutor);
}

@NotNull
private static AnnotationMatchingPointcut methodPointcutFor(Class<? extends Annotation> methodAnnotationType) {
return new AnnotationMatchingPointcut(
null,
methodAnnotationType,
true
);
}

/**
* Get the Pointcut that drives this advisor.
*/
Expand Down
Expand Up @@ -81,6 +81,15 @@ public void shouldCallLockProviderOnSchedulerCallDeprecatedAnnotation() throws N
verify(simpleLock).unlock();
}

@Test
public void shouldUseCustomAnnotation() throws NoSuchMethodException, ExecutionException, InterruptedException {
Runnable task = task("custom");
taskScheduler.schedule(task, now()).get();
verify(lockProvider).lock(hasParams("custom", 60_000, 1_000));
verify(simpleLock).unlock();
}


@Test
public void shouldUserPropertyName() throws NoSuchMethodException, ExecutionException, InterruptedException {
Runnable task = task("spelMethod");
Expand Down Expand Up @@ -134,6 +143,11 @@ public void annotatedMethod() {
assertRightSchedulerUsed();
}

@MyScheduled(name = "custom", lockAtMostFor = "1m", lockAtLeastFor = "1s")
public void custom() {
assertRightSchedulerUsed();
}

@SchedulerLock(name = "${property.value}", lockAtMostFor = "1000", lockAtLeastFor = "500")
public void spelMethod() {

Expand Down
Expand Up @@ -22,16 +22,23 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.annotation.AliasFor;
import org.springframework.scheduling.annotation.EnableScheduling;

import java.io.IOException;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static org.mockito.Mockito.mock;

@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "${default.lock_at_most_for}", defaultLockAtLeastFor = "${default.lock_at_least_for}")
@PropertySource("test.properties")
@SuppressWarnings("deprecation")
public class DeprecatedMethodProxyAopConfig {

@Bean
Expand All @@ -58,6 +65,10 @@ public void noAnnotation() {
public void normal() {
}

@MyDeprecatedScheduled(name = "custom")
public void custom() {
}

@SchedulerLock(name = "runtimeException", lockAtMostFor = 100)
public Void throwsRuntimeException() {
throw new RuntimeException();
Expand All @@ -79,6 +90,15 @@ public void spel() {
}
}

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@SchedulerLock
public @interface MyDeprecatedScheduled {
@AliasFor(annotation = SchedulerLock.class, attribute = "name")
String name();
}

interface AnotherTestBean {
void runManually();
}
Expand Down
Expand Up @@ -73,6 +73,13 @@ public void shouldCallLockProviderOnDirectCall() {
verify(simpleLock).unlock();
}

@Test
public void shouldUseCustomAnnotation() {
testBean.custom();
verify(lockProvider).lock(hasParams("custom", 30_000, 100));
verify(simpleLock).unlock();
}

@Test
public void shouldRethrowRuntimeException() {
assertThatThrownBy(() -> testBean.throwsRuntimeException()).isInstanceOf(RuntimeException.class);
Expand Down
Expand Up @@ -72,6 +72,11 @@ public void normal() {
called.set(true);
}

@MyScheduled(name = "custom", lockAtMostFor = "1m", lockAtLeastFor = "1s")
public void custom() {
called.set(true);
}

@SchedulerLock(name = "runtimeException", lockAtMostFor = "100")
public Void throwsRuntimeException() {
called.set(true);
Expand Down
Expand Up @@ -75,6 +75,14 @@ public void shouldCallLockProviderOnDirectCall() {
assertThat(testBean.wasMethodCalled()).isTrue();
}

@Test
public void shouldUseCustomAnnotation() {
testBean.custom();
verify(lockProvider).lock(hasParams("custom", 60_000, 1_000));
verify(simpleLock).unlock();
assertThat(testBean.wasMethodCalled()).isTrue();
}

@Test
public void shouldRethrowRuntimeException() {
assertThatThrownBy(() -> testBean.throwsRuntimeException()).isInstanceOf(RuntimeException.class);
Expand Down
@@ -0,0 +1,27 @@
package net.javacrumbs.shedlock.spring.aop;

import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import org.springframework.core.annotation.AliasFor;
import org.springframework.scheduling.annotation.Async;

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

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Async
@SchedulerLock
public @interface MyScheduled {
@AliasFor(annotation = SchedulerLock.class, attribute = "name")
String name();

@AliasFor(annotation = SchedulerLock.class, attribute = "lockAtMostFor")
String lockAtMostFor() default "";

@AliasFor(annotation = SchedulerLock.class, attribute = "lockAtLeastFor")
String lockAtLeastFor() default "";
}

0 comments on commit aa99ebd

Please sign in to comment.