diff --git a/src/main/java/io/openapitools/swagger/GenerateMojo.java b/src/main/java/io/openapitools/swagger/GenerateMojo.java index fab7629..5cc5643 100644 --- a/src/main/java/io/openapitools/swagger/GenerateMojo.java +++ b/src/main/java/io/openapitools/swagger/GenerateMojo.java @@ -110,40 +110,29 @@ public void execute() throws MojoExecutionException, MojoFailureException { return; } - ClassLoader origClzLoader = Thread.currentThread().getContextClassLoader(); - ClassLoader clzLoader = createClassLoader(origClzLoader); + Reader reader = new Reader(swaggerConfig == null ? new OpenAPI() : swaggerConfig.createSwaggerModel()); - try { - // set the TCCL before everything else - Thread.currentThread().setContextClassLoader(clzLoader); - - Reader reader = new Reader(swaggerConfig == null ? new OpenAPI() : swaggerConfig.createSwaggerModel()); + JaxRSScanner reflectiveScanner = new JaxRSScanner(getLog(), createClassLoader(), resourcePackages, useResourcePackagesChildren); - JaxRSScanner reflectiveScanner = new JaxRSScanner(getLog(), resourcePackages, useResourcePackagesChildren); + Application application = resolveApplication(reflectiveScanner); + reader.setApplication(application); - Application application = resolveApplication(reflectiveScanner); - reader.setApplication(application); + OpenAPI swagger = OpenAPISorter.sort(reader.read(reflectiveScanner.classes())); - OpenAPI swagger = OpenAPISorter.sort(reader.read(reflectiveScanner.classes())); - - if (outputDirectory.mkdirs()) { - getLog().debug("Created output directory " + outputDirectory); - } + if (outputDirectory.mkdirs()) { + getLog().debug("Created output directory " + outputDirectory); + } - outputFormats.forEach(format -> { - try { - File outputFile = new File(outputDirectory, outputFilename + "." + format.name().toLowerCase()); - format.write(swagger, outputFile, prettyPrint); - if (attachSwaggerArtifact) { - projectHelper.attachArtifact(project, format.name().toLowerCase(), "swagger", outputFile); - } - } catch (IOException e) { - throw new RuntimeException("Unable write " + outputFilename + " document", e); + try { + for (OutputFormat format : outputFormats) { + File outputFile = new File(outputDirectory, outputFilename + "." + format.name().toLowerCase()); + format.write(swagger, outputFile, prettyPrint); + if (attachSwaggerArtifact) { + projectHelper.attachArtifact(project, format.name().toLowerCase(), "swagger", outputFile); } - }); - } finally { - // reset the TCCL back to the original class loader - Thread.currentThread().setContextClassLoader(origClzLoader); + } + } catch (IOException e) { + throw new RuntimeException("Unable write " + outputFilename + " document", e); } } @@ -164,7 +153,7 @@ private Application resolveApplication(JaxRSScanner reflectiveScanner) { return ClassUtils.createInstance(appClazz); } - private URLClassLoader createClassLoader(ClassLoader parent) { + private URLClassLoader createClassLoader() { try { Collection dependencies = getDependentClasspathElements(); URL[] urls = new URL[dependencies.size()]; @@ -172,7 +161,7 @@ private URLClassLoader createClassLoader(ClassLoader parent) { for (String dependency : dependencies) { urls[index++] = Paths.get(dependency).toUri().toURL(); } - return new URLClassLoader(urls, parent); + return new URLClassLoader(urls, Thread.currentThread().getContextClassLoader()); } catch (MalformedURLException e) { throw new RuntimeException("Unable to create class loader with compiled classes", e); } catch (DependencyResolutionRequiredException e) { diff --git a/src/main/java/io/openapitools/swagger/JaxRSScanner.java b/src/main/java/io/openapitools/swagger/JaxRSScanner.java index 5e46262..9f5982c 100644 --- a/src/main/java/io/openapitools/swagger/JaxRSScanner.java +++ b/src/main/java/io/openapitools/swagger/JaxRSScanner.java @@ -2,7 +2,6 @@ import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -26,42 +25,48 @@ class JaxRSScanner { private final Log log; + private final ClassGraph classGraph; + private final Set resourcePackages; private final boolean useResourcePackagesChildren; - public JaxRSScanner(Log log, Set resourcePackages, Boolean useResourcePackagesChildren) { + public JaxRSScanner(Log log, ClassLoader clzLoader, Set resourcePackages, Boolean useResourcePackagesChildren) { this.log = log; + this.classGraph = new ClassGraph().enableClassInfo().enableAnnotationInfo() + .addClassLoader(clzLoader); this.resourcePackages = resourcePackages == null ? Collections.emptySet() : new HashSet<>(resourcePackages); this.useResourcePackagesChildren = Boolean.TRUE.equals(useResourcePackagesChildren); } Application applicationInstance() { - ClassGraph classGraph = new ClassGraph().enableClassInfo(); + Application applicationInstance = null; try (ScanResult scanResult = classGraph.scan()) { - List applicationClasses = scanResult.getSubclasses(Application.class.getName()).stream() - .filter(this::filterClassByResourcePackages) - .collect(Collectors.toList()); + ClassInfoList applicationClasses = scanResult.getSubclasses(Application.class.getName()) + .filter(this::filterClassByResourcePackages); if (applicationClasses.size() == 1) { - return ClassUtils.createInstance(applicationClasses.get(0).loadClass(Application.class)); - } - if (applicationClasses.size() > 1) { + applicationInstance = ClassUtils.createInstance(applicationClasses.get(0).loadClass(Application.class)); + } else if (applicationClasses.size() > 1) { log.warn("More than one javax.ws.rs.core.Application classes found on the classpath, skipping"); } } - return null; + return applicationInstance; } Set> classes() { - ClassGraph classGraph = new ClassGraph().enableClassInfo().enableAnnotationInfo(); + Set> classes; try (ScanResult scanResult = classGraph.scan()) { ClassInfoList apiClasses = scanResult.getClassesWithAnnotation(Path.class.getName()); ClassInfoList defClasses = scanResult.getClassesWithAnnotation(OpenAPIDefinition.class.getName()); - return Stream.concat(apiClasses.stream(), defClasses.stream()) - .filter(this::filterClassByResourcePackages) + classes = Stream.of(apiClasses, defClasses) + .flatMap(classList -> classList.filter(this::filterClassByResourcePackages).stream()) .map(ClassInfo::loadClass) .collect(Collectors.toSet()); } + if (classes.isEmpty()) { + log.warn("No @Path or @OpenAPIDefinition annotated classes found in given resource packages: " + resourcePackages); + } + return classes; } private boolean filterClassByResourcePackages(ClassInfo cls) {