Skip to content

Commit e51670a

Browse files
feat: avoid changing thread classloader
1 parent 74cc79b commit e51670a

File tree

2 files changed

+37
-43
lines changed

2 files changed

+37
-43
lines changed

src/main/java/io/openapitools/swagger/GenerateMojo.java

Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -110,40 +110,29 @@ public void execute() throws MojoExecutionException, MojoFailureException {
110110
return;
111111
}
112112

113-
ClassLoader origClzLoader = Thread.currentThread().getContextClassLoader();
114-
ClassLoader clzLoader = createClassLoader(origClzLoader);
113+
Reader reader = new Reader(swaggerConfig == null ? new OpenAPI() : swaggerConfig.createSwaggerModel());
115114

116-
try {
117-
// set the TCCL before everything else
118-
Thread.currentThread().setContextClassLoader(clzLoader);
119-
120-
Reader reader = new Reader(swaggerConfig == null ? new OpenAPI() : swaggerConfig.createSwaggerModel());
115+
JaxRSScanner reflectiveScanner = new JaxRSScanner(getLog(), createClassLoader(), resourcePackages, useResourcePackagesChildren);
121116

122-
JaxRSScanner reflectiveScanner = new JaxRSScanner(getLog(), resourcePackages, useResourcePackagesChildren);
117+
Application application = resolveApplication(reflectiveScanner);
118+
reader.setApplication(application);
123119

124-
Application application = resolveApplication(reflectiveScanner);
125-
reader.setApplication(application);
120+
OpenAPI swagger = OpenAPISorter.sort(reader.read(reflectiveScanner.classes()));
126121

127-
OpenAPI swagger = OpenAPISorter.sort(reader.read(reflectiveScanner.classes()));
128-
129-
if (outputDirectory.mkdirs()) {
130-
getLog().debug("Created output directory " + outputDirectory);
131-
}
122+
if (outputDirectory.mkdirs()) {
123+
getLog().debug("Created output directory " + outputDirectory);
124+
}
132125

133-
outputFormats.forEach(format -> {
134-
try {
135-
File outputFile = new File(outputDirectory, outputFilename + "." + format.name().toLowerCase());
136-
format.write(swagger, outputFile, prettyPrint);
137-
if (attachSwaggerArtifact) {
138-
projectHelper.attachArtifact(project, format.name().toLowerCase(), "swagger", outputFile);
139-
}
140-
} catch (IOException e) {
141-
throw new RuntimeException("Unable write " + outputFilename + " document", e);
126+
try {
127+
for (OutputFormat format : outputFormats) {
128+
File outputFile = new File(outputDirectory, outputFilename + "." + format.name().toLowerCase());
129+
format.write(swagger, outputFile, prettyPrint);
130+
if (attachSwaggerArtifact) {
131+
projectHelper.attachArtifact(project, format.name().toLowerCase(), "swagger", outputFile);
142132
}
143-
});
144-
} finally {
145-
// reset the TCCL back to the original class loader
146-
Thread.currentThread().setContextClassLoader(origClzLoader);
133+
}
134+
} catch (IOException e) {
135+
throw new RuntimeException("Unable write " + outputFilename + " document", e);
147136
}
148137
}
149138

@@ -164,15 +153,15 @@ private Application resolveApplication(JaxRSScanner reflectiveScanner) {
164153
return ClassUtils.createInstance(appClazz);
165154
}
166155

167-
private URLClassLoader createClassLoader(ClassLoader parent) {
156+
private URLClassLoader createClassLoader() {
168157
try {
169158
Collection<String> dependencies = getDependentClasspathElements();
170159
URL[] urls = new URL[dependencies.size()];
171160
int index = 0;
172161
for (String dependency : dependencies) {
173162
urls[index++] = Paths.get(dependency).toUri().toURL();
174163
}
175-
return new URLClassLoader(urls, parent);
164+
return new URLClassLoader(urls, Thread.currentThread().getContextClassLoader());
176165
} catch (MalformedURLException e) {
177166
throw new RuntimeException("Unable to create class loader with compiled classes", e);
178167
} catch (DependencyResolutionRequiredException e) {

src/main/java/io/openapitools/swagger/JaxRSScanner.java

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import java.util.Collections;
44
import java.util.HashSet;
5-
import java.util.List;
65
import java.util.Set;
76
import java.util.stream.Collectors;
87
import java.util.stream.Stream;
@@ -26,42 +25,48 @@ class JaxRSScanner {
2625

2726
private final Log log;
2827

28+
private final ClassGraph classGraph;
29+
2930
private final Set<String> resourcePackages;
3031

3132
private final boolean useResourcePackagesChildren;
3233

33-
public JaxRSScanner(Log log, Set<String> resourcePackages, Boolean useResourcePackagesChildren) {
34+
public JaxRSScanner(Log log, ClassLoader clzLoader, Set<String> resourcePackages, Boolean useResourcePackagesChildren) {
3435
this.log = log;
36+
this.classGraph = new ClassGraph().enableClassInfo().enableAnnotationInfo()
37+
.addClassLoader(clzLoader);
3538
this.resourcePackages = resourcePackages == null ? Collections.emptySet() : new HashSet<>(resourcePackages);
3639
this.useResourcePackagesChildren = Boolean.TRUE.equals(useResourcePackagesChildren);
3740
}
3841

3942
Application applicationInstance() {
40-
ClassGraph classGraph = new ClassGraph().enableClassInfo();
43+
Application applicationInstance = null;
4144
try (ScanResult scanResult = classGraph.scan()) {
42-
List<ClassInfo> applicationClasses = scanResult.getSubclasses(Application.class.getName()).stream()
43-
.filter(this::filterClassByResourcePackages)
44-
.collect(Collectors.toList());
45+
ClassInfoList applicationClasses = scanResult.getSubclasses(Application.class.getName())
46+
.filter(this::filterClassByResourcePackages);
4547
if (applicationClasses.size() == 1) {
46-
return ClassUtils.createInstance(applicationClasses.get(0).loadClass(Application.class));
47-
}
48-
if (applicationClasses.size() > 1) {
48+
applicationInstance = ClassUtils.createInstance(applicationClasses.get(0).loadClass(Application.class));
49+
} else if (applicationClasses.size() > 1) {
4950
log.warn("More than one javax.ws.rs.core.Application classes found on the classpath, skipping");
5051
}
5152
}
52-
return null;
53+
return applicationInstance;
5354
}
5455

5556
Set<Class<?>> classes() {
56-
ClassGraph classGraph = new ClassGraph().enableClassInfo().enableAnnotationInfo();
57+
Set<Class<?>> classes;
5758
try (ScanResult scanResult = classGraph.scan()) {
5859
ClassInfoList apiClasses = scanResult.getClassesWithAnnotation(Path.class.getName());
5960
ClassInfoList defClasses = scanResult.getClassesWithAnnotation(OpenAPIDefinition.class.getName());
60-
return Stream.concat(apiClasses.stream(), defClasses.stream())
61-
.filter(this::filterClassByResourcePackages)
61+
classes = Stream.of(apiClasses, defClasses)
62+
.flatMap(classList -> classList.filter(this::filterClassByResourcePackages).stream())
6263
.map(ClassInfo::loadClass)
6364
.collect(Collectors.toSet());
6465
}
66+
if (classes.isEmpty()) {
67+
log.warn("No @Path or @OpenAPIDefinition annotated classes found in given resource packages: " + resourcePackages);
68+
}
69+
return classes;
6570
}
6671

6772
private boolean filterClassByResourcePackages(ClassInfo cls) {

0 commit comments

Comments
 (0)