forked from spring-projects/spring-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathresources.xml
746 lines (602 loc) · 36.9 KB
/
resources.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
<?xml version="1.0" encoding="UTF-8"?>
<chapter xml:id="resources"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>Resources</title>
<section xml:id="resources-introduction">
<title>Introduction</title>
<para>Java's standard <classname>java.net.URL</classname> class and
standard handlers for various URL prefixes unfortunately are not quite
adequate enough for all access to low-level resources. For example,
there is no standardized <classname>URL</classname> implementation
that may be used to access a resource that needs to be obtained from
the classpath, or relative to a
<interfacename>ServletContext</interfacename>. While it is possible
to register new handlers for specialized <classname>URL</classname>
prefixes (similar to existing handlers for prefixes such as
<literal>http:</literal>), this is generally quite complicated, and the
<classname>URL</classname> interface still lacks some desirable
functionality, such as a method to check for the existence of the
resource being pointed to.</para>
</section>
<section xml:id="resources-resource">
<title>The <interfacename>Resource</interfacename> interface</title>
<para>Spring's <interfacename>Resource</interfacename> interface is meant
to be a more capable interface for abstracting access to low-level
resources.</para>
<programlisting language="java"><![CDATA[public interface Resource extends InputStreamSource {
boolean exists();
boolean isOpen();
URL getURL() throws IOException;
File getFile() throws IOException;
Resource createRelative(String relativePath) throws IOException;
String getFilename();
String getDescription();
}]]></programlisting>
<programlisting language="java"><![CDATA[public interface InputStreamSource {
InputStream getInputStream() throws IOException;
}]]></programlisting>
<para>Some of the most important methods from the
<interfacename>Resource</interfacename> interface are:</para>
<itemizedlist>
<listitem>
<para><methodname>getInputStream()</methodname>: locates and opens the
resource, returning an <classname>InputStream</classname> for reading
from the resource. It is expected that each invocation returns a
fresh <classname>InputStream</classname>. It is the responsibility of
the caller to close the stream.</para>
</listitem>
<listitem>
<para><methodname>exists()</methodname>: returns a
<literal>boolean</literal> indicating whether this resource actually
exists in physical form.</para>
</listitem>
<listitem>
<para><methodname>isOpen()</methodname>: returns a
<literal>boolean</literal> indicating whether this resource represents
a handle with an open stream. If <literal>true</literal>, the
<classname>InputStream</classname> cannot be read multiple times, and
must be read once only and then closed to avoid resource leaks. Will
be <literal>false</literal> for all usual resource implementations,
with the exception of
<classname>InputStreamResource</classname>.</para>
</listitem>
<listitem>
<para><methodname>getDescription()</methodname>: returns a description
for this resource, to be used for error output when working with the
resource. This is often the fully qualified file name or the actual
URL of the resource.</para>
</listitem>
</itemizedlist>
<para>Other methods allow you to obtain an actual
<classname>URL</classname> or <classname>File</classname> object
representing the resource (if the underlying implementation is compatible,
and supports that functionality).</para>
<para>The <interfacename>Resource</interfacename> abstraction is used
extensively in Spring itself, as an argument type in many method
signatures when a resource is needed. Other methods in some Spring APIs
(such as the constructors to various
<interfacename>ApplicationContext</interfacename> implementations), take a
<classname>String</classname> which in unadorned or simple form is used to
create a <interfacename>Resource</interfacename> appropriate to that
context implementation, or via special prefixes on the
<classname>String</classname> path, allow the caller to specify that a
specific <interfacename>Resource</interfacename> implementation must be
created and used.</para>
<para>While the <interfacename>Resource</interfacename> interface is used
a lot with Spring and by Spring, it's actually very useful to use as a
general utility class by itself in your own code, for access to resources,
even when your code doesn't know or care about any other parts of Spring.
While this couples your code to Spring, it really only couples it to this
small set of utility classes, which are serving as a more capable
replacement for <classname>URL</classname>, and can be considered
equivalent to any other library you would use for this purpose.</para>
<para>It is important to note that the
<interfacename>Resource</interfacename> abstraction does not replace
functionality: it wraps it where possible. For example, a
<classname>UrlResource</classname> wraps a URL, and uses the wrapped
<classname>URL</classname> to do its work.</para>
</section>
<section xml:id="resources-implementations">
<title>Built-in <interfacename>Resource</interfacename> implementations</title>
<para>There are a number of <interfacename>Resource</interfacename>
implementations that come supplied straight out of the box in
Spring:</para>
<section xml:id="resources-implementations-urlresource">
<title><classname>UrlResource</classname></title>
<para>The <classname>UrlResource</classname> wraps a
<classname>java.net.URL</classname>, and may be used to access any
object that is normally accessible via a URL, such as files, an HTTP
target, an FTP target, etc. All URLs have a standardized
<classname>String</classname> representation, such that appropriate
standardized prefixes are used to indicate one URL type from another.
This includes <literal>file:</literal> for accessing filesystem paths,
<literal>http:</literal> for accessing resources via the HTTP protocol,
<literal>ftp:</literal> for accessing resources via FTP, etc.</para>
<para>A <classname>UrlResource</classname> is created by Java code
explicitly using the <classname>UrlResource</classname> constructor, but
will often be created implicitly when you call an API method which takes
a <classname>String</classname> argument which is meant to represent a
path. For the latter case, a JavaBeans
<interfacename>PropertyEditor</interfacename> will ultimately decide
which type of <interfacename>Resource</interfacename> to create. If the
path string contains a few well-known (to it, that is) prefixes such as
<literal>classpath:</literal>, it will create an appropriate specialized
<interfacename>Resource</interfacename> for that prefix. However, if it
doesn't recognize the prefix, it will assume the this is just a standard
URL string, and will create a <classname>UrlResource</classname>.</para>
</section>
<section xml:id="resources-implementations-classpathresource">
<title><classname>ClassPathResource</classname></title>
<para>This class represents a resource which should be obtained from the
classpath. This uses either the thread context class loader, a given
class loader, or a given class for loading resources.</para>
<para>This <interfacename>Resource</interfacename> implementation
supports resolution as <classname>java.io.File</classname> if the class
path resource resides in the file system, but not for classpath
resources which reside in a jar and have not been expanded (by the
servlet engine, or whatever the environment is) to the filesystem. To
address this the various <interfacename>Resource</interfacename>
implementations always support resolution as a
<classname>java.net.URL</classname>.</para>
<para>A <classname>ClassPathResource</classname> is created by Java code
explicitly using the <classname>ClassPathResource</classname>
constructor, but will often be created implicitly when you call an API
method which takes a <classname>String</classname> argument which is
meant to represent a path. For the latter case, a JavaBeans
<interfacename>PropertyEditor</interfacename> will recognize the special
prefix <literal>classpath:</literal>on the string path, and create a
<classname>ClassPathResource</classname> in that case.</para>
</section>
<section xml:id="resources-implementations-filesystemresource">
<title><classname>FileSystemResource</classname></title>
<para>This is a <interfacename>Resource</interfacename> implementation
for <classname>java.io.File</classname> handles. It obviously supports
resolution as a <classname>File</classname>, and as a
<classname>URL</classname>.</para>
</section>
<section xml:id="resources-implementations-servletcontextresource">
<title><classname>ServletContextResource</classname></title>
<para>This is a <interfacename>Resource</interfacename> implementation
for <interfacename>ServletContext</interfacename> resources,
interpreting relative paths within the relevant web application's root
directory.</para>
<para>This always supports stream access and URL access, but only allows
<classname>java.io.File</classname> access when the web application
archive is expanded and the resource is physically on the filesystem.
Whether or not it's expanded and on the filesystem like this, or
accessed directly from the JAR or somewhere else like a DB (it's
conceivable) is actually dependent on the Servlet container.</para>
</section>
<section xml:id="resources-implementations-inputstreamresource">
<title><classname>InputStreamResource</classname></title>
<para>A <interfacename>Resource</interfacename> implementation for a
given <interfacename>InputStream</interfacename>. This should only be
used if no specific <interfacename>Resource</interfacename>
implementation is applicable. In particular, prefer
<classname>ByteArrayResource</classname> or any of the file-based
<interfacename>Resource</interfacename> implementations where
possible.</para>
<para>In contrast to other <interfacename>Resource</interfacename>
implementations, this is a descriptor for an
<emphasis>already</emphasis> opened resource - therefore returning
<literal>true</literal> from <methodname>isOpen()</methodname>. Do not
use it if you need to keep the resource descriptor somewhere, or if you
need to read a stream multiple times.</para>
</section>
<section xml:id="resources-implementations-bytearrayresource">
<title><classname>ByteArrayResource</classname></title>
<para>This is a <interfacename>Resource</interfacename> implementation
for a given byte array. It creates a
<classname>ByteArrayInputStream</classname> for the given byte
array.</para>
<para>It's useful for loading content from any given byte array, without
having to resort to a single-use
<classname>InputStreamResource</classname>.</para>
</section>
</section>
<section xml:id="resources-resourceloader">
<title>The <interfacename>ResourceLoader</interfacename></title>
<para>The <interfacename>ResourceLoader</interfacename> interface is meant
to be implemented by objects that can return (i.e. load)
<interfacename>Resource</interfacename> instances.</para>
<programlisting language="java">public interface ResourceLoader {
Resource getResource(String location);
}</programlisting>
<para>All application contexts implement the
<interfacename>ResourceLoader</interfacename> interface, and therefore all
application contexts may be used to obtain
<interfacename>Resource</interfacename> instances.</para>
<para>When you call <methodname>getResource()</methodname> on a specific
application context, and the location path specified doesn't have a
specific prefix, you will get back a
<interfacename>Resource</interfacename> type that is appropriate to that
particular application context. For example, assume the following snippet
of code was executed against a
<classname>ClassPathXmlApplicationContext</classname> instance:</para>
<programlisting language="java">Resource template = ctx.getResource("some/resource/path/myTemplate.txt");</programlisting>
<para>What would be returned would be a
<classname>ClassPathResource</classname>; if the same method was executed
against a <classname>FileSystemXmlApplicationContext</classname> instance,
you'd get back a <classname>FileSystemResource</classname>. For a
<classname>WebApplicationContext</classname>, you'd get back a
<classname>ServletContextResource</classname>, and so on.</para>
<para>As such, you can load resources in a fashion appropriate to the
particular application context.</para>
<para>On the other hand, you may also force
<classname>ClassPathResource</classname> to be used, regardless of the
application context type, by specifying the special
<literal>classpath:</literal> prefix:</para>
<programlisting language="java">Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");</programlisting>
<para>Similarly, one can force a <classname>UrlResource</classname> to be
used by specifying any of the standard <classname>java.net.URL</classname>
prefixes:</para>
<programlisting language="java">Resource template = ctx.getResource("file:/some/resource/path/myTemplate.txt");</programlisting>
<programlisting language="java">Resource template = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt");</programlisting>
<para>The following table summarizes the strategy for converting
<classname>String</classname>s to
<interfacename>Resource</interfacename>s:</para>
<table pgwide="1" xml:id="resources-resource-strings">
<title>Resource strings</title>
<tgroup cols="3">
<colspec align="left" />
<thead>
<row>
<entry align="center">Prefix</entry>
<entry align="center">Example</entry>
<entry align="center">Explanation</entry>
</row>
</thead>
<tbody>
<row>
<entry><para>classpath:</para></entry>
<entry><para> <literal>classpath:com/myapp/config.xml</literal>
</para></entry>
<entry><para>Loaded from the classpath.</para></entry>
</row>
<row>
<entry><para>file:</para></entry>
<entry><para> <literal>file:/data/config.xml</literal>
</para></entry>
<entry><para> Loaded as a <classname>URL</classname>, from the
filesystem. <footnote>
<para>But see also
<xref linkend="resources-filesystemresource-caveats" />.</para>
</footnote> </para></entry>
</row>
<row>
<entry><para>http:</para></entry>
<entry><para> <literal>http://myserver/logo.png</literal>
</para></entry>
<entry><para>Loaded as a
<classname>URL</classname>.</para></entry>
</row>
<row>
<entry><para>(none)</para></entry>
<entry><para> <literal>/data/config.xml</literal> </para></entry>
<entry><para> Depends on the underlying
<interfacename>ApplicationContext</interfacename>. </para></entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section xml:id="resources-resourceloaderaware">
<title>The <interfacename>ResourceLoaderAware</interfacename> interface</title>
<para>The <interfacename>ResourceLoaderAware</interfacename> interface is
a special marker interface, identifying objects that expect to be provided
with a <interfacename>ResourceLoader</interfacename> reference.</para>
<programlisting language="java"><![CDATA[public interface ResourceLoaderAware {
void setResourceLoader(ResourceLoader resourceLoader);
}]]></programlisting>
<para>When a class implements
<interfacename>ResourceLoaderAware</interfacename> and is deployed into an
application context (as a Spring-managed bean), it is recognized as
<interfacename>ResourceLoaderAware</interfacename> by the application
context. The application context will then invoke the
<methodname>setResourceLoader(ResourceLoader)</methodname>, supplying
itself as the argument (remember, all application contexts in Spring
implement the <interfacename>ResourceLoader</interfacename>
interface).</para>
<para>Of course, since an
<interfacename>ApplicationContext</interfacename> is a
<interfacename>ResourceLoader</interfacename>, the bean could also
implement the <interfacename>ApplicationContextAware</interfacename>
interface and use the supplied application context directly to load
resources, but in general, it's better to use the specialized
<interfacename>ResourceLoader</interfacename> interface if that's all
that's needed. The code would just be coupled to the resource loading
interface, which can be considered a utility interface, and not the whole
Spring <interfacename>ApplicationContext</interfacename> interface.</para>
<para>As of Spring 2.5, you can rely upon autowiring of the
<interfacename>ResourceLoader</interfacename> as an alternative to
implementing the <interfacename>ResourceLoaderAware</interfacename> interface.
The "traditional" <literal>constructor</literal> and <literal>byType</literal>
autowiring modes (as described in <xref linkend="beans-factory-autowire"/>)
are now capable of providing a dependency of type
<interfacename>ResourceLoader</interfacename> for either a
constructor argument or setter method parameter respectively. For more flexibility
(including the ability to autowire fields and multiple parameter methods), consider
using the new annotation-based autowiring features. In that case, the
<interfacename>ResourceLoader</interfacename> will be autowired into a field,
constructor argument, or method parameter that is expecting the
<interfacename>ResourceLoader</interfacename> type as long as the field,
constructor, or method in question carries the
<interfacename>@Autowired</interfacename> annotation. For more information,
see <xref linkend="beans-autowired-annotation"/>.</para>
</section>
<section xml:id="resources-as-dependencies">
<title><literal>Resources</literal> as dependencies</title>
<para>If the bean itself is going to determine and supply the resource
path through some sort of dynamic process, it probably makes sense for the
bean to use the <interfacename>ResourceLoader</interfacename> interface to
load resources. Consider as an example the loading of a template of some
sort, where the specific resource that is needed depends on the role of
the user. If the resources are static, it makes sense to eliminate the use
of the <interfacename>ResourceLoader</interfacename> interface completely,
and just have the bean expose the <interfacename>Resource</interfacename>
properties it needs, and expect that they will be injected into it.</para>
<para>What makes it trivial to then inject these properties, is that all
application contexts register and use a special JavaBeans
<interfacename>PropertyEditor</interfacename> which can convert
<classname>String</classname> paths to
<interfacename>Resource</interfacename> objects. So if
<literal>myBean</literal> has a template property of type
<interfacename>Resource</interfacename>, it can be configured with a
simple string for that resource, as follows:</para>
<programlisting language="xml"><![CDATA[<bean id="myBean" class="...">
<property name="template" value="some/resource/path/myTemplate.txt"/>
</bean>]]></programlisting>
<para>Note that the resource path has no prefix, so because the
application context itself is going to be used as the
<interfacename>ResourceLoader</interfacename>, the resource itself will be
loaded via a <classname>ClassPathResource</classname>,
<literal>FileSystemResource</literal>, or
<classname>ServletContextResource</classname> (as appropriate)
depending on the exact type of the context.</para>
<para>If there is a need to force a specific
<interfacename>Resource</interfacename> type to be used, then a prefix may
be used. The following two examples show how to force a
<classname>ClassPathResource</classname> and a
<classname>UrlResource</classname> (the latter being used to access a
filesystem file).</para>
<programlisting language="xml"><![CDATA[<property name="template" value="classpath:some/resource/path/myTemplate.txt">]]></programlisting>
<programlisting language="xml"><![CDATA[<property name="template" value="file:/some/resource/path/myTemplate.txt"/>]]></programlisting>
</section>
<section xml:id="resources-app-ctx">
<title>Application contexts and <interfacename>Resource</interfacename> paths</title>
<section xml:id="resources-app-ctx-construction">
<title>Constructing application contexts</title>
<para>An application context constructor (for a specific application
context type) generally takes a string or array of strings as the
location path(s) of the resource(s) such as XML files that make up the
definition of the context.</para>
<para>When such a location path doesn't have a prefix, the specific
<interfacename>Resource</interfacename> type built from that path and
used to load the bean definitions, depends on and is appropriate to the
specific application context. For example, if you create a
<classname>ClassPathXmlApplicationContext</classname> as follows:</para>
<programlisting language="java"><![CDATA[ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");]]></programlisting>
<para>The bean definitions will be loaded from the classpath, as a
<classname></classname><classname>ClassPathResource</classname> will be
used. But if you create a
<classname>FileSystemXmlApplicationContext</classname> as
follows:</para>
<programlisting language="java"><![CDATA[ApplicationContext ctx =
new FileSystemXmlApplicationContext("conf/appContext.xml");]]></programlisting>
<para>The bean definition will be loaded from a filesystem location, in
this case relative to the current working directory.</para>
<para>Note that the use of the special classpath prefix or a standard
URL prefix on the location path will override the default type of
<interfacename>Resource</interfacename> created to load the definition.
So this <classname>FileSystemXmlApplicationContext</classname>...</para>
<programlisting language="java"><![CDATA[ApplicationContext ctx =
new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");]]></programlisting>
<para>... will actually load its bean definitions from the classpath.
However, it is still a <classname>FileSystemXmlApplicationContext</classname>. If it is
subsequently used as a <interfacename>ResourceLoader</interfacename>,
any unprefixed paths will still be treated as filesystem paths.</para>
<section xml:id="resources-app-ctx-classpathxml">
<title>Constructing <classname>ClassPathXmlApplicationContext</classname> instances - shortcuts</title>
<para>The <classname>ClassPathXmlApplicationContext</classname>
exposes a number of constructors to enable convenient instantiation.
The basic idea is that one supplies merely a string array containing
just the filenames of the XML files themselves (without the leading
path information), and one <emphasis>also</emphasis> supplies a
<classname>Class</classname>; the
<classname>ClassPathXmlApplicationContext</classname> will derive the
path information from the supplied class.</para>
<para>An example will hopefully make this clear. Consider a directory
layout that looks like this:</para>
<programlisting><![CDATA[com/
foo/
services.xml
daos.xml
MessengerService.class]]></programlisting>
<para>A <classname>ClassPathXmlApplicationContext</classname> instance
composed of the beans defined in the <literal>'services.xml'</literal>
and <literal>'daos.xml'</literal> could be instantiated like
so...</para>
<programlisting language="java"><![CDATA[ApplicationContext ctx = new ClassPathXmlApplicationContext(
new String[] {"services.xml", "daos.xml"}, MessengerService.class);]]></programlisting>
<para>Please do consult the Javadocs for the
<classname>ClassPathXmlApplicationContext</classname> class for
details of the various constructors.</para>
</section>
</section>
<section xml:id="resources-app-ctx-wildcards-in-resource-paths">
<title>Wildcards in application context constructor resource paths</title>
<para>The resource paths in application context constructor values may
be a simple path (as shown above) which has a one-to-one mapping to a
target Resource, or alternately may contain the special "classpath*:"
prefix and/or internal Ant-style regular expressions (matched using
Spring's <classname>PathMatcher</classname> utility). Both of the latter
are effectively wildcards</para>
<para>One use for this mechanism is when doing component-style
application assembly. All components can 'publish' context definition
fragments to a well-known location path, and when the final application
context is created using the same path prefixed via
<literal>classpath*:</literal>, all component fragments will be picked
up automatically.</para>
<para>Note that this wildcarding is specific to use of resource paths in
application context constructors (or when using the
<classname>PathMatcher</classname> utility class hierarchy directly),
and is resolved at construction time. It has nothing to do with the
<interfacename>Resource</interfacename> type itself. It's not possible
to use the <literal>classpath*:</literal> prefix to construct an actual
<interfacename>Resource</interfacename>, as a resource points to just
one resource at a time.</para>
<section xml:id="resources-app-ctx-ant-patterns-in-paths">
<title>Ant-style Patterns</title>
<para>When the path location contains an Ant-style pattern, for example:</para>
<programlisting><![CDATA[ /WEB-INF/*-context.xml
com/mycompany/**/applicationContext.xml
file:C:/some/path/*-context.xml
classpath:com/mycompany/**/applicationContext.xml]]></programlisting>
<para>... the resolver follows a more complex but defined procedure to
try to resolve the wildcard. It produces a Resource for the path up to
the last non-wildcard segment and obtains a URL from it. If this URL
is not a "jar:" URL or container-specific variant (e.g.
"<literal>zip:</literal>" in WebLogic, "<literal>wsjar</literal>" in
WebSphere, etc.), then a <classname>java.io.File</classname> is
obtained from it and used to resolve the wildcard by traversing the
filesystem. In the case of a jar URL, the resolver either gets a
<classname>java.net.JarURLConnection</classname> from it or manually
parses the jar URL and then traverses the contents of the jar file
to resolve the wildcards.</para>
<section xml:id="resources-app-ctx-portability">
<title>Implications on portability</title>
<para>If the specified path is already a file URL (either
explicitly, or implicitly because the base
<interfacename>ResourceLoader</interfacename> is a
filesystem one, then wildcarding is guaranteed to work in a
completely portable fashion.</para>
<para>If the specified path is a classpath location, then the
resolver must obtain the last non-wildcard path segment URL via a
<methodname>Classloader.getResource()</methodname> call. Since this
is just a node of the path (not the file at the end) it is actually
undefined (in the <classname>ClassLoader</classname> Javadocs)
exactly what sort of a URL is returned in this case. In practice, it
is always a <classname>java.io.File</classname> representing the
directory, where the classpath resource resolves to a filesystem
location, or a jar URL of some sort, where the classpath resource
resolves to a jar location. Still, there is a portability concern on
this operation.</para>
<para>If a jar URL is obtained for the last non-wildcard segment,
the resolver must be able to get a
<classname>java.net.JarURLConnection</classname> from it, or
manually parse the jar URL, to be able to walk the contents of the
jar, and resolve the wildcard. This will work in most environments,
but will fail in others, and it is strongly recommended that the
wildcard resolution of resources coming from jars be thoroughly
tested in your specific environment before you rely on it.</para>
</section>
</section>
<section xml:id="resources-classpath-wildcards">
<title>The <literal>classpath*:</literal> prefix</title>
<para>When constructing an XML-based application context, a location
string may use the special <literal>classpath*:</literal>
prefix:</para>
<programlisting language="java"><![CDATA[ApplicationContext ctx =
new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");]]></programlisting>
<para>This special prefix specifies that all classpath resources that
match the given name must be obtained (internally, this essentially
happens via a <methodname>ClassLoader.getResources(...)</methodname>
call), and then merged to form the final application context
definition.</para>
<note>
<title>Classpath*: portability</title>
<para>The wildcard classpath relies on the <literal>getResources()</literal> method of the
underlying classloader. As most application servers nowadays supply
their own classloader implementation, the behavior might differ
especially when dealing with jar files. A simple test to check if
<literal>classpath*</literal> works is to use the classloader to load a file from
within a jar on the classpath:
<literal>getClass().getClassLoader().getResources("<someFileInsideTheJar>")</literal>.
Try this test with files that have the same name but are placed
inside two different locations. In case an inappropriate result is
returned, check the application server documentation for settings
that might affect the classloader behavior.</para>
</note>
<para>The "<literal>classpath*:</literal>" prefix can also be combined
with a <literal>PathMatcher</literal> pattern in the rest of the location path, for
example "<literal>classpath*:META-INF/*-beans.xml</literal>". In this
case, the resolution strategy is fairly simple: a
ClassLoader.getResources() call is used on the last non-wildcard path
segment to get all the matching resources in the class loader
hierarchy, and then off each resource the same PathMatcher resolution
strategy described above is used for the wildcard subpath.</para>
</section>
<section xml:id="resources-wildcards-in-path-other-stuff">
<title>Other notes relating to wildcards</title>
<para>Please note that "<literal>classpath*:</literal>" when
combined with Ant-style patterns will only work reliably with at least
one root directory before the pattern starts, unless the actual target
files reside in the file system. This means that a pattern like
"<literal>classpath*:*.xml</literal>" will not retrieve files from the
root of jar files but rather only from the root of expanded
directories. This originates from a limitation in the JDK's
<methodname>ClassLoader.getResources()</methodname> method which only
returns file system locations for a passed-in empty string (indicating
potential roots to search).</para>
<para>Ant-style patterns with "<literal>classpath:</literal>"
resources are not guaranteed to find matching resources if the root
package to search is available in multiple class path locations. This
is because a resource such as</para>
<programlisting><![CDATA[ com/mycompany/package1/service-context.xml]]></programlisting>
<para>may be in only one location, but when a path such as</para>
<programlisting><![CDATA[ classpath:com/mycompany/**/service-context.xml]]></programlisting>
<para>is used to try to resolve it, the resolver will work off the (first) URL
returned by <methodname>getResource("com/mycompany")</methodname>;. If
this base package node exists in multiple classloader locations, the
actual end resource may not be underneath. Therefore, preferably, use
"<literal>classpath*:</literal>" with the same Ant-style pattern in
such a case, which will search all class path locations that contain
the root package.</para>
</section>
</section>
<section xml:id="resources-filesystemresource-caveats">
<title><classname>FileSystemResource</classname> caveats</title>
<para>A <classname>FileSystemResource</classname> that is not attached
to a <classname>FileSystemApplicationContext</classname> (that is, a
<classname>FileSystemApplicationContext</classname> is not the actual
<interfacename>ResourceLoader</interfacename>) will treat absolute vs.
relative paths as you would expect. Relative paths are relative to the
current working directory, while absolute paths are relative to the root
of the filesystem.</para>
<para>For backwards compatibility (historical) reasons however, this
changes when the <classname>FileSystemApplicationContext</classname> is
the <literal>ResourceLoader</literal>. The
<classname>FileSystemApplicationContext</classname> simply forces all
attached <classname>FileSystemResource</classname> instances to treat
all location paths as relative, whether they start with a leading slash
or not. In practice, this means the following are equivalent:</para>
<programlisting language="java"><![CDATA[ApplicationContext ctx =
new FileSystemXmlApplicationContext("conf/context.xml");]]></programlisting>
<programlisting language="java"><![CDATA[ApplicationContext ctx =
new FileSystemXmlApplicationContext("/conf/context.xml");]]></programlisting>
<para>As are the following: (Even though it would make sense for them to
be different, as one case is relative and the other absolute.)</para>
<programlisting language="java"><![CDATA[FileSystemXmlApplicationContext ctx = ...;
ctx.getResource("some/resource/path/myTemplate.txt");]]></programlisting>
<programlisting language="java"><![CDATA[FileSystemXmlApplicationContext ctx = ...;
ctx.getResource("/some/resource/path/myTemplate.txt");]]></programlisting>
<para>In practice, if true absolute filesystem paths are needed, it is
better to forgo the use of absolute paths with
<classname>FileSystemResource</classname> /
<classname>FileSystemXmlApplicationContext</classname>, and just force
the use of a <classname>UrlResource</classname>, by using the
<literal>file:</literal> URL prefix.</para>
<programlisting language="java"><lineannotation>// actual context type doesn't matter, the Resource will always be UrlResource</lineannotation><![CDATA[
ctx.getResource("file:/some/resource/path/myTemplate.txt");]]></programlisting>
<programlisting language="java"><lineannotation>// force this FileSystemXmlApplicationContext to load its definition via a UrlResource</lineannotation><![CDATA[
ApplicationContext ctx =
new FileSystemXmlApplicationContext("file:/conf/context.xml");]]></programlisting>
</section>
</section>
</chapter>