|
26 | 26 |
|
27 | 27 | package org.springdoc.core.service;
|
28 | 28 |
|
| 29 | +import java.lang.annotation.Annotation; |
| 30 | +import java.lang.reflect.AnnotatedElement; |
29 | 31 | import java.lang.reflect.Method;
|
30 | 32 | import java.util.ArrayList;
|
31 | 33 | import java.util.Arrays;
|
|
51 | 53 | import io.swagger.v3.core.util.AnnotationsUtils;
|
52 | 54 | import io.swagger.v3.oas.annotations.Hidden;
|
53 | 55 | import io.swagger.v3.oas.annotations.OpenAPIDefinition;
|
| 56 | +import io.swagger.v3.oas.annotations.Webhook; |
54 | 57 | import io.swagger.v3.oas.annotations.Webhooks;
|
55 | 58 | import io.swagger.v3.oas.annotations.security.SecuritySchemes;
|
56 | 59 | import io.swagger.v3.oas.annotations.tags.Tag;
|
@@ -534,64 +537,96 @@ private Optional<OpenAPIDefinition> getOpenAPIDefinition() {
|
534 | 537 | return Optional.ofNullable(apiDef);
|
535 | 538 | }
|
536 | 539 |
|
| 540 | + |
537 | 541 | /**
|
538 | 542 | * Get webhooks webhooks [ ].
|
539 | 543 | *
|
540 | 544 | * @return the webhooks [ ]
|
541 | 545 | */
|
542 | 546 | public Webhooks[] getWebhooks() {
|
543 |
| - // List to collect all Webhooks annotations |
544 | 547 | List<Webhooks> allWebhooks = new ArrayList<>();
|
545 | 548 |
|
546 |
| - // Get beans with @Webhooks annotation managed by Spring |
547 |
| - Map<String, Object> beansWithWebhooksAnnotation = context.getBeansWithAnnotation(Webhooks.class); |
| 549 | + // First: scan Spring-managed beans |
| 550 | + Map<String, Object> beans = context.getBeansWithAnnotation(Webhooks.class); |
548 | 551 |
|
549 |
| - // Process Spring-managed beans |
550 |
| - if (!beansWithWebhooksAnnotation.isEmpty()) { |
551 |
| - beansWithWebhooksAnnotation.values().forEach(controller -> { |
552 |
| - // Get the @Webhooks annotation(s) from each bean |
553 |
| - Webhooks[] webhooksAnnotations = controller.getClass().getAnnotationsByType(Webhooks.class); |
554 |
| - allWebhooks.addAll(Arrays.asList(webhooksAnnotations)); |
555 |
| - }); |
| 552 | + for (Object bean : beans.values()) { |
| 553 | + Class<?> beanClass = bean.getClass(); |
| 554 | + |
| 555 | + // Collect @Webhooks or @Webhook on class level |
| 556 | + collectWebhooksFromElement(beanClass, allWebhooks); |
| 557 | + |
| 558 | + // Collect from methods |
| 559 | + for (Method method : beanClass.getDeclaredMethods()) { |
| 560 | + collectWebhooksFromElement(method, allWebhooks); |
| 561 | + } |
556 | 562 | }
|
557 | 563 |
|
558 |
| - // If no beans with @Webhooks annotation found, perform classpath scanning |
| 564 | + // Fallback: classpath scanning if nothing found |
559 | 565 | if (allWebhooks.isEmpty()) {
|
560 |
| - ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false); |
| 566 | + ClassPathScanningCandidateComponentProvider scanner = |
| 567 | + new ClassPathScanningCandidateComponentProvider(false); |
561 | 568 | scanner.addIncludeFilter(new AnnotationTypeFilter(Webhooks.class));
|
| 569 | + scanner.addIncludeFilter(new AnnotationTypeFilter(Webhook.class)); |
562 | 570 |
|
563 |
| - // Scan base packages if available |
564 | 571 | if (AutoConfigurationPackages.has(context)) {
|
565 |
| - List<String> packagesToScan = AutoConfigurationPackages.get(context); |
| 572 | + for (String basePackage : AutoConfigurationPackages.get(context)) { |
| 573 | + Set<BeanDefinition> candidates = scanner.findCandidateComponents(basePackage); |
566 | 574 |
|
567 |
| - for (String basePackage : packagesToScan) { |
568 |
| - // Perform the scan and get candidate components |
569 |
| - Set<BeanDefinition> components = scanner.findCandidateComponents(basePackage); |
570 |
| - |
571 |
| - // Loop through the components |
572 |
| - for (BeanDefinition beanDefinition : components) { |
| 575 | + for (BeanDefinition bd : candidates) { |
573 | 576 | try {
|
574 |
| - // Get the class name and load the class |
575 |
| - String className = beanDefinition.getBeanClassName(); |
576 |
| - Class<?> clazz = Class.forName(className); |
| 577 | + Class<?> clazz = Class.forName(bd.getBeanClassName()); |
| 578 | + |
| 579 | + // Class-level annotations |
| 580 | + collectWebhooksFromElement(clazz, allWebhooks); |
577 | 581 |
|
578 |
| - // Get @Webhooks annotation from the class |
579 |
| - Webhooks[] webhooksAnnotations = clazz.getAnnotationsByType(Webhooks.class); |
580 |
| - allWebhooks.addAll(Arrays.asList(webhooksAnnotations)); |
| 582 | + // Method-level annotations |
| 583 | + for (Method method : clazz.getDeclaredMethods()) { |
| 584 | + collectWebhooksFromElement(method, allWebhooks); |
| 585 | + } |
581 | 586 |
|
582 | 587 | } catch (ClassNotFoundException e) {
|
583 |
| - // Log the error if the class is not found |
584 | 588 | LOGGER.error("Class not found in classpath: {}", e.getMessage());
|
585 | 589 | }
|
586 | 590 | }
|
587 | 591 | }
|
588 | 592 | }
|
589 | 593 | }
|
590 | 594 |
|
591 |
| - // Convert the list of Webhooks annotations to an array and return |
592 | 595 | return allWebhooks.toArray(new Webhooks[0]);
|
593 | 596 | }
|
594 | 597 |
|
| 598 | + /** |
| 599 | + * Collect webhooks from element. |
| 600 | + * |
| 601 | + * @param element the element |
| 602 | + * @param collector the collector |
| 603 | + */ |
| 604 | + private void collectWebhooksFromElement(AnnotatedElement element, List<Webhooks> collector) { |
| 605 | + // If @Webhooks is present (container) |
| 606 | + Webhooks container = element.getAnnotation(Webhooks.class); |
| 607 | + if (container != null) { |
| 608 | + collector.add(container); |
| 609 | + } |
| 610 | + |
| 611 | + // If individual @Webhook annotations are present |
| 612 | + Webhook[] individualWebhooks = element.getAnnotationsByType(Webhook.class); |
| 613 | + if (individualWebhooks.length > 0) { |
| 614 | + collector.add(new Webhooks() { |
| 615 | + @Override |
| 616 | + public Webhook[] value() { |
| 617 | + return individualWebhooks; |
| 618 | + } |
| 619 | + |
| 620 | + @Override |
| 621 | + public Class<? extends Annotation> annotationType() { |
| 622 | + return Webhooks.class; |
| 623 | + } |
| 624 | + }); |
| 625 | + } |
| 626 | + } |
| 627 | + |
| 628 | + |
| 629 | + |
595 | 630 | /**
|
596 | 631 | * Build open api with open api definition.
|
597 | 632 | *
|
|
0 commit comments