|  | 
| 28 | 28 | 
 | 
| 29 | 29 | import org.springframework.core.annotation.AnnotationConfigurationException; | 
| 30 | 30 | import org.springframework.security.access.prepost.PreAuthorize; | 
|  | 31 | +import org.springframework.util.ClassUtils; | 
| 31 | 32 | 
 | 
| 32 | 33 | import static org.assertj.core.api.Assertions.assertThat; | 
| 33 | 34 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType; | 
| @@ -326,6 +327,14 @@ void scanParameterAnnotationWhenPresentInParentAndInterfaceThenException() throw | 
| 326 | 327 | 			.isThrownBy(() -> this.parameterScanner.scan(parameter)); | 
| 327 | 328 | 	} | 
| 328 | 329 | 
 | 
|  | 330 | +	// gh-17898 | 
|  | 331 | +	@Test | 
|  | 332 | +	void scanWhenAnnotationOnParameterizedUndeclaredMethodAndThenLocates() throws Exception { | 
|  | 333 | +		Method method = ClassUtils.getMethod(GenericInterfaceImpl.class, "processOneAndTwo", Long.class, Object.class); | 
|  | 334 | +		PreAuthorize pre = this.scanner.scan(method, method.getDeclaringClass()); | 
|  | 335 | +		assertThat(pre).isNotNull(); | 
|  | 336 | +	} | 
|  | 337 | + | 
| 329 | 338 | 	interface UserService { | 
| 330 | 339 | 
 | 
| 331 | 340 | 		void add(@CustomParameterAnnotation("one") String user); | 
| @@ -764,4 +773,27 @@ <S extends Number> S getExtByClass(Class<S> clazz, Long l) { | 
| 764 | 773 | 
 | 
| 765 | 774 | 	} | 
| 766 | 775 | 
 | 
|  | 776 | +	interface GenericInterface<A, B> { | 
|  | 777 | + | 
|  | 778 | +		@PreAuthorize("hasAuthority('thirtythree')") | 
|  | 779 | +		void processOneAndTwo(A value1, B value2); | 
|  | 780 | + | 
|  | 781 | +	} | 
|  | 782 | + | 
|  | 783 | +	abstract static class GenericAbstractSuperclass<C> implements GenericInterface<Long, C> { | 
|  | 784 | + | 
|  | 785 | +		@Override | 
|  | 786 | +		public void processOneAndTwo(Long value1, C value2) { | 
|  | 787 | +		} | 
|  | 788 | + | 
|  | 789 | +	} | 
|  | 790 | + | 
|  | 791 | +	static class GenericInterfaceImpl extends GenericAbstractSuperclass<String> { | 
|  | 792 | + | 
|  | 793 | +		// The compiler does not require us to declare a concrete | 
|  | 794 | +		// processOneAndTwo(Long, String) method, and we intentionally | 
|  | 795 | +		// do not declare one here. | 
|  | 796 | + | 
|  | 797 | +	} | 
|  | 798 | + | 
| 767 | 799 | } | 
0 commit comments