0
# Resource Processing
1
2
Resource transformation and resolution for Swagger UI assets, including dynamic configuration injection and web jar handling. This system ensures that Swagger UI resources are properly located, resolved, and configured at runtime.
3
4
## Capabilities
5
6
### SwaggerIndexPageTransformer
7
8
Resource transformer that dynamically injects configuration into Swagger UI initializer JavaScript.
9
10
```java { .api }
11
/**
12
* Resource transformer for Swagger UI index page and initializer JavaScript
13
* Dynamically injects runtime configuration into Swagger UI assets
14
*/
15
public class SwaggerIndexPageTransformer extends AbstractSwaggerIndexTransformer
16
implements SwaggerIndexTransformer {
17
18
/**
19
* Constructor for index page transformer
20
* @param swaggerUiConfig Swagger UI configuration properties
21
* @param swaggerUiOAuthProperties OAuth configuration properties
22
* @param swaggerWelcomeCommon Common welcome functionality for URL building
23
* @param objectMapperProvider JSON object mapper for configuration serialization
24
*/
25
public SwaggerIndexPageTransformer(SwaggerUiConfigProperties swaggerUiConfig,
26
SwaggerUiOAuthProperties swaggerUiOAuthProperties, SwaggerWelcomeCommon swaggerWelcomeCommon,
27
ObjectMapperProvider objectMapperProvider);
28
29
/**
30
* Transforms resources to inject dynamic configuration
31
* Identifies Swagger UI initializer JavaScript and injects runtime configuration
32
* @param request HTTP request for context-specific configuration
33
* @param resource Original resource to transform
34
* @param transformerChain Resource transformer chain for further processing
35
* @return Transformed resource with injected configuration or original resource
36
* @throws IOException if resource transformation fails
37
*/
38
@Override
39
public Resource transform(HttpServletRequest request, Resource resource,
40
ResourceTransformerChain transformerChain) throws IOException;
41
}
42
```
43
44
### SwaggerIndexTransformer
45
46
Interface marker for Swagger UI resource transformation.
47
48
```java { .api }
49
/**
50
* Interface for Swagger UI resource transformation
51
* Extends Spring's ResourceTransformer for integration with resource handling
52
*/
53
public interface SwaggerIndexTransformer extends ResourceTransformer {
54
// Marker interface - inherits all methods from ResourceTransformer
55
}
56
```
57
58
### SwaggerResourceResolver
59
60
Resource resolver that handles Swagger UI web jar asset resolution with version management.
61
62
```java { .api }
63
/**
64
* Resource resolver for Swagger UI web jar assets
65
* Extends Spring's LiteWebJarsResourceResolver with Swagger-specific functionality
66
*/
67
public class SwaggerResourceResolver extends LiteWebJarsResourceResolver {
68
69
/**
70
* Constructor for Swagger resource resolver
71
* @param swaggerUiConfigProperties Configuration properties containing version information
72
*/
73
public SwaggerResourceResolver(SwaggerUiConfigProperties swaggerUiConfigProperties);
74
75
/**
76
* Finds web jar resource paths for Swagger UI assets
77
* First attempts standard web jar resolution, then falls back to Swagger-specific resolution
78
* @param pathStr Resource path to resolve
79
* @return Resolved resource path or null if not found
80
*/
81
@Nullable
82
@Override
83
protected String findWebJarResourcePath(String pathStr);
84
}
85
```
86
87
## Resource Transformation Process
88
89
### Transformation Detection
90
91
The transformer identifies Swagger UI initializer JavaScript using pattern matching:
92
93
```java { .api }
94
/**
95
* Resource pattern matching for transformation
96
*/
97
interface TransformationDetection {
98
/**
99
* Pattern used to identify Swagger UI initializer JavaScript
100
*/
101
String SWAGGER_INITIALIZER_PATTERN = "**/swagger-ui/**/swagger-initializer.js";
102
103
/**
104
* AntPathMatcher used for pattern matching against resource URLs
105
*/
106
AntPathMatcher ANT_PATH_MATCHER = new AntPathMatcher();
107
108
/**
109
* Checks if resource matches transformation pattern
110
* @param resourceUrl URL of the resource to check
111
* @return true if resource should be transformed
112
*/
113
boolean shouldTransform(String resourceUrl);
114
}
115
```
116
117
### Configuration Injection Process
118
119
When a matching resource is found, the transformer:
120
121
1. **Builds Configuration**: Creates `SwaggerUiConfigParameters` from request context
122
2. **Updates URLs**: Calls `SwaggerWelcomeCommon.buildFromCurrentContextPath()`
123
3. **Applies Transformations**: Injects configuration into JavaScript content
124
4. **Returns Resource**: Wraps transformed content in `TransformedResource`
125
126
```java { .api }
127
/**
128
* Configuration injection steps
129
*/
130
interface ConfigurationInjection {
131
/**
132
* Create configuration parameters from current request
133
*/
134
SwaggerUiConfigParameters createConfigParameters(HttpServletRequest request);
135
136
/**
137
* Build context-specific URLs and paths
138
*/
139
void buildContextPaths(SwaggerUiConfigParameters parameters, HttpServletRequest request);
140
141
/**
142
* Apply default transformations to resource content
143
*/
144
String applyTransformations(SwaggerUiConfigParameters parameters, InputStream resourceStream);
145
146
/**
147
* Wrap transformed content in Spring Resource
148
*/
149
TransformedResource wrapTransformedContent(Resource originalResource, byte[] transformedContent);
150
}
151
```
152
153
## Resource Resolution Process
154
155
### Web Jar Resolution
156
157
The resolver follows a two-tier resolution strategy:
158
159
```java { .api }
160
/**
161
* Web jar resolution strategy
162
*/
163
interface WebJarResolution {
164
/**
165
* Primary resolution using Spring's LiteWebJarsResourceResolver
166
* Handles standard web jar path resolution and version matching
167
*/
168
String primaryResolution(String pathStr);
169
170
/**
171
* Fallback resolution using Swagger-specific utilities
172
* Uses SwaggerResourceResolverUtils.findSwaggerResourcePath()
173
*/
174
String fallbackResolution(String pathStr, String swaggerUiVersion);
175
176
/**
177
* Combined resolution logic
178
*/
179
@Nullable
180
default String resolveResourcePath(String pathStr, String version) {
181
String primaryResult = primaryResolution(pathStr);
182
return primaryResult != null ? primaryResult : fallbackResolution(pathStr, version);
183
}
184
}
185
```
186
187
### Version Management
188
189
Resource resolution uses version information from configuration:
190
191
```java { .api }
192
/**
193
* Version-aware resource resolution
194
*/
195
interface VersionManagement {
196
/**
197
* Gets Swagger UI version from configuration properties
198
*/
199
String getSwaggerUiVersion(SwaggerUiConfigProperties properties);
200
201
/**
202
* Resolves versioned web jar paths
203
*/
204
String resolveVersionedPath(String basePath, String version);
205
206
/**
207
* Handles version conflicts and fallbacks
208
*/
209
String handleVersionConflict(String requestedVersion, String availableVersion);
210
}
211
```
212
213
## Usage Examples
214
215
### Basic Resource Processing
216
217
Resource processing happens automatically during resource serving:
218
219
```java
220
// When browser requests: /swagger-ui/swagger-initializer.js
221
// 1. SwaggerResourceResolver locates the web jar asset
222
// 2. SwaggerIndexPageTransformer injects runtime configuration
223
// 3. Transformed resource served to browser with current API URLs
224
```
225
226
### Custom Transformation
227
228
Extend transformation for custom requirements:
229
230
```java
231
@Component
232
public class CustomSwaggerTransformer implements SwaggerIndexTransformer {
233
234
@Override
235
public Resource transform(HttpServletRequest request, Resource resource,
236
ResourceTransformerChain transformerChain) throws IOException {
237
238
if (isCustomResource(resource)) {
239
String customContent = addCustomConfiguration(resource);
240
return new TransformedResource(resource, customContent.getBytes(StandardCharsets.UTF_8));
241
}
242
243
return resource;
244
}
245
246
private boolean isCustomResource(Resource resource) {
247
try {
248
return resource.getURL().toString().contains("custom-swagger");
249
} catch (IOException e) {
250
return false;
251
}
252
}
253
254
private String addCustomConfiguration(Resource resource) throws IOException {
255
String originalContent = StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8);
256
return originalContent.replace("// CUSTOM_CONFIG_PLACEHOLDER",
257
"window.customSwaggerConfig = { theme: 'dark', layout: 'sidebar' };");
258
}
259
}
260
```
261
262
### Custom Resource Resolution
263
264
Override resource resolution for specific requirements:
265
266
```java
267
@Component
268
@Primary
269
public class CustomSwaggerResourceResolver extends SwaggerResourceResolver {
270
271
public CustomSwaggerResourceResolver(SwaggerUiConfigProperties properties) {
272
super(properties);
273
}
274
275
@Override
276
protected String findWebJarResourcePath(String pathStr) {
277
// Try custom resolution first
278
String customPath = findCustomSwaggerResource(pathStr);
279
if (customPath != null) {
280
return customPath;
281
}
282
283
// Fall back to standard resolution
284
return super.findWebJarResourcePath(pathStr);
285
}
286
287
private String findCustomSwaggerResource(String pathStr) {
288
if (pathStr.contains("swagger-ui-custom")) {
289
return "META-INF/resources/custom-swagger/" + pathStr;
290
}
291
return null;
292
}
293
}
294
```
295
296
### Configuration-Specific Transformations
297
298
Apply different transformations based on configuration:
299
300
```java
301
@Configuration
302
public class ConditionalTransformationConfig {
303
304
@Bean
305
@ConditionalOnProperty("app.swagger.custom-branding")
306
public SwaggerIndexTransformer brandedTransformer() {
307
return new BrandedSwaggerTransformer();
308
}
309
310
@Bean
311
@ConditionalOnProperty("app.swagger.development-mode")
312
public SwaggerIndexTransformer developmentTransformer() {
313
return new DevelopmentSwaggerTransformer();
314
}
315
}
316
317
class BrandedSwaggerTransformer implements SwaggerIndexTransformer {
318
@Override
319
public Resource transform(HttpServletRequest request, Resource resource,
320
ResourceTransformerChain transformerChain) throws IOException {
321
322
if (isSwaggerInitializer(resource)) {
323
String content = injectBrandingConfiguration(resource);
324
return new TransformedResource(resource, content.getBytes(StandardCharsets.UTF_8));
325
}
326
327
return resource;
328
}
329
330
private String injectBrandingConfiguration(Resource resource) throws IOException {
331
String content = StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8);
332
return content.replace(
333
"// Configuration placeholder",
334
"window.ui = SwaggerUIBundle({ " +
335
"customCss: '.swagger-ui .topbar { background-color: #1976d2; }', " +
336
"customSiteTitle: 'Custom API Documentation' })"
337
);
338
}
339
}
340
```
341
342
## Performance Optimization
343
344
### Caching Strategy
345
346
Resource processing can be optimized through strategic caching:
347
348
```java { .api }
349
/**
350
* Caching considerations for resource processing
351
*/
352
interface CachingStrategy {
353
/**
354
* Static assets (CSS, images) can be cached longer
355
*/
356
void cacheStaticAssets(int cacheSeconds);
357
358
/**
359
* Dynamic content (initializer JS) should not be cached
360
*/
361
void disableCacheForDynamicContent();
362
363
/**
364
* Version-based cache invalidation
365
*/
366
void versionBasedCacheInvalidation(String version);
367
368
/**
369
* Production vs development caching strategies
370
*/
371
void environmentSpecificCaching(String environment);
372
}
373
```
374
375
### Resource Processing Pipeline
376
377
```java
378
// Optimized processing pipeline:
379
// 1. Quick pattern check (avoid expensive operations for non-matching resources)
380
// 2. Lazy configuration building (only when transformation needed)
381
// 3. Efficient string replacement (avoid full parsing when possible)
382
// 4. Resource wrapping optimization (minimal object creation)
383
```
384
385
### Memory Management
386
387
```java { .api }
388
/**
389
* Memory optimization for resource processing
390
*/
391
interface MemoryOptimization {
392
/**
393
* Stream-based processing to avoid loading large resources into memory
394
*/
395
void streamBasedProcessing();
396
397
/**
398
* Resource pooling for frequently accessed assets
399
*/
400
void resourcePooling();
401
402
/**
403
* Lazy initialization of expensive components
404
*/
405
void lazyInitialization();
406
407
/**
408
* Proper resource cleanup after transformation
409
*/
410
void resourceCleanup();
411
}
412
```
413
414
## Error Handling
415
416
Resource processing includes robust error handling:
417
418
```java { .api }
419
/**
420
* Error handling strategies for resource processing
421
*/
422
interface ErrorHandling {
423
/**
424
* Handle missing web jar resources
425
*/
426
void handleMissingResource(String resourcePath);
427
428
/**
429
* Handle transformation failures
430
*/
431
void handleTransformationError(Exception error, Resource resource);
432
433
/**
434
* Handle version conflicts
435
*/
436
void handleVersionConflict(String requestedVersion, String availableVersion);
437
438
/**
439
* Graceful degradation for configuration errors
440
*/
441
void gracefulDegradation(ConfigurationException error);
442
}
443
```
444
445
Common error scenarios and handling:
446
447
```java
448
// 1. Missing Swagger UI web jar → Fall back to CDN or show error page
449
// 2. Transformation failure → Serve original resource without configuration
450
// 3. Configuration building error → Use default configuration
451
// 4. Resource access error → Return 404 with helpful error message
452
```