Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#208 Support for meta annotations #209

Merged
merged 1 commit into from Mar 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 "";
}