Move reference docs => src/reference

This change eliminates the spring-framework-reference subproject, moving
these sources into the root project's own src directory.

This makes sense because the reference docs span all submodules, and
also because api Javadoc is created at the root project level as well.
This means that both api and reference documentation output will now
reside in the root project's 'build' directory. This is more consistent
and easy to discover.
This commit is contained in:
Chris Beams
2012-01-25 13:11:43 +01:00
parent 0a07a0ed92
commit 62e94461f4
120 changed files with 0 additions and 985 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,801 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="beans-annotation-config">
<title>Annotation-based container configuration</title>
<sidebar>
<title>Are annotations better than XML for configuring Spring?</title>
<para>The introduction of annotation-based configurations raised the
question of whether this approach is 'better' than XML. The short answer
is <emphasis>it depends</emphasis>. The long answer is that each approach
has its pros and cons, and usually it is up to the developer to decide
which strategy suits her better. Due to the way they are defined,
annotations provide a lot of context in their declaration, leading to
shorter and more concise configuration. However, XML excels at wiring up
components without touching their source code or recompiling them. Some
developers prefer having the wiring close to the source while others argue
that annotated classes are no longer POJOs and, furthermore, that the
configuration becomes decentralized and harder to control.</para>
<para>No matter the choice, Spring can accommodate both styles and even mix
them together. It's worth pointing out that through its <link
linkend="beans-java">JavaConfig</link> option, Spring allows annotations
to be used in a non-invasive way, without touching the target components
source code and that in terms of tooling, all configuration styles are
supported by the <ulink url="http://www.springsource.com/products/sts"
>SpringSource Tool Suite</ulink>.</para>
</sidebar>
<para>An alternative to XML setups is provided by annotation-based
configuration which rely on the bytecode metadata for wiring up components
instead of angle-bracket declarations. Instead of using XML to describe a
bean wiring, the developer moves the configuration into the component class
itself by using annotations on the relevant class, method, or field
declaration. As mentioned in <xref
linkend="beans-factory-extension-bpp-examples-rabpp"/>, using a
<interfacename>BeanPostProcessor</interfacename> in conjunction with
annotations is a common means of extending the Spring IoC container. For
example, Spring 2.0 introduced the possibility of enforcing required
properties with the <link linkend="beans-required-annotation"
>@Required</link> annotation. Spring 2.5 made it possible to follow
that same general approach to drive Spring's dependency injection.
Essentially, the <interfacename>@Autowired</interfacename> annotation
provides the same capabilities as described in <xref
linkend="beans-factory-autowire"/> but with more fine-grained control and
wider applicability. Spring 2.5 also added support for JSR-250 annotations
such as <interfacename>@PostConstruct</interfacename>, and
<interfacename>@PreDestroy</interfacename>. Spring 3.0 added support for
JSR-330 (Dependency Injection for Java) annotations contained in the
javax.inject package such as <classname>@Inject</classname> and
<literal> @Named</literal>. Details about those annotations can be found in the <link linkend="beans-standard-annotations"
>relevant section</link>. <note> Annotation injection is performed
<emphasis>before</emphasis> XML injection, thus the latter configuration
will override the former for properties wired through both approaches.
</note> As always, you can register them as individual bean definitions, but
they can also be implicitly registered by including the following tag in an
XML-based Spring configuration (notice the inclusion of the
<literal>context</literal> namespace):</para>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<lineannotation>xmlns:context="http://www.springframework.org/schema/context"</lineannotation>
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"&gt;
<lineannotation>&lt;context:annotation-config/&gt;</lineannotation>
&lt;/beans&gt;</programlisting>
<para>(The implicitly registered post-processors include <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.html"
><classname>AutowiredAnnotationBeanPostProcessor</classname></ulink>, <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.html"
><classname>CommonAnnotationBeanPostProcessor</classname></ulink>, <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.html"
><classname>PersistenceAnnotationBeanPostProcessor</classname></ulink>, as
well as the aforementioned <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/annotation/RequiredAnnotationBeanPostProcessor.html"
><classname>RequiredAnnotationBeanPostProcessor</classname></ulink>.)</para>
<note>
<para><literal>&lt;context:annotation-config/&gt;</literal> only looks for
annotations on beans in the same application context in which it is
defined. This means that, if you put
<literal>&lt;context:annotation-config/&gt;</literal> in a
<interfacename>WebApplicationContext</interfacename> for a
<classname>DispatcherServlet</classname>, it only checks for
<interfacename>@Autowired</interfacename> beans in your controllers, and
not your services. See <xref linkend="mvc-servlet"/> for more
information.</para>
</note>
<section id="beans-required-annotation">
<title><interfacename>@Required</interfacename></title>
<para>The <interfacename>@Required</interfacename> annotation applies to
bean property setter methods, as in the following example:</para>
<programlisting language="java">public class SimpleMovieLister {
private MovieFinder movieFinder;
@Required
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>This annotation simply indicates that the affected bean property must
be populated at configuration time, through an explicit property value in
a bean definition or through autowiring. The container throws an exception
if the affected bean property has not been populated; this allows for
eager and explicit failure, avoiding
<classname>NullPointerException</classname>s or the like later on. It is
still recommended that you put assertions into the bean class itself, for
example, into an init method. Doing so enforces those required references
and values even when you use the class outside of a container.</para>
</section>
<section id="beans-autowired-annotation">
<title><interfacename>@Autowired</interfacename></title>
<para>As expected, you can apply the
<interfacename>@Autowired</interfacename> annotation to "traditional"
setter methods:</para>
<programlisting language="java">public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<note>
<para>JSR 330's @Inject annotation can be used in place of Spring's
<interfacename>@Autowired</interfacename> annotation in the examples below. See <link linkend="beans-standard-annotations"
>here</link> for more details</para>
</note>
<para>You can also apply the annotation to methods with arbitrary names
and/or multiple arguments:</para>
<programlisting language="java">public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>You can apply <interfacename>@Autowired</interfacename> to
constructors and fields:</para>
<programlisting language="java">public class MovieRecommender {
@Autowired
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>It is also possible to provide <emphasis>all</emphasis> beans of a
particular type from the <interfacename>ApplicationContext</interfacename>
by adding the annotation to a field or method that expects an array of
that type:</para>
<programlisting language="java">public class MovieRecommender {
@Autowired
private MovieCatalog[] movieCatalogs;
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>The same applies for typed collections:</para>
<programlisting language="java">public class MovieRecommender {
private Set&lt;MovieCatalog&gt; movieCatalogs;
@Autowired
public void setMovieCatalogs(Set&lt;MovieCatalog&gt; movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>Even typed Maps can be autowired as long as the expected key type is
<classname>String</classname>. The Map values will contain all beans of
the expected type, and the keys will contain the corresponding bean
names:</para>
<programlisting language="java">public class MovieRecommender {
private Map&lt;String, MovieCatalog&gt; movieCatalogs;
@Autowired
public void setMovieCatalogs(Map&lt;String, MovieCatalog&gt; movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>By default, the autowiring fails whenever <emphasis>zero</emphasis>
candidate beans are available; the default behavior is to treat annotated
methods, constructors, and fields as indicating
<emphasis>required</emphasis> dependencies. This behavior can be changed
as demonstrated below.</para>
<programlisting language="java">public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired(required=false)
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<note>
<para>Only <emphasis>one annotated constructor per-class</emphasis> can be
marked as <emphasis>required</emphasis>, but multiple non-required
constructors can be annotated. In that case, each is considered among
the candidates and Spring uses the <emphasis>greediest</emphasis>
constructor whose dependencies can be satisfied, that is the constructor
that has the largest number of arguments.</para>
<para><interfacename>@Autowired</interfacename>'s
<emphasis>required</emphasis> attribute is recommended over the
<interfacename>@Required</interfacename> annotation. The
<emphasis>required</emphasis> attribute indicates that the property is
not required for autowiring purposes, the property is ignored if it
cannot be autowired. <interfacename>@Required</interfacename>, on the
other hand, is stronger in that it enforces the property that was set by
any means supported by the container. If no value is injected, a
corresponding exception is raised.</para>
</note>
<para>You can also use <interfacename>@Autowired</interfacename> for
interfaces that are well-known resolvable dependencies:
<interfacename>BeanFactory</interfacename>,
<interfacename>ApplicationContext</interfacename>,
<interfacename>Environment</interfacename>,
<interfacename>ResourceLoader</interfacename>,
<interfacename>ApplicationEventPublisher</interfacename>, and
<interfacename>MessageSource</interfacename>. These interfaces and their
extended interfaces, such as
<interfacename>ConfigurableApplicationContext</interfacename> or
<interfacename>ResourcePatternResolver</interfacename>, are automatically
resolved, with no special setup necessary.</para>
<programlisting language="java">public class MovieRecommender {
@Autowired
private ApplicationContext context;
public MovieRecommender() {
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<note>
<para>
<interfacename>@Autowired</interfacename>,
<interfacename>@Inject</interfacename>,
<interfacename>@Resource</interfacename>, and
<interfacename>@Value</interfacename> annotations are handled by a
Spring <interfacename>BeanPostProcessor</interfacename> implementations
which in turn means that you <emphasis>cannot</emphasis>
apply these annotations within your own
<classname>BeanPostProcessor</classname> or
<classname>BeanFactoryPostProcessor</classname> types (if any). These
types must be 'wired up' explicitly via XML or using a Spring
<interfacename>@Bean</interfacename> method.</para>
</note>
</section>
<section id="beans-autowired-annotation-qualifiers">
<title>Fine-tuning annotation-based autowiring with qualifiers</title>
<para>Because autowiring by type may lead to multiple candidates, it is
often necessary to have more control over the selection process. One way
to accomplish this is with Spring's
<interfacename>@Qualifier</interfacename> annotation. You can associate
qualifier values with specific arguments, narrowing the set of type
matches so that a specific bean is chosen for each argument. In the
simplest case, this can be a plain descriptive value:</para>
<programlisting language="java">public class MovieRecommender {
@Autowired
<emphasis role="bold">@Qualifier("main")</emphasis>
private MovieCatalog movieCatalog;
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>The <interfacename>@Qualifier</interfacename> annotation can also be
specified on individual constructor arguments or method parameters:</para>
<programlisting language="java">public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(<emphasis role="bold">@Qualifier("main")</emphasis> MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>The corresponding bean definitions appear as follows. The bean with
qualifier value "main" is wired with the constructor argument that is
qualified with the same value.</para>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"&gt;
&lt;context:annotation-config/&gt;
&lt;bean class="example.SimpleMovieCatalog"&gt;
<emphasis role="bold">&lt;qualifier value="main"/&gt;</emphasis>
<lineannotation>&lt;!-- inject any dependencies required by this bean --&gt;</lineannotation>
&lt;/bean&gt;
&lt;bean class="example.SimpleMovieCatalog"&gt;
<emphasis role="bold">&lt;qualifier value="action"/&gt;</emphasis>
<lineannotation>&lt;!-- inject any dependencies required by this bean --&gt;</lineannotation>
&lt;/bean&gt;
&lt;bean id="movieRecommender" class="example.MovieRecommender"/&gt;
&lt;/beans&gt;
</programlisting>
<para>For a fallback match, the bean name is considered a default qualifier
value. Thus you can define the bean with an id "main" instead of the
nested qualifier element, leading to the same matching result. However,
although you can use this convention to refer to specific beans by name,
<interfacename>@Autowired</interfacename> is fundamentally about
type-driven injection with optional semantic qualifiers. This means that
qualifier values, even with the bean name fallback, always have narrowing
semantics within the set of type matches; they do not semantically express
a reference to a unique bean id. Good qualifier values are "main" or
"EMEA" or "persistent", expressing characteristics of a specific component
that are independent from the bean id, which may be auto-generated in case
of an anonymous bean definition like the one in the preceding
example.</para>
<para>Qualifiers also apply to typed collections, as discussed above, for
example, to <literal>Set&lt;MovieCatalog&gt;</literal>. In this case, all
matching beans according to the declared qualifiers are injected as a
collection. This implies that qualifiers do not have to be unique; they
rather simply constitute filtering criteria. For example, you can define
multiple <classname>MovieCatalog</classname> beans with the same qualifier
value "action"; all of which would be injected into a
<literal>Set&lt;MovieCatalog&gt;</literal> annotated with
<literal>@Qualifier("action")</literal>.</para>
<tip>
<para>If you intend to express annotation-driven injection by name, do not
primarily use <interfacename>@Autowired</interfacename>, even if is
technically capable of referring to a bean name through
<interfacename>@Qualifier</interfacename> values. Instead, use the
JSR-250 <interfacename>@Resource</interfacename> annotation, which is
semantically defined to identify a specific target component by its
unique name, with the declared type being irrelevant for the matching
process.</para>
<para>As a specific consequence of this semantic difference, beans that
are themselves defined as a collection or map type cannot be injected
through <interfacename>@Autowired</interfacename>, because type matching
is not properly applicable to them. Use
<interfacename>@Resource</interfacename> for such beans, referring to
the specific collection or map bean by unique name.</para>
<para><interfacename>@Autowired</interfacename> applies to fields,
constructors, and multi-argument methods, allowing for narrowing through
qualifier annotations at the parameter level. By contrast,
<interfacename>@Resource</interfacename> is supported only for fields
and bean property setter methods with a single argument. As a
consequence, stick with qualifiers if your injection target is a
constructor or a multi-argument method.</para>
</tip>
<para>You can create your own custom qualifier annotations. Simply define an
annotation and provide the <interfacename>@Qualifier</interfacename>
annotation within your definition:</para>
<programlisting language="java">@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
<emphasis role="bold">@Qualifier</emphasis>
public @interface Genre {
String value();
}</programlisting>
<para>Then you can provide the custom qualifier on autowired fields and
parameters:</para>
<programlisting language="java">public class MovieRecommender {
@Autowired
<emphasis role="bold">@Genre("Action")</emphasis>
private MovieCatalog actionCatalog;
private MovieCatalog comedyCatalog;
@Autowired
public void setComedyCatalog(<emphasis role="bold">@Genre("Comedy")</emphasis> MovieCatalog comedyCatalog) {
this.comedyCatalog = comedyCatalog;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>Next, provide the information for the candidate bean definitions. You
can add <literal>&lt;qualifier/&gt;</literal> tags as sub-elements of the
<literal>&lt;bean/&gt;</literal> tag and then specify the
<literal>type</literal> and <literal>value</literal> to match your custom
qualifier annotations. The type is matched against the fully-qualified
class name of the annotation. Or, as a convenience if no risk of
conflicting names exists, you can use the short class name. Both
approaches are demonstrated in the following example.</para>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"&gt;
&lt;context:annotation-config/&gt;
&lt;bean class="example.SimpleMovieCatalog"&gt;
<emphasis role="bold">&lt;qualifier type="Genre" value="Action"/&gt;</emphasis>
<lineannotation>&lt;!-- inject any dependencies required by this bean --&gt;</lineannotation>
&lt;/bean&gt;
&lt;bean class="example.SimpleMovieCatalog"&gt;
<emphasis role="bold">&lt;qualifier type="example.Genre" value="Comedy"/&gt;</emphasis>
<lineannotation>&lt;!-- inject any dependencies required by this bean --&gt;</lineannotation>
&lt;/bean&gt;
&lt;bean id="movieRecommender" class="example.MovieRecommender"/&gt;
&lt;/beans&gt;
</programlisting>
<para>In <xref linkend="beans-classpath-scanning"/>, you will see an
annotation-based alternative to providing the qualifier metadata in XML.
Specifically, see <xref linkend="beans-scanning-qualifiers"/>.</para>
<para>In some cases, it may be sufficient to use an annotation without a
value. This may be useful when the annotation serves a more generic
purpose and can be applied across several different types of dependencies.
For example, you may provide an <emphasis>offline</emphasis> catalog that
would be searched when no Internet connection is available. First define
the simple annotation:</para>
<programlisting language="java">@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Offline {
}</programlisting>
<para>Then add the annotation to the field or property to be
autowired:</para>
<programlisting language="java">public class MovieRecommender {
@Autowired
<emphasis role="bold">@Offline</emphasis>
private MovieCatalog offlineCatalog;
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>Now the bean definition only needs a qualifier
<literal>type</literal>:</para>
<programlisting language="xml">&lt;bean class="example.SimpleMovieCatalog"&gt;
<emphasis role="bold">&lt;qualifier type="Offline"/&gt;</emphasis>
<lineannotation>&lt;!-- inject any dependencies required by this bean --&gt;</lineannotation>
&lt;/bean&gt;</programlisting>
<para>You can also define custom qualifier annotations that accept named
attributes in addition to or instead of the simple
<literal>value</literal> attribute. If multiple attribute values are then
specified on a field or parameter to be autowired, a bean definition must
match <emphasis>all</emphasis> such attribute values to be considered an
autowire candidate. As an example, consider the following annotation
definition:</para>
<programlisting language="java">@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MovieQualifier {
String genre();
Format format();
}</programlisting>
<para>In this case <literal>Format</literal> is an enum:</para>
<programlisting language="java">public enum Format {
VHS, DVD, BLURAY
}</programlisting>
<para>The fields to be autowired are annotated with the custom qualifier and
include values for both attributes: <literal>genre</literal> and
<literal>format</literal>.</para>
<programlisting language="java">public class MovieRecommender {
@Autowired
@MovieQualifier(format=Format.VHS, genre="Action")
private MovieCatalog actionVhsCatalog;
@Autowired
@MovieQualifier(format=Format.VHS, genre="Comedy")
private MovieCatalog comedyVhsCatalog;
@Autowired
@MovieQualifier(format=Format.DVD, genre="Action")
private MovieCatalog actionDvdCatalog;
@Autowired
@MovieQualifier(format=Format.BLURAY, genre="Comedy")
private MovieCatalog comedyBluRayCatalog;
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>Finally, the bean definitions should contain matching qualifier
values. This example also demonstrates that bean <emphasis>meta</emphasis>
attributes may be used instead of the
<literal>&lt;qualifier/&gt;</literal> sub-elements. If available, the
<literal>&lt;qualifier/&gt;</literal> and its attributes take precedence,
but the autowiring mechanism falls back on the values provided within the
<literal>&lt;meta/&gt;</literal> tags if no such qualifier is present, as
in the last two bean definitions in the following example.</para>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"&gt;
&lt;context:annotation-config/&gt;
&lt;bean class="example.SimpleMovieCatalog"&gt;
&lt;qualifier type="MovieQualifier"&gt;
&lt;attribute key="format" value="VHS"/&gt;
&lt;attribute key="genre" value="Action"/&gt;
&lt;/qualifier&gt;
<lineannotation>&lt;!-- inject any dependencies required by this bean --&gt;</lineannotation>
&lt;/bean&gt;
&lt;bean class="example.SimpleMovieCatalog"&gt;
&lt;qualifier type="MovieQualifier"&gt;
&lt;attribute key="format" value="VHS"/&gt;
&lt;attribute key="genre" value="Comedy"/&gt;
&lt;/qualifier&gt;
<lineannotation>&lt;!-- inject any dependencies required by this bean --&gt;</lineannotation>
&lt;/bean&gt;
&lt;bean class="example.SimpleMovieCatalog"&gt;
&lt;meta key="format" value="DVD"/&gt;
&lt;meta key="genre" value="Action"/&gt;
<lineannotation>&lt;!-- inject any dependencies required by this bean --&gt;</lineannotation>
&lt;/bean&gt;
&lt;bean class="example.SimpleMovieCatalog"&gt;
&lt;meta key="format" value="BLURAY"/&gt;
&lt;meta key="genre" value="Comedy"/&gt;
<lineannotation>&lt;!-- inject any dependencies required by this bean --&gt;</lineannotation>
&lt;/bean&gt;
&lt;/beans&gt;</programlisting>
</section>
<section id="beans-custom-autowire-configurer">
<title><classname>CustomAutowireConfigurer</classname></title>
<para>The <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/annotation/CustomAutowireConfigurer.html"
><classname>CustomAutowireConfigurer</classname></ulink> is a
<interfacename>BeanFactoryPostProcessor</interfacename> that enables you
to register your own custom qualifier annotation types even if they are
not annotated with Spring's <interfacename>@Qualifier</interfacename>
annotation.</para>
<programlisting language="xml">&lt;bean id="customAutowireConfigurer"
class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer"&gt;
&lt;property name="customQualifierTypes"&gt;
&lt;set&gt;
&lt;value&gt;example.CustomQualifier&lt;/value&gt;
&lt;/set&gt;
&lt;/property&gt;
&lt;/bean&gt;</programlisting>
<para>The particular implementation of
<interfacename>AutowireCandidateResolver</interfacename> that is activated
for the application context depends on the Java version. In versions
earlier than Java 5, the qualifier annotations are not supported, and
therefore autowire candidates are solely determined by the
<literal>autowire-candidate</literal> value of each bean definition as
well as by any <literal>default-autowire-candidates</literal> pattern(s)
available on the <literal>&lt;beans/&gt;</literal> element. In Java 5 or
later, the presence of <interfacename>@Qualifier</interfacename>
annotations and any custom annotations registered with the
<classname>CustomAutowireConfigurer</classname> will also play a
role.</para>
<para>Regardless of the Java version, when multiple beans qualify as
autowire candidates, the determination of a "primary" candidate is the
same: if exactly one bean definition among the candidates has a
<literal>primary</literal> attribute set to <literal>true</literal>, it
will be selected.</para>
</section>
<section id="beans-resource-annotation">
<title><interfacename>@Resource</interfacename></title>
<para>Spring also supports injection using the JSR-250
<interfacename>@Resource</interfacename> annotation on fields or bean
property setter methods. This is a common pattern in Java EE 5 and 6, for
example in JSF 1.2 managed beans or JAX-WS 2.0 endpoints. Spring supports
this pattern for Spring-managed objects as well.</para>
<para><interfacename>@Resource</interfacename> takes a name attribute, and
by default Spring interprets that value as the bean name to be injected.
In other words, it follows <emphasis>by-name</emphasis> semantics, as
demonstrated in this example:</para>
<programlisting language="java">public class SimpleMovieLister {
private MovieFinder movieFinder;
<emphasis role="bold">@Resource(name="myMovieFinder")</emphasis>
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}</programlisting>
<para>If no name is specified explicitly, the default name is derived from
the field name or setter method. In case of a field, it takes the field
name; in case of a setter method, it takes the bean property name. So the
following example is going to have the bean with name "movieFinder"
injected into its setter method:</para>
<programlisting language="java">public class SimpleMovieLister {
private MovieFinder movieFinder;
<emphasis role="bold">@Resource</emphasis>
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}</programlisting>
<note>
<para>The name provided with the annotation is resolved as a bean name by
the <interfacename>ApplicationContext</interfacename> of which the
<classname>CommonAnnotationBeanPostProcessor</classname> is aware. The
names can be resolved through JNDI if you configure Spring's <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/jndi/support/SimpleJndiBeanFactory.html"
><classname>SimpleJndiBeanFactory</classname></ulink> explicitly.
However, it is recommended that you rely on the default behavior and
simply use Spring's JNDI lookup capabilities to preserve the level of
indirection.</para>
</note>
<para>In the exclusive case of <interfacename>@Resource</interfacename>
usage with no explicit name specified, and similar to
<interfacename>@Autowired</interfacename>,
<interfacename>@Resource</interfacename> finds a primary type match
instead of a specific named bean and resolves well-known resolvable
dependencies: the
<interfacename>BeanFactory</interfacename><interfacename>,
ApplicationContext,</interfacename><interfacename> ResourceLoader,
ApplicationEventPublisher</interfacename>, and
<interfacename>MessageSource</interfacename> interfaces.</para>
<para>Thus in the following example, the
<literal>customerPreferenceDao</literal> field first looks for a bean
named customerPreferenceDao, then falls back to a primary type match for
the type <classname>CustomerPreferenceDao</classname>. The "context" field
is injected based on the known resolvable dependency type
<interfacename>ApplicationContext</interfacename>.</para>
<programlisting language="java">public class MovieRecommender {
@Resource
private CustomerPreferenceDao customerPreferenceDao;
@Resource
private ApplicationContext context;
public MovieRecommender() {
}
<lineannotation>// ...</lineannotation>
}</programlisting>
</section>
<section id="beans-postconstruct-and-predestroy-annotations">
<title><interfacename>@PostConstruct</interfacename> and
<interfacename>@PreDestroy</interfacename></title>
<para>The <classname>CommonAnnotationBeanPostProcessor</classname> not only
recognizes the <interfacename>@Resource</interfacename> annotation but
also the JSR-250 <emphasis>lifecycle</emphasis> annotations. Introduced in
Spring 2.5, the support for these annotations offers yet another
alternative to those described in <link
linkend="beans-factory-lifecycle-initializingbean">initialization
callbacks</link> and <link
linkend="beans-factory-lifecycle-disposablebean">destruction
callbacks</link>. Provided that the
<classname>CommonAnnotationBeanPostProcessor</classname> is registered
within the Spring <interfacename>ApplicationContext</interfacename>, a
method carrying one of these annotations is invoked at the same point in
the lifecycle as the corresponding Spring lifecycle interface method or
explicitly declared callback method. In the example below, the cache will
be pre-populated upon initialization and cleared upon destruction.</para>
<programlisting language="java">public class CachingMovieLister {
@PostConstruct
public void populateMovieCache() {
<lineannotation>// populates the movie cache upon initialization...</lineannotation>
}
@PreDestroy
public void clearMovieCache() {
<lineannotation>// clears the movie cache upon destruction...</lineannotation>
}
}</programlisting>
<note>
<para>For details about the effects of combining various lifecycle
mechanisms, see <xref linkend="beans-factory-lifecycle-combined-effects"
/>.</para>
</note>
</section>
</section>

View File

@@ -0,0 +1,502 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="beans-classpath-scanning">
<title>Classpath scanning and managed components</title>
<para>Most examples in this chapter use XML to specify the configuration
metadata that produces each <interfacename>BeanDefinition</interfacename>
within the Spring container. The previous section
(<xref linkend="beans-annotation-config"/>) demonstrates how to provide a
lot of the configuration metadata through source-level annotations. Even
in those examples, however, the "base" bean definitions are explicitly
defined in the XML file, while the annotations only drive the dependency
injection. This section describes an option for implicitly detecting the
<emphasis>candidate components</emphasis> by scanning the classpath.
Candidate components are classes that match against a filter criteria and
have a corresponding bean definition registered with the container. This
removes the need to use XML to perform bean registration, instead you can
use annotations (for example @Component), AspectJ type expressions, or your
own custom filter criteria to select which classes will have bean
definitions registered with the container.</para>
<note>
<para>Starting with Spring 3.0, many features provided by the <ulink
url="http://www.springsource.org/javaconfig">Spring JavaConfig
project</ulink> are part of the core Spring Framework. This allows you to
define beans using Java rather than using the traditional XML files. Take
a look at the <interfacename>@Configuration</interfacename>,
<interfacename>@Bean</interfacename>,
<interfacename>@Import</interfacename>, and
<interfacename>@DependsOn</interfacename> annotations for examples of how
to use these new features.</para>
</note>
<section id="beans-stereotype-annotations">
<title><interfacename>@Component</interfacename> and further stereotype
annotations</title>
<para>In Spring 2.0 and later, the
<interfacename>@Repository</interfacename> annotation is a marker for any
class that fulfills the role or <emphasis>stereotype</emphasis> (also
known as Data Access Object or DAO) of a repository. Among the uses of
this marker is the automatic translation of exceptions as described in
<xref linkend="orm-exception-translation"/>.</para>
<para>Spring 2.5 introduces further stereotype annotations:
<interfacename>@Component</interfacename>,
<interfacename>@Service</interfacename>, and
<interfacename>@Controller</interfacename>.
<interfacename>@Component</interfacename> is a generic stereotype for any
Spring-managed component. <interfacename>@Repository</interfacename>,
<interfacename>@Service</interfacename>, and
<interfacename>@Controller</interfacename> are specializations of
<interfacename>@Component</interfacename> for more specific use cases, for
example, in the persistence, service, and presentation layers,
respectively. Therefore, you can annotate your component classes with
<interfacename>@Component</interfacename>, but by annotating them with
<interfacename>@Repository</interfacename>,
<interfacename>@Service</interfacename>, or
<interfacename>@Controller</interfacename> instead, your classes are more
properly suited for processing by tools or associating with aspects. For
example, these stereotype annotations make ideal targets for pointcuts. It
is also possible that <interfacename>@Repository</interfacename>,
<interfacename>@Service</interfacename>, and
<interfacename>@Controller</interfacename> may carry additional semantics
in future releases of the Spring Framework. Thus, if you are choosing
between using <interfacename>@Component</interfacename> or
<interfacename>@Service</interfacename> for your service layer,
<interfacename>@Service</interfacename> is clearly the better choice.
Similarly, as stated above, <interfacename>@Repository</interfacename> is
already supported as a marker for automatic exception translation in your
persistence layer.</para>
</section>
<section id="beans-scanning-autodetection">
<title>Automatically detecting classes and registering bean
definitions</title>
<para>Spring can automatically detect stereotyped classes and register
corresponding <interfacename>BeanDefinition</interfacename>s with the
<interfacename>ApplicationContext</interfacename>. For example, the
following two classes are eligible for such autodetection:</para>
<programlisting language="java">@Service
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired
public SimpleMovieLister(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}</programlisting>
<programlisting language="java">@Repository
public class JpaMovieFinder implements MovieFinder {
<lineannotation>// implementation elided for clarity</lineannotation>
}</programlisting>
<para>To autodetect these classes and register the corresponding beans, you
need to include the following element in XML, where the base-package
element is a common parent package for the two classes. (Alternatively,
you can specify a comma-separated list that includes the parent package of
each class.)</para>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"&gt;
&lt;context:component-scan base-package="org.example"/&gt;
&lt;/beans&gt;</programlisting>
<note>
<para>The scanning of classpath packages requires the presence of
corresponding directory entries in the classpath. When you build JARs
with Ant, make sure that you do <emphasis>not</emphasis> activate the
files-only switch of the JAR task.</para>
</note>
<para>Furthermore, the
<interfacename>AutowiredAnnotationBeanPostProcessor</interfacename> and
<interfacename>CommonAnnotationBeanPostProcessor</interfacename> are both
included implicitly when you use the component-scan element. That means
that the two components are autodetected <emphasis>and</emphasis> wired
together - all without any bean configuration metadata provided in
XML.</para>
<note>
<para>You can disable the registration of
<interfacename>AutowiredAnnotationBeanPostProcessor</interfacename> and
<interfacename>CommonAnnotationBeanPostProcessor</interfacename> by
including the <emphasis>annotation-config</emphasis> attribute with a
value of false.</para>
</note>
<!--
<note>
<para>In Spring 3.0 RC1 you can use JSR 330's
<interfacename>@Named</interfacename> annotation in place of
stereotpye annotations and they will be automatically detected during
component-scanning. The value of the
<interfacename>@Named</interfacename> property will be used as the
Bean Name. At this time Spring defaults for bean scope will be applied
when using @Named. This behavior as well as mapping of JSR 330 and JSR
299 scopes is planned for Spring 3.0 GA assuming the JSRs are stable
at that time.</para>
</note>
-->
</section>
<section id="beans-scanning-filters">
<title>Using filters to customize scanning</title>
<para>By default, classes annotated with
<interfacename>@Component</interfacename>,
<interfacename>@Repository</interfacename>,
<interfacename>@Service</interfacename>,
<interfacename>@Controller</interfacename>, or a custom annotation that
itself is annotated with <interfacename>@Component</interfacename> are the
only detected candidate components. However, you can modify and extend
this behavior simply by applying custom filters. Add them as
<emphasis>include-filter</emphasis> or <emphasis>exclude-filter</emphasis>
sub-elements of the <literal>component-scan</literal> element. Each filter
element requires the <literal>type</literal> and
<literal>expression</literal> attributes. The following table describes
the filtering options.</para>
<table id="beans-scanning-filters-tbl">
<title>Filter Types</title>
<tgroup cols="3">
<colspec colname="c1" colwidth="1*"/>
<colspec colname="c2" colwidth="3*"/>
<colspec colname="c" colwidth="4*"/>
<thead>
<row>
<entry>Filter Type</entry>
<entry>Example Expression</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>annotation</entry>
<entry><literal>org.example.SomeAnnotation</literal></entry>
<entry>An annotation to be present at the type level in target
components.</entry>
</row>
<row>
<entry>assignable</entry>
<entry><literal>org.example.SomeClass</literal></entry>
<entry>A class (or interface) that the target components are
assignable to (extend/implement).</entry>
</row>
<row>
<entry>aspectj</entry>
<entry><literal>org.example..*Service+</literal></entry>
<entry>An AspectJ type expression to be matched by the target
components.</entry>
</row>
<row>
<entry>regex</entry>
<entry><literal>org\.example\.Default.*</literal></entry>
<entry>A regex expression to be matched by the target components
class names.</entry>
</row>
<row>
<entry>custom</entry>
<entry><literal>org.example.MyTypeFilter</literal></entry>
<entry>A custom implementation of the
<interfacename>org.springframework.core.type
.TypeFilter</interfacename> interface.</entry>
</row>
</tbody>
</tgroup>
</table>
<para>The following example shows the XML configuration ignoring all
<interfacename>@Repository</interfacename> annotations and using "stub"
repositories instead.</para>
<programlisting language="xml">&lt;beans&gt;
&lt;context:component-scan base-package="org.example"&gt;
&lt;context:include-filter type="regex" expression=".*Stub.*Repository"/&gt;
&lt;context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Repository"/&gt;
&lt;/context:component-scan&gt;
&lt;/beans&gt;</programlisting>
<note>
<para>You can also disable the default filters by providing
<emphasis>use-default-filters="false"</emphasis> as an attribute of the
&lt;component-scan/&gt; element. This will in effect disable automatic
detection of classes annotated with
<interfacename>@Component</interfacename>,
<interfacename>@Repository</interfacename>,
<interfacename>@Service</interfacename>, or
<interfacename>@Controller</interfacename>.</para>
</note>
</section>
<section id="beans-factorybeans-annotations">
<title>Defining bean metadata within components</title>
<para>Spring components can also contribute bean definition metadata to the
container. You do this with the same <literal>@Bean</literal> annotation
used to define bean metadata within <literal>@Configuration</literal>
annotated classes. Here is a simple example:</para>
<programlisting language="java">@Component
public class FactoryMethodComponent {
@Bean @Qualifier("public")
public TestBean publicInstance() {
return new TestBean("publicInstance");
}
public void doWork() {
// Component method implementation omitted
}
}</programlisting>
<para>This class is a Spring component that has application-specific code
contained in its <methodname>doWork()</methodname> method. However, it
also contributes a bean definition that has a factory method referring to
the method <methodname>publicInstance()</methodname>. The
<literal>@Bean</literal> annotation identifies the factory method and
other bean definition properties, such as a qualifier value through the
<classname>@Qualifier</classname> annotation. Other method level
annotations that can be specified are <literal>@Scope</literal>,
<literal>@Lazy</literal>, and custom qualifier annotations. Autowired
fields and methods are supported as previously discussed, with additional
support for autowiring of <literal>@Bean</literal> methods:</para>
<programlisting language="java">@Component
public class FactoryMethodComponent {
private static int i;
@Bean @Qualifier("public")
public TestBean publicInstance() {
return new TestBean("publicInstance");
}
// use of a custom qualifier and autowiring of method parameters
@Bean
protected TestBean protectedInstance(@Qualifier("public") TestBean spouse,
@Value("#{privateInstance.age}") String country) {
TestBean tb = new TestBean("protectedInstance", 1);
tb.setSpouse(tb);
tb.setCountry(country);
return tb;
}
@Bean @Scope(BeanDefinition.SCOPE_SINGLETON)
private TestBean privateInstance() {
return new TestBean("privateInstance", i++);
}
@Bean @Scope(value = WebApplicationContext.SCOPE_SESSION,
proxyMode = ScopedProxyMode.TARGET_CLASS)
public TestBean requestScopedInstance() {
return new TestBean("requestScopedInstance", 3);
}
}
</programlisting>
<para>The example autowires the <classname>String</classname> method
parameter <literal>country</literal> to the value of the
<literal>Age</literal> property on another bean named
<literal>privateInstance</literal>. A Spring Expression Language element
defines the value of the property through the notation <literal>#{
&lt;expression&gt; }</literal>. For <literal>@Value</literal> annotations,
an expression resolver is preconfigured to look for bean names when
resolving expression text.</para>
<para>The <literal>@Bean</literal> methods in a Spring component are
processed differently than their counterparts inside a Spring
<literal>@Configuration</literal> class. The difference is that
<literal>@Component</literal> classes are not enhanced with CGLIB to
intercept the invocation of methods and fields. CGLIB proxying is the
means by which invoking methods or fields within
<literal>@Configuration</literal> classes <literal>@Bean</literal> methods
create bean metadata references to collaborating objects. Methods are
<emphasis>not</emphasis> invoked with normal Java semantics. In contrast,
calling a method or field within a <literal>@Component</literal> classes
<literal>@Bean</literal> method <emphasis>has</emphasis> standard Java
semantics.</para>
</section>
<section id="beans-scanning-name-generator">
<title>Naming autodetected components</title>
<para>When a component is autodetected as part of the scanning process, its
bean name is generated by the
<interfacename>BeanNameGenerator</interfacename> strategy known to that
scanner. By default, any Spring stereotype annotation
(<interfacename>@Component</interfacename>,
<interfacename>@Repository</interfacename>,
<interfacename>@Service</interfacename>, and
<interfacename>@Controller</interfacename>) that contains a
<literal>name</literal> value will thereby provide that name to the
corresponding bean definition.</para>
<para>If such an annotation contains no <literal>name</literal> value or for
any other detected component (such as those discovered by custom filters),
the default bean name generator returns the uncapitalized non-qualified
class name. For example, if the following two components were detected,
the names would be myMovieLister and movieFinderImpl:</para>
<programlisting language="java">@Service("myMovieLister")
public class SimpleMovieLister {
<lineannotation>// ...</lineannotation>
}</programlisting>
<programlisting language="java">@Repository
public class MovieFinderImpl implements MovieFinder {
<lineannotation>// ...</lineannotation>
}</programlisting>
<note>
<para>If you do not want to rely on the default bean-naming strategy, you
can provide a custom bean-naming strategy. First, implement the <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/support/BeanNameGenerator.html"
><interfacename>BeanNameGenerator</interfacename></ulink> interface, and
be sure to include a default no-arg constructor. Then, provide the
fully-qualified class name when configuring the scanner:</para>
</note>
<programlisting language="xml">&lt;beans&gt;
&lt;context:component-scan base-package="org.example"
name-generator="org.example.MyNameGenerator" /&gt;
&lt;/beans&gt;</programlisting>
<para>As a general rule, consider specifying the name with the annotation
whenever other components may be making explicit references to it. On the
other hand, the auto-generated names are adequate whenever the container
is responsible for wiring.</para>
</section>
<section id="beans-scanning-scope-resolver">
<title>Providing a scope for autodetected components</title>
<para>As with Spring-managed components in general, the default and most
common scope for autodetected components is singleton. However, sometimes
you need other scopes, which Spring 2.5 provides with a new
<interfacename>@Scope</interfacename> annotation. Simply provide the name
of the scope within the annotation:</para>
<programlisting language="java">@Scope("prototype")
@Repository
public class MovieFinderImpl implements MovieFinder {
<lineannotation>// ...</lineannotation>
}</programlisting>
<note>
<para>To provide a custom strategy for scope resolution rather than
relying on the annotation-based approach, implement the <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/annotation/ScopeMetadataResolver.html"
><interfacename>ScopeMetadataResolver</interfacename></ulink> interface,
and be sure to include a default no-arg constructor. Then, provide the
fully-qualified class name when configuring the scanner:</para>
</note>
<programlisting language="xml">&lt;beans&gt;
&lt;context:component-scan base-package="org.example"
scope-resolver="org.example.MyScopeResolver" /&gt;
&lt;/beans&gt;</programlisting>
<para>When using certain non-singleton scopes, it may be necessary to
generate proxies for the scoped objects. The reasoning is described in
<xref linkend="beans-factory-scopes-other-injection"/>. For this purpose,
a <emphasis>scoped-proxy</emphasis> attribute is available on the
component-scan element. The three possible values are: no, interfaces, and
targetClass. For example, the following configuration will result in
standard JDK dynamic proxies:</para>
<programlisting language="xml">&lt;beans&gt;
&lt;context:component-scan base-package="org.example"
scoped-proxy="interfaces" /&gt;
&lt;/beans&gt;</programlisting>
</section>
<section id="beans-scanning-qualifiers">
<title>Providing qualifier metadata with annotations</title>
<para>The <interfacename>@Qualifier</interfacename> annotation is discussed
in <xref linkend="beans-autowired-annotation-qualifiers"/>. The examples
in that section demonstrate the use of the
<interfacename>@Qualifier</interfacename> annotation and custom qualifier
annotations to provide fine-grained control when you resolve autowire
candidates. Because those examples were based on XML bean definitions, the
qualifier metadata was provided on the candidate bean definitions using
the <literal>qualifier</literal> or <literal>meta</literal> sub-elements
of the <literal>bean</literal> element in the XML. When relying upon
classpath scanning for autodetection of components, you provide the
qualifier metadata with type-level annotations on the candidate class. The
following three examples demonstrate this technique:</para>
<programlisting language="java">@Component
<emphasis role="bold">@Qualifier("Action")</emphasis>
public class ActionMovieCatalog implements MovieCatalog {
<lineannotation>// ...</lineannotation>
}</programlisting>
<programlisting language="java">@Component
<emphasis role="bold">@Genre("Action")</emphasis>
public class ActionMovieCatalog implements MovieCatalog {
<lineannotation>// ...</lineannotation>
}</programlisting>
<programlisting language="java">@Component
<emphasis role="bold">@Offline</emphasis>
public class CachingMovieCatalog implements MovieCatalog {
<lineannotation>// ...</lineannotation>
}</programlisting>
<note>
<para>As with most annotation-based alternatives, keep in mind that the
annotation metadata is bound to the class definition itself, while the
use of XML allows for multiple beans <emphasis>of the same
type</emphasis> to provide variations in their qualifier metadata,
because that metadata is provided per-instance rather than
per-class.</para>
</note>
</section>
</section>

View File

@@ -0,0 +1,663 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="context-introduction">
<title>Additional Capabilities of the
<interfacename>ApplicationContext</interfacename></title>
<!-- MLP: Beverly to review paragraph and list -->
<para>As was discussed in the chapter introduction, the
<literal>org.springframework.beans.factory</literal> package provides basic
functionality for managing and manipulating beans, including in a
programmatic way. The <literal>org.springframework.context</literal> package
adds the <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/ApplicationContext.html"
><interfacename>ApplicationContext</interfacename></ulink> interface, which
extends the <interfacename>BeanFactory</interfacename> interface, in
addition to extending other interfaces to provide additional functionality
in a more <emphasis>application framework-oriented style</emphasis>. Many
people use the <interfacename>ApplicationContext</interfacename> in a
completely declarative fashion, not even creating it programmatically, but
instead relying on support classes such as
<classname>ContextLoader</classname> to automatically instantiate an
<interfacename>ApplicationContext</interfacename> as part of the normal
startup process of a J2EE web application.</para>
<para>To enhance <interfacename>BeanFactory</interfacename> functionality in a
more framework-oriented style the context package also provides the
following functionality:</para>
<itemizedlist>
<listitem>
<para><emphasis>Access to messages in i18n-style</emphasis>, through the
<interfacename>MessageSource</interfacename> interface.</para>
</listitem>
<listitem>
<para><emphasis>Access to resources</emphasis>, such as URLs and files,
through the <interfacename>ResourceLoader</interfacename>
interface.</para>
</listitem>
<listitem>
<para><emphasis>Event publication</emphasis> to beans implementing the
<interfacename>ApplicationListener</interfacename> interface, through
the use of the <interfacename>ApplicationEventPublisher</interfacename>
interface.</para>
</listitem>
<listitem>
<para><emphasis>Loading of multiple (hierarchical) contexts</emphasis>,
allowing each to be focused on one particular layer, such as the web
layer of an application, through the
<interfacename>HierarchicalBeanFactory</interfacename> interface.</para>
</listitem>
</itemizedlist>
<section id="context-functionality-messagesource">
<title>Internationalization using
<interfacename>MessageSource</interfacename></title>
<!-- MLP: Beverly to review this paragraph -->
<para>The <interfacename>ApplicationContext</interfacename> interface
extends an interface called <interfacename>MessageSource</interfacename>,
and therefore provides internationalization (i18n) functionality. Spring
also provides the interface
<classname>HierarchicalMessageSource</classname>, which can resolve
messages hierarchically. Together these interfaces provide the foundation
upon which Spring effects message resolution. The methods defined on these
interfaces include:</para>
<itemizedlist>
<listitem>
<para><methodname>String getMessage(String code, Object[] args, String
default, Locale loc)</methodname>: The basic method used to retrieve a
message from the <interfacename>MessageSource</interfacename>. When no
message is found for the specified locale, the default message is
used. Any arguments passed in become replacement values, using the
<interfacename>MessageFormat</interfacename> functionality provided by
the standard library.</para>
</listitem>
<listitem>
<para><methodname>String getMessage(String code, Object[] args, Locale
loc)</methodname>: Essentially the same as the previous method, but
with one difference: no default message can be specified; if the
message cannot be found, a
<classname>NoSuchMessageException</classname> is thrown.</para>
</listitem>
<listitem>
<para><methodname>String getMessage(MessageSourceResolvable resolvable,
Locale locale)</methodname>: All properties used in the preceding
methods are also wrapped in a class named
<interfacename>MessageSourceResolvable</interfacename>, which you can
use with this method.</para>
</listitem>
</itemizedlist>
<para>When an <interfacename>ApplicationContext</interfacename> is loaded,
it automatically searches for a
<interfacename>MessageSource</interfacename> bean defined in the context.
The bean must have the name <literal>messageSource</literal>. If such a
bean is found, all calls to the preceding methods are delegated to the
message source. If no message source is found, the
<interfacename>ApplicationContext</interfacename> attempts to find a
parent containing a bean with the same name. If it does, it uses that bean
as the <interfacename>MessageSource</interfacename>. If the
<interfacename>ApplicationContext</interfacename> cannot find any source
for messages, an empty <classname>DelegatingMessageSource</classname> is
instantiated in order to be able to accept calls to the methods defined
above.</para>
<para>Spring provides two <interfacename>MessageSource</interfacename>
implementations, <classname>ResourceBundleMessageSource</classname> and
<classname>StaticMessageSource</classname>. Both implement
<interfacename>HierarchicalMessageSource</interfacename> in order to do
nested messaging. The <classname>StaticMessageSource</classname> is rarely
used but provides programmatic ways to add messages to the source. The
<classname>ResourceBundleMessageSource</classname> is shown in the
following example:</para>
<programlisting language="xml">&lt;beans&gt;
&lt;bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource"&gt;
&lt;property name="basenames"&gt;
&lt;list&gt;
&lt;value&gt;format&lt;/value&gt;
&lt;value&gt;exceptions&lt;/value&gt;
&lt;value&gt;windows&lt;/value&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting>
<para>In the example it is assumed you have three resource bundles defined
in your classpath called <literal>format</literal>,
<literal>exceptions</literal> and <literal>windows</literal>. Any request
to resolve a message will be handled in the JDK standard way of resolving
messages through ResourceBundles. For the purposes of the example, assume
the contents of two of the above resource bundle files are...</para>
<programlisting language="java"><lineannotation># in format.properties</lineannotation>
message=Alligators rock!</programlisting>
<programlisting language="java"><lineannotation># in exceptions.properties</lineannotation>
argument.required=The '{0}' argument is required.</programlisting>
<para>A program to execute the <classname>MessageSource</classname>
functionality is shown in the next example. Remember that all
<classname>ApplicationContext</classname> implementations are also
<classname>MessageSource</classname> implementations and so can be cast to
the <classname>MessageSource</classname> interface.</para>
<programlisting language="java">public static void main(String[] args) {
MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
String message = resources.getMessage("message", null, "Default", null);
System.out.println(message);
}</programlisting>
<para>The resulting output from the above program will be...</para>
<programlisting>Alligators rock!</programlisting>
<para>So to summarize, the <classname>MessageSource</classname> is defined
in a file called <literal>beans.xml</literal>, which exists at the root of
your classpath. The <literal>messageSource</literal> bean definition
refers to a number of resource bundles through its
<literal>basenames</literal> property. The three files that are passed in
the list to the <literal>basenames</literal> property exist as files at
the root of your classpath and are called
<literal>format.properties</literal>,
<literal>exceptions.properties</literal>, and
<literal>windows.properties</literal> respectively.</para>
<para>The next example shows arguments passed to the message lookup; these
arguments will be converted into Strings and inserted into placeholders in
the lookup message.</para>
<programlisting language="xml">&lt;beans&gt;
<lineannotation>&lt;!-- this <interfacename>MessageSource</interfacename> is being used in a web application --&gt;</lineannotation>
&lt;bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"&gt;
&lt;property name="basename" value="test-messages"/&gt;
&lt;/bean&gt;
<lineannotation>&lt;!-- lets inject the above <interfacename>MessageSource</interfacename> into this POJO --&gt;</lineannotation>
&lt;bean id="example" class="com.foo.Example"&gt;
&lt;property name="messages" ref="messageSource"/&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting>
<programlisting language="java">public class Example {
private MessageSource messages;
public void setMessages(MessageSource messages) {
this.messages = messages;
}
public void execute() {
String message = this.messages.getMessage("argument.required",
new Object [] {"userDao"}, "Required", null);
System.out.println(message);
}
}</programlisting>
<para>The resulting output from the invocation of the
<methodname>execute()</methodname> method will be...</para>
<programlisting>The userDao argument is required.</programlisting>
<para>With regard to internationalization (i18n), Spring's various
<classname>MessageResource</classname> implementations follow the same
locale resolution and fallback rules as the standard JDK
<classname>ResourceBundle</classname>. In short, and continuing with the
example <literal>messageSource</literal> defined previously, if you want
to resolve messages against the British (en-GB) locale, you would create
files called <literal>format_en_GB.properties</literal>,
<literal>exceptions_en_GB.properties</literal>, and
<literal>windows_en_GB.properties</literal> respectively.</para>
<para>Typically, locale resolution is managed by the surrounding environment
of the application. In this example, the locale against which (British)
messages will be resolved is specified manually.</para>
<programlisting><lineannotation># in exceptions_en_GB.properties</lineannotation>
argument.required=Ebagum lad, the '{0}' argument is required, I say, required.</programlisting>
<programlisting language="java">public static void main(final String[] args) {
MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
String message = resources.getMessage("argument.required",
new Object [] {"userDao"}, "Required", Locale.UK);
System.out.println(message);
}</programlisting>
<para>The resulting output from the running of the above program will
be...</para>
<programlisting>Ebagum lad, the 'userDao' argument is required, I say, required.</programlisting>
<para>You can also use the <classname>MessageSourceAware</classname>
interface to acquire a reference to any
<classname>MessageSource</classname> that has been defined. Any bean that
is defined in an <classname>ApplicationContext</classname> that implements
the <classname>MessageSourceAware</classname> interface is injected with
the application context's <classname>MessageSource</classname> when the
bean is created and configured.</para>
<note>
<para><emphasis>As an alternative to
<classname>ResourceBundleMessageSource</classname>, Spring provides a
<classname>ReloadableResourceBundleMessageSource</classname> class. This
variant supports the same bundle file format but is more flexible than
the standard JDK based
<classname>ResourceBundleMessageSource</classname>
implementation.</emphasis> In particular, it allows for reading files
from any Spring resource location (not just from the classpath) and
supports hot reloading of bundle property files (while efficiently
caching them in between). Check out the
<classname>ReloadableResourceBundleMessageSource</classname> javadoc for
details.</para>
</note>
</section>
<section id="context-functionality-events">
<title>Standard and Custom Events</title>
<para>Event handling in the
<interfacename>ApplicationContext</interfacename> is provided through the
<classname>ApplicationEvent</classname> class and
<interfacename>ApplicationListener</interfacename> interface. If a bean
that implements the <interfacename>ApplicationListener</interfacename>
interface is deployed into the context, every time an
<classname>ApplicationEvent</classname> gets published to the
<interfacename>ApplicationContext</interfacename>, that bean is notified.
Essentially, this is the standard <emphasis>Observer</emphasis> design
pattern. Spring provides the following standard events:</para>
<table id="beans-ctx-events-tbl">
<title>Built-in Events</title>
<tgroup cols="2">
<colspec colname="c1" colwidth="2*"/>
<colspec colname="c2" colwidth="5*"/>
<thead>
<row>
<entry>Event</entry>
<entry>Explanation</entry>
</row>
</thead>
<tbody>
<row>
<entry><classname>ContextRefreshedEvent</classname></entry>
<entry>Published when the
<interfacename>ApplicationContext</interfacename> is initialized
or refreshed, for example, using the
<methodname>refresh()</methodname> method on the
<interfacename>ConfigurableApplicationContext</interfacename>
interface. "Initialized" here means that all beans are loaded,
post-processor beans are detected and activated, singletons are
pre-instantiated, and the
<interfacename>ApplicationContext</interfacename> object is ready
for use. As long as the context has not been closed, a refresh can
be triggered multiple times, provided that the chosen
<interfacename>ApplicationContext</interfacename> actually
supports such "hot" refreshes. For example,
<classname>XmlWebApplicationContext</classname> supports hot
refreshes, but <classname>GenericApplicationContext</classname>
does not.</entry>
</row>
<row>
<entry><classname>ContextStartedEvent</classname></entry>
<entry>Published when the
<interfacename>ApplicationContext</interfacename> is started,
using the <methodname>start()</methodname> method on the
<interfacename>ConfigurableApplicationContext</interfacename>
interface. "Started" here means that all
<interfacename>Lifecycle</interfacename> beans receive an explicit
start signal. Typically this signal is used to restart beans after
an explicit stop, but it may also be used to start components that
have not been configured for autostart , for example, components
that have not already started on initialization.</entry>
</row>
<row>
<entry><classname>ContextStoppedEvent</classname></entry>
<entry>Published when the
<interfacename>ApplicationContext</interfacename> is stopped,
using the <methodname>stop()</methodname> method on the
<interfacename>ConfigurableApplicationContext</interfacename>
interface. "Stopped" here means that all
<interfacename>Lifecycle</interfacename> beans receive an explicit
stop signal. A stopped context may be restarted through a
<methodname>start()</methodname> call.</entry>
</row>
<row>
<entry><classname>ContextClosedEvent</classname></entry>
<entry>Published when the
<interfacename>ApplicationContext</interfacename> is closed, using
the <methodname>close()</methodname> method on the
<interfacename>ConfigurableApplicationContext</interfacename>
interface. "Closed" here means that all singleton beans are
destroyed. A closed context reaches its end of life; it cannot be
refreshed or restarted.</entry>
</row>
<row>
<entry><classname>RequestHandledEvent</classname></entry>
<entry>A web-specific event telling all beans that an HTTP request
has been serviced. This event is published
<emphasis>after</emphasis> the request is complete. This event is
only applicable to web applications using Spring's
<classname>DispatcherServlet</classname>.</entry>
</row>
</tbody>
</tgroup>
</table>
<para>You can also create and publish your own custom events. This example
demonstrates a simple class that extends Spring's
<classname>ApplicationEvent</classname> base class:</para>
<programlisting language="java">public class BlackListEvent extends ApplicationEvent {
private final String address;
private final String test;
public BlackListEvent(Object source, String address, String test) {
super(source);
this.address = address;
this.test = test;
}
<lineannotation>// accessor and other methods...</lineannotation>
}</programlisting>
<para>To publish a custom <classname>ApplicationEvent</classname>, call the
<methodname>publishEvent()</methodname> method on an
<interfacename>ApplicationEventPublisher</interfacename>. Typically this
is done by creating a class that implements
<interfacename>ApplicationEventPublisherAware</interfacename> and
registering it as a Spring bean. The following example demonstrates such a
class:</para>
<programlisting language="java"><![CDATA[public class EmailService implements ApplicationEventPublisherAware {
private List<String> blackList;
private ApplicationEventPublisher publisher;
public void setBlackList(List<String> blackList) {
this.blackList = blackList;
}
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
public void sendEmail(String address, String text) {
if (blackList.contains(address)) {
BlackListEvent event = new BlackListEvent(this, address, text);
publisher.publishEvent(event);
return;
}
]]><lineannotation>// send email...</lineannotation><![CDATA[
}
}]]></programlisting>
<para>At configuration time, the Spring container will detect that
<classname>EmailService</classname> implements
<interfacename>ApplicationEventPublisherAware</interfacename> and will
automatically call
<methodname>setApplicationEventPublisher()</methodname>. In reality, the
parameter passed in will be the Spring container itself; you're simply
interacting with the application context via its
<interfacename>ApplicationEventPublisher</interfacename> interface.</para>
<para>To receive the custom <classname>ApplicationEvent</classname>, create
a class that implements <interfacename>ApplicationListener</interfacename>
and register it as a Spring bean. The following example demonstrates such
a class:</para>
<programlisting language="java"><![CDATA[public class BlackListNotifier implements ApplicationListener<BlackListEvent> {
private String notificationAddress;
public void setNotificationAddress(String notificationAddress) {
this.notificationAddress = notificationAddress;
}
public void onApplicationEvent(BlackListEvent event) {
]]><lineannotation> // notify appropriate parties via notificationAddress...</lineannotation><![CDATA[
}
}]]></programlisting>
<para>Notice that <interfacename>ApplicationListener</interfacename> is
generically parameterized with the type of your custom event,
<classname>BlackListEvent</classname>. This means that the
<methodname>onApplicationEvent()</methodname> method can remain type-safe,
avoiding any need for downcasting. You may register as many event
listeners as you wish, but note that by default event listeners receive
events synchronously. This means the
<methodname>publishEvent()</methodname> method blocks until all listeners
have finished processing the event. One advantage of this synchronous and
single-threaded approach is that when a listener receives an event, it
operates inside the transaction context of the publisher if a transaction
context is available. If another strategy for event publication becomes
necessary, refer to the JavaDoc for Spring's
<interfacename>ApplicationEventMulticaster</interfacename>
interface.</para>
<para>The following example shows the bean definitions used to
register and configure each of the classes above:</para>
<programlisting language="xml"><![CDATA[<bean id="emailService" class="example.EmailService">
<property name="blackList">
<list>
<value>known.spammer@example.org</value>
<value>known.hacker@example.org</value>
<value>john.doe@example.org</value>
</list>
</property>
</bean>
<bean id="blackListNotifier" class="example.BlackListNotifier">
<property name="notificationAddress" value="blacklist@example.org"/>
</bean>]]></programlisting>
<para>Putting it all together, when the <methodname>sendEmail()</methodname>
method of the <literal>emailService</literal> bean is called, if there are
any emails that should be blacklisted, a custom event of type
<classname>BlackListEvent</classname> is published. The
<literal>blackListNotifier</literal> bean is registered as an
<interfacename>ApplicationListener</interfacename> and thus receives the
<classname>BlackListEvent</classname>, at which point it can notify
appropriate parties.</para>
<note>
<para>Spring's eventing mechanism is designed for simple communication
between Spring beans within the same application context. However, for
more sophisticated enterprise integration needs, the
separately-maintained <ulink
url="http://springsource.org/spring-integration">Spring
Integration</ulink> project provides complete support for building
lightweight, <ulink url="http://www.enterpriseintegrationpatterns.com"
>pattern-oriented</ulink>, event-driven architectures that build upon
the well-known Spring programming model.</para>
</note>
</section>
<section id="context-functionality-resources">
<title>Convenient access to low-level resources</title>
<para>For optimal usage and understanding of application contexts, users
should generally familiarize themselves with Spring's
<interfacename>Resource</interfacename> abstraction, as described in the
chapter <xref linkend="resources"/>.</para>
<para>An application context is a
<interfacename>ResourceLoader</interfacename>, which can be used to load
<interfacename>Resource</interfacename>s. A
<interfacename>Resource</interfacename> is essentially a more feature rich
version of the JDK class <literal>java.net.URL</literal>, in fact, the
implementations of the <interfacename>Resource</interfacename> wrap an
instance of <literal>java.net.URL</literal> where appropriate. A
<interfacename>Resource</interfacename> can obtain low-level resources
from almost any location in a transparent fashion, including from the
classpath, a filesystem location, anywhere describable with a standard
URL, and some other variations. If the resource location string is a
simple path without any special prefixes, where those resources come from
is specific and appropriate to the actual application context type.</para>
<para>You can configure a bean deployed into the application context to
implement the special callback interface,
<interfacename>ResourceLoaderAware</interfacename>, to be automatically
called back at initialization time with the application context itself
passed in as the <interfacename>ResourceLoader</interfacename>. You can
also expose properties of type <interfacename>Resource</interfacename>, to
be used to access static resources; they will be injected into it like any
other properties. You can specify those
<interfacename>Resource</interfacename> properties as simple String paths,
and rely on a special JavaBean
<interfacename>PropertyEditor</interfacename> that is automatically
registered by the context, to convert those text strings to actual
<interfacename>Resource</interfacename> objects when the bean is
deployed.</para>
<para>The location path or paths supplied to an
<interfacename>ApplicationContext</interfacename> constructor are actually
resource strings, and in simple form are treated appropriately to the
specific context implementation.
<classname>ClassPathXmlApplicationContext</classname> treats a simple
location path as a classpath location. You can also use location paths
(resource strings) with special prefixes to force loading of definitions
from the classpath or a URL, regardless of the actual context type.</para>
</section>
<section id="context-create">
<title>Convenient <interfacename>ApplicationContext</interfacename>
instantiation for web applications</title>
<para>You can create <interfacename>ApplicationContext</interfacename>
instances declaratively by using, for example, a
<classname>ContextLoader</classname>. Of course you can also create
<interfacename>ApplicationContext</interfacename> instances
programmatically by using one of the
<interfacename>ApplicationContext</interfacename> implementations.</para>
<para>The <classname>ContextLoader</classname> mechanism comes in two
flavors: the <classname>ContextLoaderListener</classname> and the
<classname>ContextLoaderServlet</classname>. They have the same
functionality but differ in that the listener version is not reliable in
Servlet 2.3 containers. In the Servlet 2.4 specification, Servlet context
listeners must execute immediately after the Servlet context for the web
application is created and is available to service the first request (and
also when the Servlet context is about to be shut down). As such a Servlet
context listener is an ideal place to initialize the Spring
<interfacename>ApplicationContext</interfacename>. All things being equal,
you should probably prefer <classname>ContextLoaderListener</classname>;
for more information on compatibility, have a look at the Javadoc for the
<classname>ContextLoaderServlet</classname>.</para>
<para>You can register an <interfacename>ApplicationContext</interfacename>
using the <classname>ContextLoaderListener</classname> as follows:</para>
<programlisting language="xml">&lt;context-param&gt;
&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
&lt;param-value&gt;/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml&lt;/param-value&gt;
&lt;/context-param&gt;
&lt;listener&gt;
&lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
&lt;/listener&gt;
<lineannotation>&lt;!-- or use the <classname>ContextLoaderServlet</classname> instead of the above listener</lineannotation><emphasis>
&lt;servlet&gt;
&lt;servlet-name&gt;context&lt;/servlet-name&gt;
&lt;servlet-class&gt;org.springframework.web.context.ContextLoaderServlet&lt;/servlet-class&gt;
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
&lt;/servlet&gt;
--</emphasis>&gt;</programlisting>
<para>The listener inspects the <literal>contextConfigLocation</literal>
parameter. If the parameter does not exist, the listener uses
<literal>/WEB-INF/applicationContext.xml</literal> as a default. When the
parameter <emphasis>does</emphasis> exist, the listener separates the
String by using predefined delimiters (comma, semicolon and whitespace)
and uses the values as locations where application contexts will be
searched. Ant-style path patterns are supported as well. Examples are
<literal>/WEB-INF/*Context.xml</literal> for all files with names ending
with "Context.xml", residing in the "WEB-INF" directory, and
<literal>/WEB-INF/**/*Context.xml</literal>, for all such files in any
subdirectory of "WEB-INF".</para>
<para>You can use <classname>ContextLoaderServlet</classname> instead of
<classname>ContextLoaderListener</classname>. The Servlet uses the
<literal>contextConfigLocation</literal> parameter just as the listener
does.</para>
</section>
<section>
<title>Deploying a Spring ApplicationContext as a J2EE RAR file</title>
<para>In Spring 2.5 and later, it is possible to deploy a Spring
ApplicationContext as a RAR file, encapsulating the context and all of its
required bean classes and library JARs in a J2EE RAR deployment unit. This
is the equivalent of bootstrapping a standalone ApplicationContext, just
hosted in J2EE environment, being able to access the J2EE servers
facilities. RAR deployment is a more natural alternative to scenario of
deploying a headless WAR file, in effect, a WAR file without any HTTP
entry points that is used only for bootstrapping a Spring
ApplicationContext in a J2EE environment.</para>
<para>RAR deployment is ideal for application contexts that do not need HTTP
entry points but rather consist only of message endpoints and scheduled
jobs. Beans in such a context can use application server resources such as
the JTA transaction manager and JNDI-bound JDBC DataSources and JMS
ConnectionFactory instances, and may also register with the platform's JMX
server - all through Spring's standard transaction management and JNDI and
JMX support facilities. Application components can also interact with the
application server's JCA WorkManager through Spring's
<interfacename>TaskExecutor</interfacename> abstraction.</para>
<para>Check out the JavaDoc of the <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/jca/context/SpringContextResourceAdapter.html"
>SpringContextResourceAdapter</ulink> class for the configuration details
involved in RAR deployment.</para>
<para><emphasis>For a simple deployment of a Spring ApplicationContext as a
J2EE RAR file:</emphasis> package all application classes into a RAR file,
which is a standard JAR file with a different file extension. Add all
required library JARs into the root of the RAR archive. Add a
"META-INF/ra.xml" deployment descriptor (as shown in
<classname>SpringContextResourceAdapter</classname>s JavaDoc) and the
corresponding Spring XML bean definition file(s) (typically
"META-INF/applicationContext.xml"), and drop the resulting RAR file into
your application server's deployment directory.</para>
<note>
<para>Such RAR deployment units are usually self-contained; they do not
expose components to the outside world, not even to other modules of the
same application. Interaction with a RAR-based ApplicationContext
usually occurs through JMS destinations that it shares with other
modules. A RAR-based ApplicationContext may also, for example, schedule
some jobs, reacting to new files in the file system (or the like). If it
needs to allow synchronous access from the outside, it could for example
export RMI endpoints, which of course may be used by other application
modules on the same machine.</para>
</note>
</section>
</section>

View File

@@ -0,0 +1,665 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="beans-factory-nature">
<title>Customizing the nature of a bean</title>
<section id="beans-factory-lifecycle">
<title>Lifecycle callbacks</title>
<!-- MLP Beverly to review: Old Text: The Spring Framework provides several callback interfaces to
change the behavior of your bean in the container; they include -->
<para>To interact with the container's management of the bean lifecycle, you
can implement the Spring <interfacename>InitializingBean</interfacename>
and <interfacename>DisposableBean</interfacename> interfaces. The
container calls <methodname>afterPropertiesSet()</methodname> for the
former and <methodname>destroy()</methodname> for the latter to allow the
bean to perform certain actions upon initialization and destruction of
your beans. You can also achieve the same integration with the container
without coupling your classes to Spring interfaces through the use of
init-method and destroy method object definition metadata.</para>
<para>Internally, the Spring Framework uses
<interfacename>BeanPostProcessor</interfacename> implementations to
process any callback interfaces it can find and call the appropriate
methods. If you need custom features or other lifecycle behavior Spring
does not offer out-of-the-box, you can implement a
<interfacename>BeanPostProcessor</interfacename> yourself. For more
information, see <xref linkend="beans-factory-extension"/>.</para>
<para>In addition to the initialization and destruction callbacks,
Spring-managed objects may also implement the
<interfacename>Lifecycle</interfacename> interface so that those objects
can participate in the startup and shutdown process as driven by the
container's own lifecycle.</para>
<para>The lifecycle callback interfaces are described in this
section.</para>
<section id="beans-factory-lifecycle-initializingbean">
<title>Initialization callbacks</title>
<para>The
<interfacename>org.springframework.beans.factory.InitializingBean</interfacename>
interface allows a bean to perform initialization work after all
necessary properties on the bean have been set by the container. The
<interfacename>InitializingBean</interfacename> interface specifies a
single method:</para>
<programlisting language="java">void afterPropertiesSet() throws Exception;</programlisting>
<para>It is recommended that you do not use the
<interfacename>InitializingBean</interfacename> interface because it
unnecessarily couples the code to Spring. Alternatively, specify a POJO
initialization method. In the case of XML-based configuration metadata,
you use the <literal>init-method</literal> attribute to specify the name
of the method that has a void no-argument signature. For example, the
following definition:</para>
<programlisting language="xml">&lt;bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/&gt;</programlisting>
<programlisting language="java">public class ExampleBean {
public void init() {
<lineannotation>// do some initialization work</lineannotation>
}
}</programlisting>
<para>...is exactly the same as...</para>
<programlisting language="xml">&lt;bean id="exampleInitBean" class="examples.AnotherExampleBean"/&gt;</programlisting>
<programlisting language="java">public class AnotherExampleBean implements InitializingBean {
public void afterPropertiesSet() {
<lineannotation>// do some initialization work</lineannotation>
}
}</programlisting>
<para>... but does not couple the code to Spring.</para>
</section>
<section id="beans-factory-lifecycle-disposablebean">
<title>Destruction callbacks</title>
<para>Implementing the
<interfacename>org.springframework.beans.factory.DisposableBean</interfacename>
interface allows a bean to get a callback when the container containing
it is destroyed. The <interfacename>DisposableBean</interfacename>
interface specifies a single method:</para>
<programlisting language="java">void destroy() throws Exception;</programlisting>
<para>It is recommended that you do not use the
<interfacename>DisposableBean</interfacename> callback interface because
it unnecessarily couples the code to Spring. Alternatively, specify a
generic method that is supported by bean definitions. With XML-based
configuration metadata, you use the <literal>destroy-method</literal>
attribute on the <literal>&lt;bean/&gt;</literal>. For example, the
following definition:</para>
<programlisting language="xml">&lt;bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/&gt;</programlisting>
<programlisting language="java">public class ExampleBean {
public void cleanup() {
<lineannotation>// do some destruction work (like releasing pooled connections)</lineannotation>
}
}</programlisting>
<para>...is exactly the same as...</para>
<programlisting language="xml">&lt;bean id="exampleInitBean" class="examples.AnotherExampleBean"/&gt;</programlisting>
<programlisting language="java">public class AnotherExampleBean implements DisposableBean {
public void destroy() {
<lineannotation>// do some destruction work (like releasing pooled connections)</lineannotation>
}
}</programlisting>
<para>... but does not couple the code to Spring.</para>
</section>
<section id="beans-factory-lifecycle-default-init-destroy-methods">
<title>Default initialization and destroy methods</title>
<para>When you write initialization and destroy method callbacks that do
not use the Spring-specific
<interfacename>InitializingBean</interfacename> and
<interfacename>DisposableBean</interfacename> callback interfaces, you
typically write methods with names such as <literal>init()</literal>,
<literal>initialize()</literal>, <literal>dispose()</literal>, and so
on. Ideally, the names of such lifecycle callback methods are
standardized across a project so that all developers use the same method
names and ensure consistency.</para>
<para>You can configure the Spring container to <literal>look</literal>
for named initialization and destroy callback method names on
<emphasis>every</emphasis> bean. This means that you, as an application
developer, can write your application classes and use an initialization
callback called <literal>init()</literal>, without having to configure
an <literal>init-method="init"</literal> attribute with each bean
definition. The Spring IoC container calls that method when the bean is
created (and in accordance with the standard lifecycle callback contract
described previously). This feature also enforces a consistent naming
convention for initialization and destroy method callbacks.</para>
<para>Suppose that your initialization callback methods are named
<literal>init()</literal> and destroy callback methods are named
<literal>destroy()</literal>. Your class will resemble the class in the
following example.</para>
<programlisting language="java">public class DefaultBlogService implements BlogService {
private BlogDao blogDao;
public void setBlogDao(BlogDao blogDao) {
this.blogDao = blogDao;
}
<lineannotation>// this is (unsurprisingly) the initialization callback method</lineannotation>
public void init() {
if (this.blogDao == null) {
throw new IllegalStateException("The [blogDao] property must be set.");
}
}
}</programlisting>
<programlisting language="xml">&lt;beans <emphasis role="bold">default-init-method="init"</emphasis>&gt;
&lt;bean id="blogService" class="com.foo.DefaultBlogService"&gt;
&lt;property name="blogDao" ref="blogDao" /&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting>
<para>The presence of the <literal>default-init-method</literal> attribute
on the top-level <literal>&lt;beans/&gt;</literal> element attribute
causes the Spring IoC container to recognize a method called
<literal>init</literal> on beans as the initialization method callback.
When a bean is created and assembled, if the bean class has such a
method, it is invoked at the appropriate time.</para>
<para>You configure destroy method callbacks similarly (in XML, that is)
by using the <literal>default-destroy-method</literal> attribute on the
top-level <literal>&lt;beans/&gt;</literal> element.</para>
<para>Where existing bean classes already have callback methods that are
named at variance with the convention, you can override the default by
specifying (in XML, that is) the method name using the
<literal>init-method</literal> and <literal>destroy-method</literal>
attributes of the &lt;bean/&gt; itself.</para>
<para>The Spring container guarantees that a configured initialization
callback is called immediately after a bean is supplied with all
dependencies. Thus the initialization callback is called on the raw bean
reference, which means that AOP interceptors and so forth are not yet
applied to the bean. A target bean is fully created
<emphasis>first</emphasis>, <emphasis>then</emphasis> an AOP proxy (for
example) with its interceptor chain is applied. If the target bean and
the proxy are defined separately, your code can even interact with the
raw target bean, bypassing the proxy. Hence, it would be inconsistent to
apply the interceptors to the init method, because doing so would couple
the lifecycle of the target bean with its proxy/interceptors and leave
strange semantics when your code interacts directly to the raw target
bean.</para>
</section>
<section id="beans-factory-lifecycle-combined-effects">
<title>Combining lifecycle mechanisms</title>
<para>As of Spring 2.5, you have three options for controlling bean
lifecycle behavior: the <link
linkend="beans-factory-lifecycle-initializingbean"
><interfacename>InitializingBean</interfacename></link> and <link
linkend="beans-factory-lifecycle-disposablebean"
><interfacename>DisposableBean</interfacename></link> callback
interfaces; custom <literal>init()</literal> and
<literal>destroy()</literal> methods; and the <link
linkend="beans-postconstruct-and-predestroy-annotations"
><interfacename>@PostConstruct</interfacename> and
<interfacename>@PreDestroy</interfacename> annotations</link>. You can
combine these mechanisms to control a given bean.</para>
<note>
<para>If multiple lifecycle mechanisms are configured for a bean, and
each mechanism is configured with a different method name, then each
configured method is executed in the order listed below. However, if
the same method name is configured - for example,
<literal>init()</literal> for an initialization method - for more than
one of these lifecycle mechanisms, that method is executed once, as
explained in the preceding section.</para>
</note>
<para>Multiple lifecycle mechanisms configured for the same bean, with
different initialization methods, are called as follows:</para>
<itemizedlist>
<listitem>
<para>Methods annotated with
<interfacename>@PostConstruct</interfacename></para>
</listitem>
<listitem>
<para><literal>afterPropertiesSet()</literal> as defined by the
<interfacename>InitializingBean</interfacename> callback
interface</para>
</listitem>
<listitem>
<para>A custom configured <literal>init()</literal> method</para>
</listitem>
</itemizedlist>
<para>Destroy methods are called in the same order:</para>
<itemizedlist>
<listitem>
<para>Methods annotated with
<interfacename>@PreDestroy</interfacename></para>
</listitem>
<listitem>
<para><literal>destroy()</literal> as defined by the
<interfacename>DisposableBean</interfacename> callback
interface</para>
</listitem>
<listitem>
<para>A custom configured <literal>destroy()</literal> method</para>
</listitem>
</itemizedlist>
</section>
<section id="beans-factory-lifecycle-processor">
<title>Startup and shutdown callbacks</title>
<para>The <interfacename>Lifecycle</interfacename> interface defines the
essential methods for any object that has its own lifecycle requirements
(e.g. starts and stops some background process):</para>
<programlisting language="java">public interface Lifecycle {
void start();
void stop();
boolean isRunning();
}</programlisting>
<para>Any Spring-managed object may implement that interface. Then, when
the ApplicationContext itself starts and stops, it will cascade those
calls to all Lifecycle implementations defined within that context. It
does this by delegating to a
<interfacename>LifecycleProcessor</interfacename>:</para>
<programlisting language="java">public interface LifecycleProcessor extends Lifecycle {
void onRefresh();
void onClose();
}</programlisting>
<para>Notice that the <interfacename>LifecycleProcessor</interfacename> is
itself an extension of the <interfacename>Lifecycle</interfacename>
interface. It also adds two other methods for reacting to the context
being refreshed and closed.</para>
<para>The order of startup and shutdown invocations can be important. If a
"depends-on" relationship exists between any two objects, the dependent
side will start <emphasis>after</emphasis> its dependency, and it will
stop <emphasis>before</emphasis> its dependency. However, at times the
direct dependencies are unknown. You may only know that objects of a
certain type should start prior to objects of another type. In those
cases, the <interfacename>SmartLifecycle</interfacename> interface
defines another option, namely the <methodname>getPhase()</methodname>
method as defined on its super-interface,
<interfacename>Phased</interfacename>.</para>
<programlisting language="java">public interface Phased {
int getPhase();
}
public interface SmartLifecycle extends Lifecycle, Phased {
boolean isAutoStartup();
void stop(Runnable callback);
}</programlisting>
<para>When starting, the objects with the lowest phase start first, and
when stopping, the reverse order is followed. Therefore, an object that
implements <interfacename>SmartLifecycle</interfacename> and whose
getPhase() method returns <literal>Integer.MIN_VALUE</literal> would be
among the first to start and the last to stop. At the other end of the
spectrum, a phase value of <literal>Integer.MAX_VALUE</literal> would
indicate that the object should be started last and stopped first
(likely because it depends on other processes to be running). When
considering the phase value, it's also important to know that the
default phase for any "normal" <interfacename>Lifecycle</interfacename>
object that does not implement
<interfacename>SmartLifecycle</interfacename> would be 0. Therefore, any
negative phase value would indicate that an object should start before
those standard components (and stop after them), and vice versa for any
positive phase value.</para>
<para>As you can see the stop method defined by
<interfacename>SmartLifecycle</interfacename> accepts a callback. Any
implementation <emphasis>must</emphasis> invoke that callback's run()
method after that implementation's shutdown process is complete. That
enables asynchronous shutdown where necessary since the default
implementation of the <interfacename>LifecycleProcessor</interfacename>
interface, <classname>DefaultLifecycleProcessor</classname>, will wait
up to its timeout value for the group of objects within each phase to
invoke that callback. The default per-phase timeout is 30 seconds. You
can override the default lifecycle processor instance by defining a bean
named "lifecycleProcessor" within the context. If you only want to
modify the timeout, then defining the following would be
sufficient:</para>
<programlisting language="xml">&lt;bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor"&gt;
&lt;!-- timeout value in milliseconds --&gt;
&lt;property name="timeoutPerShutdownPhase" value="10000"/&gt;
&lt;/bean&gt;</programlisting>
<para>As mentioned, the <interfacename>LifecycleProcessor</interfacename>
interface defines callback methods for the refreshing and closing of the
context as well. The latter will simply drive the shutdown process as if
stop() had been called explicitly, but it will happen when the context
is closing. The 'refresh' callback on the other hand enables another
feature of <interfacename>SmartLifecycle</interfacename> beans. When the
context is refreshed (after all objects have been instantiated and
initialized), that callback will be invoked, and at that point the
default lifecycle processor will check the boolean value returned by
each <interfacename>SmartLifecycle</interfacename> object's
<methodname>isAutoStartup()</methodname> method. If "true", then that
object will be started at that point rather than waiting for an explicit
invocation of the context's or its own start() method (unlike the
context refresh, the context start does not happen automatically for a
standard context implementation). The "phase" value as well as any
"depends-on" relationships will determine the startup order in the same
way as described above.</para>
</section>
<section id="beans-factory-shutdown">
<title>Shutting down the Spring IoC container gracefully in non-web
applications</title>
<note>
<para>This section applies only to non-web applications. Spring's
web-based <interfacename>ApplicationContext</interfacename>
implementations already have code in place to shut down the Spring IoC
container gracefully when the relevant web application is shut
down.</para>
</note>
<para>If you are using Spring's IoC container in a non-web application
environment; for example, in a rich client desktop environment; you
register a shutdown hook with the JVM. Doing so ensures a graceful
shutdown and calls the relevant destroy methods on your singleton beans
so that all resources are released. Of course, you must still configure
and implement these destroy callbacks correctly.</para>
<para>To register a shutdown hook, you call the
<methodname>registerShutdownHook()</methodname> method that is declared
on the <classname>AbstractApplicationContext</classname> class:</para>
<programlisting language="java">import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public final class Boot {
public static void main(final String[] args) throws Exception {
AbstractApplicationContext ctx
= new ClassPathXmlApplicationContext(new String []{"beans.xml"});
<lineannotation>// add a shutdown hook for the above context... </lineannotation>
ctx.registerShutdownHook();
<lineannotation>// app runs here...</lineannotation>
<lineannotation>// main method exits, hook is called prior to the app shutting down...</lineannotation>
}
}</programlisting>
</section>
</section>
<section id="beans-factory-aware">
<title><interfacename>ApplicationContextAware</interfacename> and
<interfacename>BeanNameAware</interfacename></title>
<para>When an <interfacename>ApplicationContext</interfacename> creates a
class that implements the
<interfacename>org.springframework.context.ApplicationContextAware</interfacename>
interface, the class is provided with a reference to that
<interfacename>ApplicationContext</interfacename>.</para>
<programlisting language="java">public interface ApplicationContextAware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}</programlisting>
<para>Thus beans can manipulate programmatically the
<interfacename>ApplicationContext</interfacename> that created them,
through the <interfacename>ApplicationContext</interfacename> interface,
or by casting the reference to a known subclass of this interface, such as
<classname>ConfigurableApplicationContext</classname>, which exposes
additional functionality. One use would be the programmatic retrieval of
other beans. Sometimes this capability is useful; however, in general you
should avoid it, because it couples the code to Spring and does not follow
the Inversion of Control style, where collaborators are provided to beans
as properties. Other methods of the ApplicationContext provide access to
file resources, publishing application events, and accessing a
MessageSource. These additional features are described in <xref
linkend="context-introduction"/></para>
<para>As of Spring 2.5, autowiring is another alternative to obtain
reference to the <interfacename>ApplicationContext</interfacename>. The
"traditional" <literal>constructor</literal> and <literal>byType</literal>
autowiring modes (as described in <xref linkend="beans-factory-autowire"
/>) can provide a dependency of type
<interfacename>ApplicationContext</interfacename> for a constructor
argument or setter method parameter, respectively. For more flexibility,
including the ability to autowire fields and multiple parameter methods,
use the new annotation-based autowiring features. If you do, the
<interfacename>ApplicationFactory</interfacename> is autowired into a
field, constructor argument, or method parameter that is expecting the
<interfacename>BeanFactory</interfacename> type if the field, constructor,
or method in question carries the
<interfacename>@Autowired</interfacename> annotation. For more
information, see <xref linkend="beans-autowired-annotation"/>.</para>
<para>When an ApplicationContext creates a class that implements the
<interfacename>org.springframework.beans.factory.BeanNameAware</interfacename>
interface, the class is provided with a reference to the name defined in
its associated object definition.</para>
<programlisting language="java">public interface BeanNameAware {
void setBeanName(string name) throws BeansException;
}</programlisting>
<para>The callback is invoked after population of normal bean properties but
before an initialization callback such as
<interfacename>InitializingBean</interfacename>s
<emphasis>afterPropertiesSet</emphasis> or a custom init-method.</para>
</section>
<section id="aware-list">
<title>Other <interfacename>Aware</interfacename> interfaces</title>
<para>Besides <interfacename>ApplicationContextAware</interfacename> and
<interfacename>BeanNameAware</interfacename> discussed above, Spring
offers a range of
<emphasis><interfacename>Aware</interfacename></emphasis> interfaces that
allow beans to indicate to the container that they require a certain
<emphasis>infrastructure</emphasis> dependency. The most important
<interfacename>Aware</interfacename> interfaces are summarized below - as
a general rule, the name is a good indication of the dependency
type:</para>
<table id="beans-factory-nature-aware-list" pgwide="1">
<title><interfacename>Aware</interfacename> interfaces</title>
<tgroup cols="3">
<colspec align="left"/>
<thead>
<row>
<entry>Name</entry>
<entry>Injected Dependency</entry>
<entry>Explained in...</entry>
</row>
</thead>
<tbody>
<row>
<entry><para><classname>ApplicationContextAware</classname></para></entry>
<entry><para>Declaring
<interfacename>ApplicationContext</interfacename></para></entry>
<entry><para><xref linkend="beans-factory-aware"/></para></entry>
</row>
<row>
<entry><para><classname>ApplicationEventPublisherAware</classname></para></entry>
<entry><para>Event publisher of the enclosing
<interfacename>ApplicationContext</interfacename></para></entry>
<entry><para><xref linkend="context-introduction"/></para></entry>
</row>
<row>
<entry><para><classname>BeanClassLoaderAware</classname></para></entry>
<entry><para>Class loader used to load the bean
classes.</para></entry>
<entry><para><xref linkend="beans-factory-class"/></para></entry>
</row>
<row>
<entry><para><classname>BeanFactoryAware</classname></para></entry>
<entry><para>Declaring
<interfacename>BeanFactory</interfacename></para></entry>
<entry><para><xref linkend="beans-factory-aware"/></para></entry>
</row>
<row>
<entry><para><classname>BeanNameAware</classname></para></entry>
<entry><para>Name of the declaring bean</para></entry>
<entry><para><xref linkend="beans-factory-aware"/></para></entry>
</row>
<row>
<entry><para><classname>BootstrapContextAware</classname></para></entry>
<entry><para>Resource adapter
<interfacename>BootstrapContext</interfacename> the container runs
in. Typically available only in JCA aware
<interfacename>ApplicationContext</interfacename>s</para></entry>
<entry><para><xref linkend="cci"/></para></entry>
</row>
<row>
<entry><para><classname>LoadTimeWeaverAware</classname></para></entry>
<entry><para>Defined <emphasis>weaver</emphasis> for processing
class definition at load time</para></entry>
<entry><para><xref linkend="aop-aj-ltw"/></para></entry>
</row>
<row>
<entry><para><classname>MessageSourceAware</classname></para></entry>
<entry><para>Configured strategy for resolving messages (with
support for parametrization and
internationalization)</para></entry>
<entry><para><xref linkend="context-introduction"/></para></entry>
</row>
<row>
<entry><para><classname>NotificationPublisherAware</classname></para></entry>
<entry><para>Spring JMX notification publisher</para></entry>
<entry><para><xref linkend="jmx-notifications"/></para></entry>
</row>
<row>
<entry><para><classname>PortletConfigAware</classname></para></entry>
<entry><para>Current <interfacename>PortletConfig</interfacename>
the container runs in. Valid only in a web-aware Spring
<interfacename>ApplicationContext</interfacename></para></entry>
<entry><para><xref linkend="portlet"/></para></entry>
</row>
<row>
<entry><para><classname>PortletContextAware</classname></para></entry>
<entry><para>Current <interfacename>PortletContext</interfacename>
the container runs in. Valid only in a web-aware Spring
<interfacename>ApplicationContext</interfacename></para></entry>
<entry><para><xref linkend="portlet"/></para></entry>
</row>
<row>
<entry><para><classname>ResourceLoaderAware</classname></para></entry>
<entry><para>Configured loader for low-level access to
resources</para></entry>
<entry><para><xref linkend="resources"/></para></entry>
</row>
<row>
<entry><para><classname>ServletConfigAware</classname></para></entry>
<entry><para>Current <interfacename>ServletConfig</interfacename>
the container runs in. Valid only in a web-aware Spring
<interfacename>ApplicationContext</interfacename></para></entry>
<entry><para><xref linkend="mvc"/></para></entry>
</row>
<row>
<entry><para><classname>ServletContextAware</classname></para></entry>
<entry><para>Current <interfacename>ServletContext</interfacename>
the container runs in. Valid only in a web-aware Spring
<interfacename>ApplicationContext</interfacename></para></entry>
<entry><para><xref linkend="mvc"/></para></entry>
</row>
</tbody>
</tgroup>
</table>
<para>Note again that usage of these interfaces ties your code to the Spring
API and does not follow the Inversion of Control style. As such, they are
recommended for infrastructure beans that require programmatic access to
the container.</para>
</section>
</section>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,557 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="beans-factory-extension">
<title>Container Extension Points</title>
<para>Typically, an application developer does not need to subclass
<interfacename>ApplicationContext</interfacename> implementation classes.
Instead, the Spring IoC container can be extended by plugging in
implementations of special integration interfaces. The next few sections
describe these integration interfaces.</para>
<section id="beans-factory-extension-bpp">
<title>Customizing beans using a
<interfacename>BeanPostProcessor</interfacename></title>
<para>The <interfacename>BeanPostProcessor</interfacename> interface defines
<firstterm>callback methods</firstterm> that you can implement to provide
your own (or override the container's default) instantiation logic,
dependency-resolution logic, and so forth. If you want to implement some
custom logic after the Spring container finishes instantiating,
configuring, and initializing a bean, you can plug in one or
more <interfacename>BeanPostProcessor</interfacename>
implementations.</para>
<para>You can configure multiple <literal>BeanPostProcessor</literal>
instances, and you can control the order in which these
<literal>BeanPostProcessor</literal>s execute by setting the
<literal>order</literal> property. You can set this property only if the
<interfacename>BeanPostProcessor</interfacename> implements the
<interfacename>Ordered</interfacename> interface; if you write your own
<interfacename>BeanPostProcessor</interfacename> you should consider
implementing the <interfacename>Ordered</interfacename> interface too. For
further details, consult the Javadoc for the
<interfacename>BeanPostProcessor</interfacename> and
<interfacename>Ordered</interfacename> interfaces. See also the note below on
<link linkend="beans-factory-programmatically-registering-beanpostprocessors">
programmatic registration of <interfacename>BeanPostProcessors</interfacename>
</link></para>
<note>
<para><literal>BeanPostProcessor</literal>s operate on bean (or object)
<emphasis>instances</emphasis>; that is to say, the Spring IoC container
instantiates a bean instance and <emphasis>then</emphasis>
<literal>BeanPostProcessor</literal>s do their work.</para>
<para><literal>BeanPostProcessor</literal>s are scoped
<emphasis>per-container</emphasis>. This is only relevant if you are
using container hierarchies. If you define a
<interfacename>BeanPostProcessor</interfacename> in one container, it
will <emphasis>only</emphasis> post-process the beans in that
container. In other words, beans that are defined in one container are not
post-processed by a <literal>BeanPostProcessor</literal> defined in another
container, even if both containers are part of the same hierarchy.</para>
<para>To change the actual bean definition (i.e., the
<emphasis>blueprint</emphasis> that defines the bean), you instead need to use a
<interfacename>BeanFactoryPostProcessor</interfacename> as described
in <xref linkend="beans-factory-extension-factory-postprocessors"
/>.</para>
</note>
<para>The
<interfacename>org.springframework.beans.factory.config.BeanPostProcessor</interfacename>
interface consists of exactly two callback methods. When such a class is
registered as a post-processor with the container, for each bean instance
that is created by the container, the post-processor gets a callback from
the container both <emphasis>before</emphasis> container initialization
methods (such as InitializingBean's <emphasis>afterPropertiesSet()</emphasis>
and any declared init method) are called as well as <emphasis>after</emphasis>
any bean initialization callbacks. The post-processor can take
any action with the bean instance, including ignoring the callback
completely. A bean post-processor typically checks for callback
interfaces or may wrap a bean with a proxy. Some Spring AOP
infrastructure classes are implemented as bean post-processors in order
to provide proxy-wrapping logic.</para>
<para>An <interfacename>ApplicationContext</interfacename>
<emphasis>automatically detects</emphasis> any beans that are defined in
the configuration metadata which implement the
<interfacename>BeanPostProcessor</interfacename> interface. The
<interfacename>ApplicationContext</interfacename> registers these beans as
post-processors so that they can be called later upon bean creation.
Bean post-processors can be deployed in the container just like any other
beans.</para>
<anchor id="beans-factory-programmatically-registering-beanpostprocessors"/>
<note>
<title>Programmatically registering <interfacename>BeanPostProcessors
</interfacename></title>
<para>
While the recommended approach for <interfacename>BeanPostProcessor
</interfacename> registration is through <interfacename>ApplicationContext
</interfacename> auto-detection (as described above), it is also
possible to register them <emphasis>programmatically</emphasis>
against an <interfacename>ApplicationContext</interfacename> using the
<methodname>addBeanPostProcessor</methodname> method. This can be useful
when needing to evaluate conditional logic before registration, or even
for copying bean post processors across contexts in a hierarchy. Note
however that <interfacename>BeanPostProcessors</interfacename> added
programmatically <emphasis>do not respect the <interfacename>Ordered
</interfacename> interface</emphasis>. Here it is the <emphasis>order of
registration</emphasis> that dictates the order of execution. Note also
that <interfacename>BeanPostProcessors</interfacename> registered
programmatically are always processed before those registered through
auto-detection, regardless of any explicit ordering.
</para>
</note>
<note>
<title><interfacename>BeanPostProcessors</interfacename> and AOP
auto-proxying</title>
<para>Classes that implement the
<interfacename>BeanPostProcessor</interfacename> interface are
<emphasis>special</emphasis> and are treated differently by the
container. All <interfacename>BeanPostProcessors</interfacename>
<emphasis>and beans that they reference directly</emphasis> are
instantiated on startup, as part of the special startup phase of the
<interfacename>ApplicationContext</interfacename>. Next, all
<interfacename>BeanPostProcessors</interfacename> are registered in a
sorted fashion and applied to all further beans in the container.
Because AOP auto-proxying is implemented as a
<interfacename>BeanPostProcessor</interfacename> itself, neither
<interfacename>BeanPostProcessors</interfacename> nor the beans they reference
directly are eligible for auto-proxying, and thus do not have aspects woven
into them.</para>
<para>For any such bean, you should see an informational log message:
<quote><emphasis>Bean foo is not eligible for getting processed by all
BeanPostProcessor interfaces (for example: not eligible for
auto-proxying)</emphasis></quote>.</para>
</note>
<para>The following examples show how to write, register, and use
<literal>BeanPostProcessors</literal> in an
<interfacename>ApplicationContext</interfacename>.</para>
<section id="beans-factory-extension-bpp-examples-hw">
<title>Example: Hello World,
<interfacename>BeanPostProcessor</interfacename>-style</title>
<para>This first example illustrates basic usage. The example shows a
custom <interfacename>BeanPostProcessor</interfacename> implementation
that invokes the <methodname>toString()</methodname> method of each bean
as it is created by the container and prints the resulting string to the
system console.</para>
<para>Find below the custom
<interfacename>BeanPostProcessor</interfacename> implementation class
definition:</para>
<programlisting language="java">package scripting;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.BeansException;
public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor {
<lineannotation>// simply return the instantiated bean as-is</lineannotation>
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return bean; <lineannotation>// we could potentially return <emphasis>any</emphasis> object reference here...</lineannotation>
}
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("Bean '" + beanName + "' created : " + bean.toString());
return bean;
}
}</programlisting>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/lang
http://www.springframework.org/schema/lang/spring-lang-3.0.xsd"&gt;
&lt;lang:groovy id="messenger"
script-source="classpath:org/springframework/scripting/groovy/Messenger.groovy"&gt;
&lt;lang:property name="message" value="Fiona Apple Is Just So Dreamy."/&gt;
&lt;/lang:groovy&gt;
<lineannotation>&lt;!--
when the above bean (messenger) is instantiated, this custom
<interfacename>BeanPostProcessor</interfacename> implementation will output the fact to the system console
--&gt;</lineannotation>
&lt;bean class="scripting.InstantiationTracingBeanPostProcessor"/&gt;
&lt;/beans&gt;</programlisting>
<para>Notice how the
<classname>InstantiationTracingBeanPostProcessor</classname> is simply
defined. It does not even have a name, and because it is a bean it can
be dependency-injected just like any other bean. (The preceding
configuration also defines a bean that is backed by a Groovy script. The
Spring 2.0 dynamic language support is detailed in the chapter entitled
<xref linkend="dynamic-language"/>.)</para>
<para>The following simple Java application executes the preceding code and
configuration:</para>
<programlisting language="java">import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scripting.Messenger;
public final class Boot {
public static void main(final String[] args) throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext("scripting/beans.xml");
Messenger messenger = (Messenger) ctx.getBean("messenger");
System.out.println(messenger);
}
}</programlisting>
<para>The output of the preceding application resembles the
following:</para>
<programlisting>Bean 'messenger' created : org.springframework.scripting.groovy.GroovyMessenger@272961
org.springframework.scripting.groovy.GroovyMessenger@272961</programlisting>
</section>
<section id="beans-factory-extension-bpp-examples-rabpp">
<title>Example: The
<classname>RequiredAnnotationBeanPostProcessor</classname></title>
<para>Using callback interfaces or annotations in conjunction with a
custom <interfacename>BeanPostProcessor</interfacename> implementation
is a common means of extending the Spring IoC container. An example is
Spring's <classname>RequiredAnnotationBeanPostProcessor</classname> &mdash; a
<interfacename>BeanPostProcessor</interfacename> implementation that
ships with the Spring distribution which ensures that JavaBean
properties on beans that are marked with an (arbitrary) annotation are
actually (configured to be) dependency-injected with a value.</para>
</section>
</section>
<section id="beans-factory-extension-factory-postprocessors">
<title>Customizing configuration metadata with a
<interfacename>BeanFactoryPostProcessor</interfacename></title>
<para>The next extension point that we will look at is the
<interfacename>org.springframework.beans.factory.config.BeanFactoryPostProcessor</interfacename>.
The semantics of this interface are similar to those of the
<interfacename>BeanPostProcessor</interfacename>, with one major
difference: <literal>BeanFactoryPostProcessor</literal>s operate on the
<emphasis>bean configuration metadata</emphasis>; that is, the Spring IoC
container allows <literal>BeanFactoryPostProcessors</literal> to read the
configuration metadata and potentially change it
<emphasis>before</emphasis> the container instantiates any beans other
than <literal>BeanFactoryPostProcessors</literal>.</para>
<para>You can configure multiple
<literal>BeanFactoryPostProcessors</literal>, and you can control the order in
which these <literal>BeanFactoryPostProcessors</literal> execute by
setting the <literal>order</literal> property. However, you can only set
this property if the
<interfacename>BeanFactoryPostProcessor</interfacename> implements the
<interfacename>Ordered</interfacename> interface. If you write your own
<interfacename>BeanFactoryPostProcessor</interfacename>, you should
consider implementing the <interfacename>Ordered</interfacename> interface
too. Consult the Javadoc for the
<interfacename>BeanFactoryPostProcessor</interfacename> and
<interfacename>Ordered</interfacename> interfaces for more details.</para>
<note>
<para>If you want to change the actual bean <emphasis>instances</emphasis>
(i.e., the objects that are created from the configuration metadata), then you
instead need to use a <interfacename>BeanPostProcessor</interfacename>
(described above in <xref linkend="beans-factory-extension-bpp"/>). While
it is technically possible to work with bean instances within a
<interfacename>BeanFactoryPostProcessor</interfacename> (e.g., using
<methodname>BeanFactory.getBean()</methodname>), doing so causes
premature bean instantiation, violating the standard container lifecycle.
This may cause negative side effects such as bypassing bean post
processing.</para>
<para>Also, <literal>BeanFactoryPostProcessors</literal> are scoped
<emphasis>per-container</emphasis>. This is only relevant if you are
using container hierarchies. If you define a
<interfacename>BeanFactoryPostProcessor</interfacename> in one
container, it will <emphasis>only</emphasis> be applied to the bean
definitions in that container. Bean definitions in one container
will not be post-processed by
<literal>BeanFactoryPostProcessors</literal> in another container, even
if both containers are part of the same hierarchy.</para>
</note>
<para>A bean factory post-processor is executed automatically when it is
declared inside an <interfacename>ApplicationContext</interfacename>,
in order to apply changes to the configuration metadata that define the
container. Spring includes a number of predefined bean factory
post-processors, such as <classname>PropertyOverrideConfigurer</classname>
and <classname>PropertyPlaceholderConfigurer</classname>. A custom
<interfacename>BeanFactoryPostProcessor</interfacename> can also be used,
for example, to register custom property editors.</para>
<anchor id="beans-factory-autodetect-beanfactorypostprocessors"/>
<para>An <interfacename>ApplicationContext</interfacename> automatically
detects any beans that are deployed into it that implement the
<interfacename>BeanFactoryPostProcessor</interfacename> interface. It
uses these beans as bean factory post-processors, at the
appropriate time. You can deploy these post-processor beans as you
would any other bean.</para>
<note>
<para>As with <interfacename>BeanPostProcessor</interfacename>s, you typically
do not want to configure <interfacename>BeanFactoryPostProcessor</interfacename>s
for lazy initialization. If no other bean references a
<interfacename>Bean(Factory)PostProcessor</interfacename>,
that post-processor will not get instantiated at all. Thus, marking it for
lazy initialization will be ignored, and the
<interfacename>Bean(Factory)PostProcessor</interfacename> will be
instantiated eagerly even if you set the <literal>default-lazy-init</literal>
attribute to <literal>true</literal> on the declaration of your
<code>&lt;beans /&gt;</code> element.</para>
</note>
<section id="beans-factory-placeholderconfigurer">
<title>Example: the
<interfacename>PropertyPlaceholderConfigurer</interfacename></title>
<para>You use the
<interfacename>PropertyPlaceholderConfigurer</interfacename> to
externalize property values from a bean definition in a separate
file using the standard Java <classname>Properties</classname> format.
Doing so enables the person deploying an application to customize
environment-specific properties such as database URLs and passwords,
without the complexity or risk of modifying the main XML definition file
or files for the container.</para>
<!-- MLP: Beverly to review following 2 paragraphs -->
<para>Consider the following XML-based configuration metadata fragment,
where a <interfacename>DataSource</interfacename> with placeholder
values is defined. The example shows properties configured from an
external <classname>Properties</classname> file. At runtime, a
<classname>PropertyPlaceholderConfigurer</classname> is applied to the
metadata that will replace some properties of the DataSource. The values
to replace are specified as <emphasis>placeholders</emphasis> of the form
${property-name} which follows the Ant / log4j / JSP EL style.</para>
<programlisting language="xml">&lt;bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"&gt;
&lt;property name="locations" value="classpath:com/foo/jdbc.properties"/&gt;
&lt;/bean&gt;
&lt;bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource"&gt;
&lt;property name="driverClassName" value="<emphasis role="bold">${jdbc.driverClassName}</emphasis>"/&gt;
&lt;property name="url" value="<emphasis role="bold">${jdbc.url}</emphasis>"/&gt;
&lt;property name="username" value="<emphasis role="bold">${jdbc.username}</emphasis>"/&gt;
&lt;property name="password" value="<emphasis role="bold">${jdbc.password}</emphasis>"/&gt;
&lt;/bean&gt;</programlisting>
<para>The actual values come from another file in the standard Java
<classname>Properties</classname> format:</para>
<programlisting>jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://production:9002
jdbc.username=sa
jdbc.password=root</programlisting>
<para>Therefore, the string <literal>${jdbc.username}</literal> is replaced
at runtime with the value 'sa', and the same applies for other placeholder
values that match keys in the properties file. The
<classname>PropertyPlaceholderConfigurer</classname> checks for
placeholders in most properties and attributes of a bean definition.
Furthermore, the placeholder prefix and suffix can be customized.</para>
<para>With the <literal>context</literal> namespace introduced in Spring
2.5, it is possible to configure property placeholders with a dedicated
configuration element. One or more locations can be provided as a
comma-separated list in the <literal>location</literal>
attribute.</para>
<programlisting language="xml">&lt;context:property-placeholder location="classpath:com/foo/jdbc.properties"/&gt;</programlisting>
<para>The <classname>PropertyPlaceholderConfigurer</classname> not only
looks for properties in the <classname>Properties</classname> file
you specify. By default it also checks against the Java
<classname>System</classname> properties if it cannot find a property
in the specified properties files. You can customize this behavior by setting the
<literal>systemPropertiesMode</literal> property of the configurer with
one of the following three supported integer values:
<!--What property is it overriding and what will replace the overridden value?-->
<!--MLP: override a value in the Properties with one from the 'systemProperties' -->
</para>
<itemizedlist>
<listitem>
<para><emphasis>never</emphasis> (0): Never check system properties</para>
</listitem>
<listitem>
<para><emphasis>fallback</emphasis> (1): Check system properties if not resolvable in the specified properties files. This is the default.</para>
</listitem>
<listitem>
<para><emphasis>override</emphasis> (2): Check system properties first, before trying the specified properties files. This allows system properties to override any other property source.</para>
</listitem>
</itemizedlist>
<para>
Consult the Javadoc for the <classname>PropertyPlaceholderConfigurer</classname>
for more information.</para>
<tip>
<title>Class name substitution</title>
<para>You can use the
<classname>PropertyPlaceholderConfigurer</classname> to substitute
class names, which is sometimes useful when you have to pick a
particular implementation class at runtime. For example:</para>
<programlisting language="xml">&lt;bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"&gt;
&lt;property name="locations"&gt;
&lt;value&gt;classpath:com/foo/strategy.properties&lt;/value&gt;
&lt;/property&gt;
&lt;property name="properties"&gt;
&lt;value&gt;custom.strategy.class=com.foo.DefaultStrategy&lt;/value&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="serviceStrategy" class="${custom.strategy.class}"/&gt;</programlisting>
<para>If the class cannot be resolved at runtime to a valid class,
resolution of the bean fails when it is about to be created, which is
during the <methodname>preInstantiateSingletons()</methodname> phase
of an <interfacename>ApplicationContext</interfacename> for a
non-lazy-init bean.</para>
</tip>
</section>
<section id="beans-factory-overrideconfigurer">
<title>Example: the
<classname>PropertyOverrideConfigurer</classname></title>
<para>The <classname>PropertyOverrideConfigurer</classname>, another bean
factory post-processor, resembles the
<interfacename>PropertyPlaceholderConfigurer</interfacename>, but unlike
the latter, the original definitions can have default values or no
values at all for bean properties. If an overriding
<classname>Properties</classname> file does not have an entry for a
certain bean property, the default context definition is used.</para>
<para>Note that the bean definition is <emphasis>not</emphasis> aware of
being overridden, so it is not immediately obvious from the XML
definition file that the override configurer is being used. In case of
multiple <classname>PropertyOverrideConfigurer</classname> instances
that define different values for the same bean property, the last one
wins, due to the overriding mechanism.</para>
<para>Properties file configuration lines take this format:</para>
<programlisting language="java">beanName.property=value</programlisting>
<para>For example:</para>
<programlisting language="java">dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql:mydb</programlisting>
<para>This example file can be used with a container definition that
contains a bean called <emphasis>dataSource</emphasis>, which has
<emphasis>driver</emphasis> and <emphasis>url</emphasis>
properties.</para>
<para>Compound property names are also supported, as long as every
component of the path except the final property being overridden is
already non-null (presumably initialized by the constructors). In this
example...</para>
<programlisting language="java">foo.fred.bob.sammy=123</programlisting>
<para>... the <literal>sammy</literal> property of the
<literal>bob</literal> property of the <literal>fred</literal> property
of the <literal>foo</literal> bean is set to the scalar value
<literal>123</literal>.</para>
<note>
<para>Specified override values are always <emphasis>literal</emphasis>
values; they are not translated into bean references. This convention
also applies when the original value in the XML bean definition
specifies a bean reference.</para>
</note>
<para>With the <literal>context</literal> namespace introduced in Spring
2.5, it is possible to configure property overriding with a dedicated
configuration element:</para>
<programlisting language="xml">&lt;context:property-override location="classpath:override.properties"/&gt;</programlisting>
</section>
</section>
<section id="beans-factory-extension-factorybean">
<title>Customizing instantiation logic with a
<interfacename>FactoryBean</interfacename></title>
<para>Implement the
<interfacename>org.springframework.beans.factory.FactoryBean</interfacename>
interface for objects that <emphasis>are themselves
factories</emphasis>.</para>
<para>The <interfacename>FactoryBean</interfacename> interface is a point of
pluggability into the Spring IoC container's instantiation logic. If you
have complex initialization code that is better expressed in Java as
opposed to a (potentially) verbose amount of XML, you can create your own
<interfacename>FactoryBean</interfacename>, write the complex
initialization inside that class, and then plug your custom
<interfacename>FactoryBean</interfacename> into the container.</para>
<para>The <interfacename>FactoryBean</interfacename> interface provides
three methods:</para>
<itemizedlist>
<listitem>
<para><methodname>Object getObject()</methodname>: returns an instance
of the object this factory creates. The instance can possibly be
shared, depending on whether this factory returns singletons or
prototypes.</para>
</listitem>
<listitem>
<para><methodname>boolean isSingleton()</methodname>: returns
<literal>true</literal> if this
<interfacename>FactoryBean</interfacename> returns singletons,
<literal>false</literal> otherwise.</para>
</listitem>
<listitem>
<para><methodname>Class getObjectType()</methodname>: returns the object
type returned by the <methodname>getObject()</methodname> method or
<literal>null</literal> if the type is not known in advance.</para>
</listitem>
</itemizedlist>
<para>The <interfacename>FactoryBean</interfacename> concept and interface
is used in a number of places within the Spring Framework; more than 50
implementations of the <interfacename>FactoryBean</interfacename>
interface ship with Spring itself.</para>
<para>When you need to ask a container for an actual
<interfacename>FactoryBean</interfacename> instance itself instead of the bean
it produces, preface the bean's id with the ampersand symbol
(<literal>&amp;</literal>) when calling the
<methodname>getBean()</methodname> method of the
<interfacename>ApplicationContext</interfacename>. So for a given
<interfacename>FactoryBean</interfacename> with an id of
<literal>myBean</literal>, invoking <literal>getBean("myBean")</literal>
on the container returns the product of the
<interfacename>FactoryBean</interfacename>; whereas, invoking
<literal>getBean("&amp;myBean")</literal> returns the
<interfacename>FactoryBean</interfacename> instance
itself.<!--Moved ApplicationContext section to almost the end of the doc, right before BeanFactory and renamed it Additional Capabilities of.--></para>
</section>
</section>

View File

@@ -0,0 +1,908 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="beans-java">
<title>Java-based container configuration</title>
<section id="beans-java-basic-concepts">
<title>Basic concepts: <literal>@Configuration</literal> and
<literal>@Bean</literal></title>
<para>The central artifact in Spring's new Java-configuration support is the
<interfacename>@Configuration</interfacename>-annotated class. These
classes consist principally of
<interfacename>@Bean</interfacename>-annotated methods that define
instantiation, configuration, and initialization logic for objects to be
managed by the Spring IoC container.</para>
<para>Annotating a class with the
<interfacename>@Configuration</interfacename> indicates that the class can
be used by the Spring IoC container as a source of bean definitions. The
simplest possible <interfacename>@Configuration</interfacename> class
would read as follows:
<programlisting language="java">@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}</programlisting></para>
<para>For those more familiar with Spring <literal>&lt;beans/&gt;</literal>
XML, the <literal>AppConfig</literal> class above would be equivalent to:
<programlisting language="xml">&lt;beans&gt;
&lt;bean id="myService" class="com.acme.services.MyServiceImpl"/&gt;
&lt;/beans&gt;</programlisting>
As you can see, the <literal>@Bean</literal> annotation plays the same
role as the <literal>&lt;bean/&gt;</literal> element. The
<literal>@Bean</literal> annotation will be discussed in depth in the
sections below. First, however, we'll cover the various ways of creating a
spring container using Java-based configuration.</para>
</section>
<section id="beans-java-instantiating-container">
<title>Instantiating the Spring container using
<literal>AnnotationConfigApplicationContext</literal></title>
<para>The sections below document Spring's
<literal>AnnotationConfigApplicationContext</literal>, new in Spring 3.0.
This versatile <literal>ApplicationContext</literal> implementation is
capable of accepting not only <literal>@Configuration</literal> classes as
input, but also plain <literal>@Component</literal> classes and classes
annotated with JSR-330 metadata.</para>
<para>When <literal>@Configuration</literal> classes are provided as input,
the <literal>@Configuration</literal> class itself is registered as a bean
definition, and all declared <literal>@Bean</literal> methods within the
class are also registered as bean definitions.</para>
<para>When <literal>@Component</literal> and JSR-330 classes are provided,
they are registered as bean definitions, and it is assumed that DI
metadata such as <literal>@Autowired</literal> or
<literal>@Inject</literal> are used within those classes where
necessary.</para>
<section id="beans-java-instantiating-container-contstructor">
<title>Simple construction</title>
<para>In much the same way that Spring XML files are used as input when
instantiating a <literal>ClassPathXmlApplicationContext</literal>,
<literal>@Configuration</literal> classes may be used as input when
instantiating an <literal>AnnotationConfigApplicationContext</literal>.
This allows for completely XML-free usage of the Spring container:
<programlisting language="java">public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}</programlisting>
As mentioned above,
<literal>AnnotationConfigApplicationContext</literal> is not limited to
working only with <literal>@Configuration</literal> classes. Any
<literal>@Component</literal> or JSR-330 annotated class may be supplied
as input to the constructor. For example:
<programlisting language="java">public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class);
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}</programlisting>
The above assumes that <literal>MyServiceImpl</literal>,
<literal>Dependency1</literal> and <literal>Dependency2</literal> use
Spring dependency injection annotations such as
<literal>@Autowired</literal>.</para>
</section>
<section id="beans-java-instantiating-container-register">
<title>Building the container programmatically using
<literal>register(Class&lt;?&gt;...)</literal></title>
<para>An <literal>AnnotationConfigApplicationContext</literal> may be
instantiated using a no-arg constructor and then configured using the
<literal>register()</literal> method. This approach is particularly
useful when programmatically building an
<literal>AnnotationConfigApplicationContext</literal>.
<programlisting language="java">public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class, OtherConfig.class);
ctx.register(AdditionalConfig.class);
ctx.refresh();
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}</programlisting></para>
</section>
<section id="beans-java-instantiating-container-scan">
<title>Enabling component scanning with
<literal>scan(String...)</literal></title>
<para>Experienced Spring users will be familiar with the following
commonly-used XML declaration from Spring's <literal>context:</literal>
namespace
<programlisting language="xml">&lt;beans&gt;
&lt;context:component-scan base-package="com.acme"/&gt;
&lt;/beans&gt;</programlisting>
In the example above, the <literal>com.acme</literal> package will be
scanned, looking for any <literal>@Component</literal>-annotated
classes, and those classes will be registered as Spring bean definitions
within the container.
<literal>AnnotationConfigApplicationContext</literal> exposes the
<literal>scan(String...)</literal> method to allow for the same
component-scanning
functionality:<programlisting language="java">public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("com.acme");
ctx.refresh();
MyService myService = ctx.getBean(MyService.class);
}</programlisting></para>
<note>
<para>Remember that <literal>@Configuration</literal> classes are
meta-annotated with <literal>@Component</literal>, so they are
candidates for component-scanning! In the example above, assuming that
<literal>AppConfig</literal> is declared within the
<literal>com.acme</literal> package (or any package underneath), it
will be picked up during the call to <literal>scan()</literal>, and
upon <literal>refresh()</literal> all its <literal>@Bean</literal>
methods will be processed and registered as bean definitions within
the container.</para>
</note>
</section>
<section id="beans-java-instantiating-container-web">
<title>Support for web applications with
<literal>AnnotationConfigWebApplicationContext</literal></title>
<para>A <literal>WebApplicationContext</literal> variant of
<literal>AnnotationConfigApplicationContext</literal> is available with
<literal>AnnotationConfigWebApplicationContext</literal>. This
implementation may be used when configuring the Spring
<literal>ContextLoaderListener</literal> servlet listener, Spring MVC
<literal>DispatcherServlet</literal>, etc. What follows is a
<literal>web.xml</literal> snippet that configures a typical Spring MVC
web application. Note the use of the <literal>contextClass</literal>
context-param and init-param:
<programlisting language="xml">
&lt;web-app&gt;
&lt;!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
instead of the default XmlWebApplicationContext --&gt;
&lt;context-param&gt;
&lt;param-name&gt;contextClass&lt;/param-name&gt;
&lt;param-value&gt;
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
&lt;/param-value&gt;
&lt;/context-param&gt;
&lt;!-- Configuration locations must consist of one or more comma- or space-delimited
fully-qualified @Configuration classes. Fully-qualified packages may also be
specified for component-scanning --&gt;
&lt;context-param&gt;
&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
&lt;param-value&gt;com.acme.AppConfig&lt;/param-value&gt;
&lt;/context-param&gt;
&lt;!-- Bootstrap the root application context as usual using ContextLoaderListener --&gt;
&lt;listener&gt;
&lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
&lt;/listener&gt;
&lt;!-- Declare a Spring MVC DispatcherServlet as usual --&gt;
&lt;servlet&gt;
&lt;servlet-name&gt;dispatcher&lt;/servlet-name&gt;
&lt;servlet-class&gt;org.springframework.web.servlet.DispatcherServlet&lt;/servlet-class&gt;
&lt;!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
instead of the default XmlWebApplicationContext --&gt;
&lt;init-param&gt;
&lt;param-name&gt;contextClass&lt;/param-name&gt;
&lt;param-value&gt;
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;!-- Again, config locations must consist of one or more comma- or space-delimited
and fully-qualified @Configuration classes --&gt;
&lt;init-param&gt;
&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
&lt;param-value&gt;com.acme.web.MvcConfig&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;/servlet&gt;
&lt;!-- map all requests for /app/* to the dispatcher servlet --&gt;
&lt;servlet-mapping&gt;
&lt;servlet-name&gt;dispatcher&lt;/servlet-name&gt;
&lt;url-pattern&gt;/app/*&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;
&lt;/web-app&gt;</programlisting></para>
</section>
</section>
<section id="beans-java-composing-configuration-classes">
<title>Composing Java-based configurations</title>
<section id="beans-java-using-import">
<title>Using the <literal>@Import</literal> annotation</title>
<para>Much as the <literal>&lt;import/&gt;</literal> element is used
within Spring XML files to aid in modularizing configurations, the
<literal>@Import</literal> annotation allows for loading
<literal>@Bean</literal> definitions from another configuration
class:<programlisting language="java">@Configuration
public class ConfigA {
public @Bean A a() { return new A(); }
}
@Configuration
@Import(ConfigA.class)
public class ConfigB {
public @Bean B b() { return new B(); }
}</programlisting>
Now, rather than needing to specify both
<literal>ConfigA.class</literal> and <literal>ConfigB.class</literal>
when instantiating the context, only <literal>ConfigB</literal> needs to
be supplied
explicitly:<programlisting language="java">public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);
// now both beans A and B will be available...
A a = ctx.getBean(A.class);
B b = ctx.getBean(B.class);
}</programlisting>
This approach simplifies container instantiation, as only one class
needs to be dealt with, rather than requiring the developer to remember
a potentially large number of <literal>@Configuration</literal> classes
during construction.</para>
<section id="beans-java-injecting-imported-beans">
<title>Injecting dependencies on imported <literal>@Bean</literal>
definitions</title>
<para>The example above works, but is simplistic. In most practical
scenarios, beans will have dependencies on one another across
configuration classes. When using XML, this is not an issue, per se,
because there is no compiler involved, and one can simply declare
<literal>ref="someBean"</literal> and trust that Spring will work it
out during container initialization. Of course, when using
<literal>@Configuration</literal> classes, the Java compiler places
constraints on the configuration model, in that references to other
beans must be valid Java syntax.</para>
<para>Fortunately, solving this problem is simple. Remember that
<literal>@Configuration</literal> classes are ultimately just another
bean in the container - this means that they can take advantage of
<literal>@Autowired</literal> injection metadata just like any other
bean!</para>
<para>Let's consider a more real-world scenario with several
<literal>@Configuration</literal> classes, each depending on beans
declared in the
others:<programlisting language="java">@Configuration
public class ServiceConfig {
private @Autowired AccountRepository accountRepository;
public @Bean TransferService transferService() {
return new TransferServiceImpl(accountRepository);
}
}
@Configuration
public class RepositoryConfig {
private @Autowired DataSource dataSource;
public @Bean AccountRepository accountRepository() {
return new JdbcAccountRepository(dataSource);
}
}
@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {
public @Bean DataSource dataSource() { /* return new DataSource */ }
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
// everything wires up across configuration classes...
TransferService transferService = ctx.getBean(TransferService.class);
transferService.transfer(100.00, "A123", "C456");
}</programlisting></para>
<section id="beans-java-injecting-imported-beans-fq">
<title>Fully-qualifying imported beans for ease of navigation</title>
<para>In the scenario above, using <literal>@Autowired</literal> works
well and provides the desired modularity, but determining exactly
where the autowired bean definitions are declared is still somewhat
ambiguous. For example, as a developer looking at
<literal>ServiceConfig</literal>, how do you know exactly where the
<literal>@Autowired AccountRepository</literal> bean is declared?
It's not explicit in the code, and this may be just fine. Remember
that the <ulink url="http://www.springsource.com/products/sts"
>SpringSource Tool Suite</ulink> provides tooling that can render
graphs showing how everything is wired up - that may be all you
need. Also, your Java IDE can easily find all declarations and uses
of the <literal>AccountRepository</literal> type, and will quickly
show you the location of <literal>@Bean</literal> methods that
return that type.</para>
<para>In cases where this ambiguity is not acceptable and you wish to
have direct navigation from within your IDE from one
<literal>@Configuration</literal> class to another, consider
autowiring the configuration classes themselves:
<programlisting language="java">@Configuration
public class ServiceConfig {
private @Autowired RepositoryConfig repositoryConfig;
public @Bean TransferService transferService() {
// navigate 'through' the config class to the @Bean method!
return new TransferServiceImpl(repositoryConfig.accountRepository());
}
}</programlisting>
In the situation above, it is completely explicit where
<literal>AccountRepository</literal> is defined. However,
<literal>ServiceConfig</literal> is now tightly coupled to
<literal>RepositoryConfig</literal>; that's the tradeoff. This tight
coupling can be somewhat mitigated by using interface-based or
abstract class-based <literal>@Configuration</literal> classes.
Consider the following:
<programlisting language="java">@Configuration
public class ServiceConfig {
private @Autowired RepositoryConfig repositoryConfig;
public @Bean TransferService transferService() {
return new TransferServiceImpl(repositoryConfig.accountRepository());
}
}
@Configuration
public interface RepositoryConfig {
@Bean AccountRepository accountRepository();
}
@Configuration
public class DefaultRepositoryConfig implements RepositoryConfig {
public @Bean AccountRepository accountRepository() {
return new JdbcAccountRepository(...);
}
}
@Configuration
@Import({ServiceConfig.class, DefaultRepositoryConfig.class}) // import the concrete config!
public class SystemTestConfig {
public @Bean DataSource dataSource() { /* return DataSource */ }
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
TransferService transferService = ctx.getBean(TransferService.class);
transferService.transfer(100.00, "A123", "C456");
}</programlisting>
Now <literal>ServiceConfig</literal> is loosely coupled with respect
to the concrete <literal>DefaultRepositoryConfig</literal>, and
built-in IDE tooling is still useful: it will be easy for the
developer to get a type hierarchy of
<literal>RepositoryConfig</literal> implementations. In this way,
navigating <literal>@Configuration</literal> classes and their
dependencies becomes no different than the usual process of
navigating interface-based code.</para>
</section>
</section>
</section>
<section id="beans-java-combining">
<title>Combining Java and XML configuration</title>
<para>Spring's <literal>@Configuration</literal> class support does not
aim to be a 100% complete replacement for Spring XML. Some facilities
such as Spring XML namespaces remain an ideal way to configure the
container. In cases where XML is convenient or necessary, you have a
choice: either instantiate the container in an "XML-centric" way using,
for example, <literal>ClassPathXmlApplicationContext</literal>, or in a
"Java-centric" fashion using
<literal>AnnotationConfigApplicationContext</literal> and the
<literal>@ImportResource</literal> annotation to import XML as
needed.</para>
<section id="beans-java-combining-xml-centric">
<title>XML-centric use of <literal>@Configuration</literal>
classes</title>
<para>It may be preferable to bootstrap the Spring container from XML
and include <literal>@Configuration</literal> classes in an ad-hoc
fashion. For example, in a large existing codebase that uses Spring
XML, it will be easier to create <literal>@Configuration</literal>
classes on an as-needed basis and include them from the existing XML
files. Below you'll find the options for using
<literal>@Configuration</literal> classes in this kind of
"XML-centric" situation.</para>
<section id="beans-java-combining-xml-centric-declare-as-bean">
<title>Declaring <literal>@Configuration</literal> classes as plain
Spring <literal>&lt;bean/&gt;</literal> elements</title>
<para>Remember that <literal>@Configuration</literal> classes are
ultimately just bean definitions in the container. In this example,
we create a <literal>@Configuration</literal> class named
<literal>AppConfig</literal> and include it within
<literal>system-test-config.xml</literal> as a
<literal>&lt;bean/&gt;</literal>definition. Because
<literal>&lt;context:annotation-config/&gt;</literal> is switched
on, the container will recognize the
<literal>@Configuration</literal> annotation, and process the
<literal>@Bean</literal> methods declared in
<literal>AppConfig</literal>
properly.<programlisting language="java">@Configuration
public class AppConfig {
private @Autowired DataSource dataSource;
public @Bean AccountRepository accountRepository() {
return new JdbcAccountRepository(dataSource);
}
public @Bean TransferService transferService() {
return new TransferService(accountRepository());
}
}</programlisting>
<programlisting language="xml"><lineannotation role="listingtitle">system-test-config.xml</lineannotation>
&lt;beans&gt;
&lt;!-- enable processing of annotations such as @Autowired and @Configuration --&gt;
&lt;context:annotation-config/&gt;
&lt;context:property-placeholder location="classpath:/com/acme/jdbc.properties"/&gt;
&lt;bean class="com.acme.AppConfig"/&gt;
&lt;bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;
&lt;property name="url" value="${jdbc.url}"/&gt;
&lt;property name="username" value="${jdbc.username}"/&gt;
&lt;property name="password" value="${jdbc.password}"/&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting>
<programlisting><lineannotation role="listingtitle">jdbc.properties</lineannotation>
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb
jdbc.username=sa
jdbc.password=</programlisting>
<programlisting language="java">public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml");
TransferService transferService = ctx.getBean(TransferService.class);
// ...
}</programlisting></para>
<note>
<para>In <literal>system-test-config.xml</literal> above, the
<literal>AppConfig&lt;bean/&gt;</literal> does not declare an
<literal>id</literal> element. While it would be acceptable to do
so, it is unnecessary given that no other bean will ever refer to
it, and it is unlikely that it will be explicitly fetched from the
container by name. Likewise with the <literal>DataSource</literal>
bean - it is only ever autowired by type, so an explicit bean id
is not strictly required.</para>
</note>
</section>
<section id="beans-java-combining-xml-centric-component-scan">
<title>Using <literal>&lt;context:component-scan/&gt;</literal> to
pick up <literal>@Configuration</literal> classes</title>
<para>Because <literal>@Configuration</literal> is meta-annotated with
<literal>@Component</literal>,
<literal>@Configuration</literal>-annotated classes are
automatically candidates for component scanning. Using the same
scenario as above, we can redefine
<literal>system-test-config.xml</literal> to take advantage of
component-scanning. Note that in this case, we don't need to
explicitly declare
<literal>&lt;context:annotation-config/&gt;</literal>, because
<literal>&lt;context:component-scan/&gt;</literal> enables all the
same
functionality.<programlisting language="xml"><lineannotation role="listingtitle">system-test-config.xml</lineannotation>
&lt;beans&gt;
&lt;!-- picks up and registers AppConfig as a bean definition --&gt;
&lt;context:component-scan base-package="com.acme"/&gt;
&lt;context:property-placeholder location="classpath:/com/acme/jdbc.properties"/&gt;
&lt;bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;
&lt;property name="url" value="${jdbc.url}"/&gt;
&lt;property name="username" value="${jdbc.username}"/&gt;
&lt;property name="password" value="${jdbc.password}"/&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting></para>
</section>
</section>
<section id="beans-java-combining-java-centric">
<title><literal>@Configuration</literal> class-centric use of XML with
<literal>@ImportResource</literal></title>
<para>In applications where <literal>@Configuration</literal> classes
are the primary mechanism for configuring the container, it will still
likely be necessary to use at least some XML. In these scenarios,
simply use <literal>@ImportResource</literal> and define only as much
XML as is needed. Doing so achieves a "Java-centric" approach to
configuring the container and keeps XML to a bare minimum.
<programlisting language="java">@Configuration
@ImportResource("classpath:/com/acme/properties-config.xml")
public class AppConfig {
private @Value("${jdbc.url}") String url;
private @Value("${jdbc.username}") String username;
private @Value("${jdbc.password}") String password;
public @Bean DataSource dataSource() {
return new DriverManagerDataSource(url, username, password);
}
}</programlisting>
<programlisting language="xml"><lineannotation role="listingtitle">properties-config.xml</lineannotation>
&lt;beans&gt;
&lt;context:property-placeholder location="classpath:/com/acme/jdbc.properties"/&gt;
&lt;/beans&gt;</programlisting>
<programlisting><lineannotation role="listingtitle">jdbc.properties</lineannotation>
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb
jdbc.username=sa
jdbc.password=</programlisting>
<programlisting language="java">public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
TransferService transferService = ctx.getBean(TransferService.class);
// ...
}</programlisting></para>
</section>
</section>
</section>
<section id="beans-java-bean-annotation">
<title>Using the <interfacename>@Bean</interfacename> annotation</title>
<para><interfacename>@Bean</interfacename> is a method-level annotation and
a direct analog of the XML <code>&lt;bean/&gt;</code> element. The
annotation supports some of the attributes offered by
<code>&lt;bean/&gt;</code>, such as: <code><link
linkend="beans-factory-lifecycle-initializingbean"
>init-method</link></code>, <code><link
linkend="beans-factory-lifecycle-disposablebean"
>destroy-method</link></code>, <code><link
linkend="beans-factory-autowire">autowiring</link></code> and
<code>name</code>.</para>
<para>You can use the <interfacename>@Bean</interfacename> annotation in a
<interfacename>@Configuration</interfacename>-annotated or in a
<interfacename>@Component</interfacename>-annotated class.</para>
<section id="beans-java-declaring-a-bean">
<title>Declaring a bean</title>
<para>To declare a bean, simply annotate a method with the
<interfacename>@Bean</interfacename> annotation. You use this method to
register a bean definition within an <code>ApplicationContext</code> of
the type specified as the method's return value. By default, the bean
name will be the same as the method name. The following is a simple
example of a <interfacename>@Bean</interfacename> method declaration:
<programlisting language="java">@Configuration
public class AppConfig {
@Bean
public TransferService transferService() {
return new TransferServiceImpl();
}
}</programlisting></para>
<para>The preceding configuration is exactly equivalent to the following
Spring XML:
<programlisting language="xml">&lt;beans&gt;
&lt;bean id="transferService" class="com.acme.TransferServiceImpl"/&gt;
&lt;/beans&gt; </programlisting></para>
<para>Both declarations make a bean named <code>transferService</code>
available in the <code>ApplicationContext</code>, bound to an object
instance of type <code>TransferServiceImpl</code>:
<programlisting>
transferService -&gt; com.acme.TransferServiceImpl
</programlisting></para>
</section>
<section id="beans-java-injecting-dependencies">
<title>Injecting dependencies</title>
<para>When <interfacename>@Bean</interfacename>s have dependencies on one
another, expressing that dependency is as simple as having one bean
method call another:
<programlisting language="java">@Configuration
public class AppConfig {
@Bean
public Foo foo() {
return new Foo(bar());
}
@Bean
public Bar bar() {
return new Bar();
}
} </programlisting></para>
<para>In the example above, the <code>foo</code> bean receives a reference
to <code> bar</code> via constructor injection.</para>
</section>
<section id="beans-java-lifecycle-callbacks">
<title>Receiving lifecycle callbacks</title>
<para>Beans declared in a
<interfacename>@Configuration</interfacename>-annotated class support
the regular lifecycle callbacks. Any classes defined with the
<literal>@Bean</literal> annotation can use the
<literal>@PostConstruct</literal> and <literal>@PreDestroy</literal>
annotations from JSR-250, see <link
linkend="beans-postconstruct-and-predestroy-annotations">JSR-250
annotations</link> for further details.</para>
<para>The regular Spring <link linkend="beans-factory-nature"
>lifecycle</link> callbacks are fully supported as well. If a bean
implements <code>InitializingBean</code>, <code>DisposableBean</code>,
or <code>Lifecycle</code>, their respective methods are called by the
container.</para>
<para>The standard set of <code>*Aware</code> interfaces such as
<code><link linkend="beans-beanfactory">BeanFactoryAware</link></code>,
<code><link linkend="beans-factory-aware">BeanNameAware</link></code>,
<code><link linkend="context-functionality-messagesource"
>MessageSourceAware</link></code>, <code><link
linkend="beans-factory-aware">ApplicationContextAware</link></code>, and
so on are also fully supported.</para>
<para>The <interfacename>@Bean</interfacename> annotation supports
specifying arbitrary initialization and destruction callback methods,
much like Spring XML's <code>init-method</code> and
<code>destroy-method</code> attributes on the <code>bean</code> element:
<programlisting language="java">public class Foo {
public void init() {
// initialization logic
}
}
public class Bar {
public void cleanup() {
// destruction logic
}
}
@Configuration
public class AppConfig {
@Bean(initMethod = "init")
public Foo foo() {
return new Foo();
}
@Bean(destroyMethod = "cleanup")
public Bar bar() {
return new Bar();
}
}
</programlisting></para>
<para>Of course, in the case of <code>Foo</code> above, it would be
equally as valid to call the <code>init()</code> method directly during
construction:
<programlisting language="java">@Configuration
public class AppConfig {
@Bean
public Foo foo() {
Foo foo = new Foo();
foo.init();
return foo;
}
// ...
} </programlisting></para>
<tip>
<para>When you work directly in Java, you can do anything you like with
your objects and do not always need to rely on the container
lifecycle!</para>
</tip>
</section>
<section id="beans-java-specifying-bean-scope">
<title>Specifying bean scope</title>
<section id="beans-java-available-scopes">
<title>Using the <interfacename>@Scope</interfacename>
annotation</title>
<!-- MLP: Beverly, did not apply your edit as it changed meaning -->
<para>You can specify that your beans defined with the
<interfacename>@Bean</interfacename> annotation should have a specific
scope. You can use any of the standard scopes specified in the <link
linkend="beans-factory-scopes">Bean Scopes</link> section.</para>
<para>The default scope is <literal>singleton</literal>, but you can
override this with the <interfacename>@Scope</interfacename>
annotation:
<programlisting language="java">@Configuration
public class MyConfiguration {
@Bean
<emphasis role="bold">@Scope("prototype")</emphasis>
public Encryptor encryptor() {
// ...
}
}</programlisting></para>
</section>
<section id="beans-java-scoped-proxy">
<title><code>@Scope and scoped-proxy</code></title>
<para>Spring offers a convenient way of working with scoped dependencies
through <link linkend="beans-factory-scopes-other-injection">scoped
proxies</link>. The easiest way to create such a proxy when using the
XML configuration is the <code>&lt;aop:scoped-proxy/&gt;</code>
element. Configuring your beans in Java with a @Scope annotation
offers equivalent support with the proxyMode attribute. The default is
no proxy (<varname>ScopedProxyMode.NO</varname>), but you can specify
<classname>ScopedProxyMode.TARGET_CLASS</classname> or
<classname>ScopedProxyMode.INTERFACES</classname>.</para>
<para>If you port the scoped proxy example from the XML reference
documentation (see preceding link) to our
<interfacename>@Bean</interfacename> using Java, it would look like
the following:
<programlisting language="java">// an HTTP Session-scoped bean exposed as a proxy
@Bean
<emphasis role="bold">@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)</emphasis>
public UserPreferences userPreferences() {
return new UserPreferences();
}
@Bean
public Service userService() {
UserService service = new SimpleUserService();
// a reference to the proxied userPreferences bean
service.setUserPreferences(userPreferences());
return service;
} </programlisting></para>
</section>
<section id="beans-java-method-injection">
<title>Lookup method injection</title>
<para>As noted earlier, <link linkend="beans-factory-method-injection"
>lookup method injection</link> is an advanced feature that you should
use rarely. It is useful in cases where a singleton-scoped bean has a
dependency on a prototype-scoped bean. Using Java for this type of
configuration provides a natural means for implementing this pattern.
<programlisting language="java">public abstract class CommandManager {
public Object process(Object commandState) {
// grab a new instance of the appropriate Command interface
Command command = createCommand();
// set the state on the (hopefully brand new) Command instance
command.setState(commandState);
return command.execute();
}
// okay... but where is the implementation of this method?
protected abstract Command createCommand();
} </programlisting></para>
<para>Using Java-configuration support , you can create a subclass of
<code>CommandManager</code> where the abstract
<code>createCommand()</code> method is overridden in such a way that
it looks up a new (prototype) command object:
<programlisting language="java">@Bean
@Scope("prototype")
public AsyncCommand asyncCommand() {
AsyncCommand command = new AsyncCommand();
// inject dependencies here as required
return command;
}
@Bean
public CommandManager commandManager() {
// return new anonymous implementation of CommandManager with command() overridden
// to return a new prototype Command object
return new CommandManager() {
protected Command createCommand() {
return asyncCommand();
}
}
} </programlisting></para>
</section>
</section>
<section id="beans-java-customizing-bean-naming">
<title>Customizing bean naming</title>
<para>By default, configuration classes use a
<interfacename>@Bean</interfacename> method's name as the name of the
resulting bean. This functionality can be overridden, however, with the
<code>name</code> attribute.
<programlisting language="java">@Configuration
public class AppConfig {
@Bean(name = "myFoo")
public Foo foo() {
return new Foo();
}
} </programlisting></para>
</section>
<section id="beans-java-bean-aliasing">
<title>Bean aliasing</title>
<para>As discussed in <xref linkend="beans-beanname"/>, it is sometimes
desirable to give a single bean multiple names, otherwise known as
<emphasis>bean aliasing</emphasis>. The <literal>name</literal>
attribute of the <literal>@Bean</literal> annotation accepts a String
array for this purpose.
<programlisting language="java">@Configuration
public class AppConfig {
@Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" })
public DataSource dataSource() {
// instantiate, configure and return DataSource bean...
}
} </programlisting></para>
</section>
</section>
<section id="beans-java-further-information-java-config">
<title>Further information about how Java-based configuration works
internally</title>
<para>The following example shows a <literal>@Bean</literal> annotated
method being called twice:</para>
<programlisting language="java">
@Configuration
public class AppConfig {
@Bean
public ClientService clientService1() {
ClientServiceImpl clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao());
return clientService;
}
@Bean
public ClientService clientService2() {
ClientServiceImpl clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao());
return clientService;
}
@Bean
public ClientDao clientDao() {
return new ClientDaoImpl();
}
}
</programlisting>
<para> <methodname>clientDao()</methodname> has been called once in
<methodname>clientService1()</methodname> and once in
<methodname>clientService2()</methodname>. Since this method creates a new
instance of <classname>ClientDaoImpl</classname> and returns it, you would
normally expect having 2 instances (one for each service). That definitely
would be problematic: in Spring, instantiated beans have a
<literal>singleton</literal> scope by default. This is where the magic
comes in: All <literal>@Configuration</literal> classes are subclassed at
startup-time with <literal>CGLIB</literal>. In the subclass, the child
method checks the container first for any cached (scoped) beans before it
calls the parent method and creates a new instance. </para>
<note>
<para> The behavior could be different according to the scope of your
bean. We are talking about singletons here. </para>
</note>
<note>
<para> Beware that, in order for JavaConfig to work, you must include the
CGLIB jar in your list of dependencies. </para>
</note>
<note>
<para> There are a few restrictions due to the fact that CGLIB dynamically
adds features at startup-time: <itemizedlist>
<listitem>
<para>Configuration classes should not be final</para>
</listitem>
<listitem>
<para>They should have a constructor with no arguments</para>
</listitem>
</itemizedlist> </para>
</note>
</section>
</section>

View File

@@ -0,0 +1,686 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="beans-factory-scopes">
<title>Bean scopes</title>
<para>When you create a bean definition, you create a
<emphasis>recipe</emphasis> for creating actual instances of the class
defined by that bean definition. The idea that a bean definition is a recipe
is important, because it means that, as with a class, you can create many
object instances from a single recipe.</para>
<para>You can control not only the various dependencies and configuration
values that are to be plugged into an object that is created from a
particular bean definition, but also the <firstterm>scope</firstterm> of the
objects created from a particular bean definition. This approach is powerful
and flexible in that you can <emphasis>choose</emphasis> the scope of the
objects you create through configuration instead of having to bake in the
scope of an object at the Java class level. Beans can be defined to be
deployed in one of a number of scopes: out of the box, the Spring Framework
supports five scopes, three of which are available only if you use a
web-aware <interfacename>ApplicationContext</interfacename>.</para>
<para>The following scopes are supported out of the box. You can also create
<link linkend="beans-factory-scopes-custom">a custom scope.</link></para>
<table id="beans-factory-scopes-tbl">
<title>Bean scopes</title>
<tgroup cols="2">
<thead>
<row>
<entry align="center">Scope</entry>
<entry align="center">Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><para> <link linkend="beans-factory-scopes-singleton"
>singleton</link> </para></entry>
<entry><para>(Default) Scopes a single bean definition to a single
object instance per Spring IoC container.</para></entry>
</row>
<row>
<entry><para> <link linkend="beans-factory-scopes-prototype"
>prototype</link> </para></entry>
<entry><para>Scopes a single bean definition to any number of object
instances.</para></entry>
</row>
<row>
<entry><para> <link linkend="beans-factory-scopes-request"
>request</link> </para></entry>
<entry><para>Scopes a single bean definition to the lifecycle of a
single HTTP request; that is, each HTTP request has its own instance
of a bean created off the back of a single bean definition. Only
valid in the context of a web-aware Spring
<interfacename>ApplicationContext</interfacename>.</para></entry>
</row>
<row>
<entry><para> <link linkend="beans-factory-scopes-session"
>session</link> </para></entry>
<entry><para>Scopes a single bean definition to the lifecycle of an
HTTP <interfacename>Session</interfacename>. Only valid in the
context of a web-aware Spring
<interfacename>ApplicationContext</interfacename>.</para></entry>
</row>
<row>
<entry><para> <link linkend="beans-factory-scopes-global-session"
>global session</link> </para></entry>
<entry><para>Scopes a single bean definition to the lifecycle of a
global HTTP <interfacename>Session</interfacename>. Typically only
valid when used in a portlet context. Only valid in the context of a
web-aware Spring
<interfacename>ApplicationContext</interfacename>.</para></entry>
</row>
</tbody>
</tgroup>
</table>
<note>
<title>Thread-scoped beans</title>
<para>As of Spring 3.0, a <emphasis>thread scope</emphasis> is available,
but is not registered by default. For more information, see the
documentation for <ulink
url="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/support/SimpleThreadScope.html"
>SimpleThreadScope</ulink>. For instructions on how to register this or
any other custom scope, see <xref
linkend="beans-factory-scopes-custom-using"/>.</para>
</note>
<section id="beans-factory-scopes-singleton">
<title>The singleton scope</title>
<para>Only one <emphasis>shared</emphasis> instance of a singleton bean is
managed, and all requests for beans with an id or ids matching that bean
definition result in that one specific bean instance being returned by the
Spring container.</para>
<para>To put it another way, when you define a bean definition and it is
scoped as a singleton, the Spring IoC container creates <emphasis>exactly
one</emphasis> instance of the object defined by that bean definition.
This single instance is stored in a cache of such singleton beans, and
<emphasis>all subsequent requests and references</emphasis> for that named
bean return the cached object.</para>
<para><mediaobject>
<imageobject role="fo">
<imagedata align="center" fileref="images/singleton.png" format="PNG"/>
</imageobject>
<imageobject role="html">
<imagedata align="center" fileref="images/singleton.png" format="PNG"/>
</imageobject>
</mediaobject></para>
<para>Spring's concept of a singleton bean differs from the Singleton
pattern as defined in the Gang of Four (GoF) patterns book. The GoF
Singleton hard-codes the scope of an object such that one <emphasis>and
only one</emphasis> instance of a particular class is created<emphasis>
per <classname>ClassLoader</classname></emphasis>. The scope of the Spring
singleton is best described as <emphasis>per container and per
bean</emphasis>. This means that if you define one bean for a particular
class in a single Spring container, then the Spring container creates one
<emphasis>and only one</emphasis> instance of the class defined by that
bean definition. <emphasis>The singleton scope is the default scope in
Spring</emphasis>. To define a bean as a singleton in XML, you would
write, for example:</para>
<programlisting language="xml">&lt;bean id="accountService" class="com.foo.DefaultAccountService"/&gt;
<lineannotation>&lt;!-- the following is equivalent, though redundant (singleton scope is the default) --&gt;</lineannotation>
&lt;bean id="accountService" class="com.foo.DefaultAccountService" scope="singleton"/&gt;</programlisting>
</section>
<section id="beans-factory-scopes-prototype">
<title>The prototype scope</title>
<para>The non-singleton, prototype scope of bean deployment results in the
<emphasis>creation of a new bean instance</emphasis> every time a request
for that specific bean is made. That is, the bean is injected into another
bean or you request it through a <literal>getBean()</literal> method call
on the container. As a rule, use the prototype scope for all stateful
beans and the singleton scope for stateless beans.</para>
<para>The following diagram illustrates the Spring prototype scope.
<emphasis>A data access object (DAO) is not typically configured as a
prototype, because a typical DAO does not hold any conversational state;
it was just easier for this author to reuse the core of the singleton
diagram.</emphasis><!--First it says diagram illustrates scope, but then says it's not typical of a prototype scope. Why not use realistic one? --></para>
<para><mediaobject>
<imageobject role="fo">
<imagedata align="center" fileref="images/prototype.png" format="PNG"/>
</imageobject>
<imageobject role="html">
<imagedata align="center" fileref="images/prototype.png" format="PNG"/>
</imageobject>
</mediaobject></para>
<para>The following example defines a bean as a prototype in XML:</para>
<programlisting language="xml"><lineannotation>&lt;!-- using <literal>spring-beans-2.0.dtd</literal> --&gt;</lineannotation>
&lt;bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/&gt;</programlisting>
<para>In contrast to the other scopes, Spring does not manage the complete
lifecycle of a prototype bean: the container instantiates, configures, and
otherwise assembles a prototype object, and hands it to the client, with
no further record of that prototype instance. Thus, although
<emphasis>initialization</emphasis> lifecycle callback methods are called
on all objects regardless of scope, in the case of prototypes, configured
<emphasis>destruction</emphasis> lifecycle callbacks are
<emphasis>not</emphasis> called. The client code must clean up
prototype-scoped objects and release expensive resources that the
prototype bean(s) are holding. To get the Spring container to release
resources held by prototype-scoped beans, try using a custom <link
linkend="beans-factory-extension-bpp">bean post-processor</link>, which
holds a reference to beans that need to be cleaned up.</para>
<para>In some respects, the Spring container's role in regard to a
prototype-scoped bean is a replacement for the Java <literal>new</literal>
operator. All lifecycle management past that point must be handled by the
client. (For details on the lifecycle of a bean in the Spring container,
see <xref linkend="beans-factory-lifecycle"/>.)</para>
</section>
<section id="beans-factory-scopes-sing-prot-interaction">
<title>Singleton beans with prototype-bean dependencies</title>
<para>When you use singleton-scoped beans with dependencies on prototype
beans, be aware that <emphasis>dependencies are resolved at instantiation
time</emphasis>. Thus if you dependency-inject a prototype-scoped bean
into a singleton-scoped bean, a new prototype bean is instantiated and
then dependency-injected into the singleton bean. The prototype instance
is the sole instance that is ever supplied to the singleton-scoped
bean.</para>
<para>However, suppose you want the singleton-scoped bean to acquire a new
instance of the prototype-scoped bean repeatedly at runtime. You cannot
dependency-inject a prototype-scoped bean into your singleton bean,
because that injection occurs only <emphasis>once</emphasis>, when the
Spring container is instantiating the singleton bean and resolving and
injecting its dependencies. If you need a new instance of a prototype bean
at runtime more than once, see <xref
linkend="beans-factory-method-injection"/></para>
</section>
<section id="beans-factory-scopes-other">
<title>Request, session, and global session scopes</title>
<para>The <literal>request</literal>, <literal>session</literal>, and
<literal>global session</literal> scopes are <emphasis>only</emphasis>
available if you use a web-aware Spring
<interfacename>ApplicationContext</interfacename> implementation (such as
<classname>XmlWebApplicationContext</classname>). If you use these scopes
with regular Spring IoC containers such as the
<classname>ClassPathXmlApplicationContext</classname>, you get an
<classname>IllegalStateException</classname> complaining about an unknown
bean scope.</para>
<section id="beans-factory-scopes-other-web-configuration">
<title>Initial web configuration</title>
<para>To support the scoping of beans at the <literal>request</literal>,
<literal>session</literal>, and <literal>global session</literal> levels
(web-scoped beans), some minor initial configuration is required before
you define your beans. (This initial setup is <emphasis>not</emphasis>
required for the standard scopes, singleton and prototype.)</para>
<para>How you accomplish this initial setup depends on your particular
Servlet environment..</para>
<para>If you access scoped beans within Spring Web MVC, in effect, within
a request that is processed by the Spring
<classname>DispatcherServlet</classname>, or
<classname>DispatcherPortlet</classname>, then no special setup is
necessary: <classname>DispatcherServlet</classname> and
<classname>DispatcherPortlet</classname> already expose all relevant
state.</para>
<para>If you use a Servlet 2.4+ web container, with requests processed
outside of Spring's DispatcherServlet (for example, when using JSF or
Struts), you need to add the following
<interfacename>javax.servlet.ServletRequestListener</interfacename> to
the declarations in your web applications <literal>web.xml</literal>
file:</para>
<programlisting language="xml">&lt;web-app&gt;
...
&lt;listener&gt;
&lt;listener-class&gt;
org.springframework.web.context.request.RequestContextListener
&lt;/listener-class&gt;
&lt;/listener&gt;
...
&lt;/web-app&gt;</programlisting>
<para>If you use an older web container (Servlet 2.3), use the provided
<interfacename>javax.servlet.Filter</interfacename> implementation. The
following snippet of XML configuration must be included in the
<literal>web.xml</literal> file of your web application if you want to
access web-scoped beans in requests outside of Spring's
DispatcherServlet on a Servlet 2.3 container. (The filter mapping
depends on the surrounding web application configuration, so you must
change it as appropriate.)</para>
<programlisting language="xml">&lt;web-app&gt;
..
&lt;filter&gt;
&lt;filter-name&gt;requestContextFilter&lt;/filter-name&gt;
&lt;filter-class&gt;org.springframework.web.filter.RequestContextFilter&lt;/filter-class&gt;
&lt;/filter&gt;
&lt;filter-mapping&gt;
&lt;filter-name&gt;requestContextFilter&lt;/filter-name&gt;
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;
...
&lt;/web-app&gt;</programlisting>
<para><classname>DispatcherServlet</classname>,
<classname>RequestContextListener</classname> and
<classname>RequestContextFilter</classname> all do exactly the same
thing, namely bind the HTTP request object to the
<classname>Thread</classname> that is servicing that request. This makes
beans that are request- and session-scoped available further down the
call chain.</para>
</section>
<section id="beans-factory-scopes-request">
<title>Request scope</title>
<para>Consider the following bean definition:</para>
<programlisting language="xml">&lt;bean id="loginAction" class="com.foo.LoginAction" scope="request"/&gt;</programlisting>
<para>The Spring container creates a new instance of the
<classname>LoginAction</classname> bean by using the
<literal>loginAction</literal> bean definition for each and every HTTP
request. That is, the <literal>loginAction</literal> bean is scoped at
the HTTP request level. You can change the internal state of the
instance that is created as much as you want, because other instances
created from the same <literal>loginAction</literal> bean definition
will not see these changes in state; they are particular to an
individual request. When the request completes processing, the bean that
is scoped to the request is discarded.</para>
</section>
<section id="beans-factory-scopes-session">
<title>Session scope</title>
<para>Consider the following bean definition:</para>
<programlisting language="xml">&lt;bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/&gt;</programlisting>
<para>The Spring container creates a new instance of the
<classname>UserPreferences</classname> bean by using the
<literal>userPreferences</literal> bean definition for the lifetime of a
single HTTP <interfacename>Session</interfacename>. In other words, the
<literal>userPreferences</literal> bean is effectively scoped at the
HTTP <interfacename>Session</interfacename> level. As with
<literal>request-scoped</literal> beans, you can change the internal
state of the instance that is created as much as you want, knowing that
other HTTP <interfacename>Session</interfacename> instances that are
also using instances created from the same
<literal>userPreferences</literal> bean definition do not see these
changes in state, because they are particular to an individual HTTP
<interfacename>Session</interfacename>. When the HTTP
<interfacename>Session</interfacename> is eventually discarded, the bean
that is scoped to that particular HTTP
<interfacename>Session</interfacename> is also discarded.</para>
</section>
<section id="beans-factory-scopes-global-session">
<title>Global session scope</title>
<para>Consider the following bean definition:</para>
<programlisting language="xml">&lt;bean id="userPreferences" class="com.foo.UserPreferences" scope="globalSession"/&gt;</programlisting>
<para>The <literal>global session</literal> scope is similar to the
standard HTTP <interfacename>Session</interfacename> scope (<link
linkend="beans-factory-scopes-session">described above</link>), and
applies only in the context of portlet-based web applications. The
portlet specification defines the notion of a global
<interfacename>Session</interfacename> that is shared among all portlets
that make up a single portlet web application. Beans defined at the
<literal>global session</literal> scope are scoped (or bound) to the
lifetime of the global portlet
<interfacename>Session</interfacename>.</para>
<para>If you write a standard Servlet-based web application and you define
one or more beans as having <literal>global session</literal> scope, the
standard HTTP <interfacename>Session</interfacename> scope is used, and
no error is raised.</para>
</section>
<section id="beans-factory-scopes-other-injection">
<title>Scoped beans as dependencies</title>
<para>The Spring IoC container manages not only the instantiation of your
objects (beans), but also the wiring up of collaborators (or
dependencies). If you want to inject (for example) an HTTP request
scoped bean into another bean, you must inject an AOP proxy in place of
the scoped bean. That is, you need to inject a proxy object that exposes
the same public interface as the scoped object but that can also
retrieve the real, target object from the relevant scope (for example,
an HTTP request) and delegate method calls onto the real object.</para>
<note>
<para>You <emphasis>do not</emphasis> need to use the
<literal>&lt;aop:scoped-proxy/&gt;</literal> in conjunction with beans
that are scoped as <literal>singletons</literal> or
<literal>prototypes</literal>. If you try to create a scoped proxy for
a singleton bean, the
<exceptionname>BeanCreationException</exceptionname> is raised.</para>
</note>
<para>The configuration in the following example is only one line, but it
is important to understand the <quote>why</quote> as well as the
<quote>how</quote> behind it.</para>
<!--What is this example supposed to show?-->
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"&gt;
<lineannotation>&lt;!-- an HTTP <interfacename>Session</interfacename>-scoped bean exposed as a proxy --&gt;</lineannotation>
&lt;bean id="userPreferences" class="com.foo.UserPreferences" <emphasis role="bold">scope="session"</emphasis>&gt;
<lineannotation>&lt;!-- instructs the container to proxy the surrounding bean --&gt;</lineannotation>
<emphasis role="bold">&lt;aop:scoped-proxy/&gt;</emphasis>
&lt;/bean&gt;
<lineannotation>&lt;!-- a singleton-scoped bean <emphasis role="bold">injected with a proxy to the above bean</emphasis> --&gt;</lineannotation>
&lt;bean id="userService" class="com.foo.SimpleUserService"&gt;
<lineannotation>&lt;!-- a reference to the <emphasis role="bold">proxied</emphasis> <literal>userPreferences</literal> bean --&gt;</lineannotation>
&lt;property name="userPreferences" ref="userPreferences"/&gt;
&lt;/bean&gt;
&lt;/beans&gt;
</programlisting>
<para>To create such a proxy, you insert a child
<literal>&lt;aop:scoped-proxy/&gt;</literal> element into a scoped bean
definition.
<!--To create what such proxy? Is the proxy created above? Also, below added an x-ref that seems relevant.-->(If
you choose class-based proxying, you also need the CGLIB library in your
classpath. See <xref
linkend="beans-factory-scopes-other-injection-proxies"/> and <xref
linkend="xsd-config"/>.) Why do definitions of beans scoped at the
<literal>request</literal>, <literal>session</literal>,
<literal>globalSession</literal> and custom-scope levels require the
<literal>&lt;aop:scoped-proxy/&gt;</literal> element ? Let's examine the
following singleton bean definition and contrast it with what you need
to define for the aforementioned scopes. (The following
<literal>userPreferences</literal> bean definition as it stands is
<emphasis>incomplete.)</emphasis></para>
<programlisting language="xml">&lt;bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/&gt;
&lt;bean id="userManager" class="com.foo.UserManager"&gt;
&lt;property name="userPreferences" ref="userPreferences"/&gt;
&lt;/bean&gt;</programlisting>
<para>In the preceding example, the singleton bean
<literal>userManager</literal> is injected with a reference to the HTTP
<interfacename>Session</interfacename>-scoped bean
<literal>userPreferences</literal>. The salient point here is that the
<literal>userManager</literal> bean is a singleton: it will be
instantiated <emphasis>exactly once</emphasis> per container, and its
dependencies (in this case only one, the
<literal>userPreferences</literal> bean) are also injected only once.
This means that the <literal>userManager</literal> bean will only
operate on the exact same <literal>userPreferences</literal> object,
that is, the one that it was originally injected with.</para>
<!-- MLP: Beverly to review paragraph -->
<para>This is <emphasis>not</emphasis> the behavior you want when
injecting a shorter-lived scoped bean into a longer-lived scoped bean,
for example injecting an HTTP
<interfacename>Session</interfacename>-scoped collaborating bean as a
dependency into singleton bean. Rather, you need a single
<literal>userManager</literal> object, and for the lifetime of an HTTP
<interfacename>Session</interfacename>, you need a
<literal>userPreferences</literal> object that is specific to said HTTP
<interfacename>Session</interfacename>. Thus the container creates an
object that exposes the exact same public interface as the
<classname>UserPreferences</classname> class (ideally an object that
<emphasis>is a</emphasis> <classname>UserPreferences</classname>
instance) which can fetch the real
<classname>UserPreferences</classname> object from the scoping mechanism
(HTTP request, <interfacename>Session</interfacename>, etc.). The
container injects this proxy object into the
<literal>userManager</literal> bean, which is unaware that this
<classname>UserPreferences</classname> reference is a proxy. In this
example, when a <interfacename>UserManager</interfacename> instance
invokes a method on the dependency-injected
<classname>UserPreferences</classname> object, it actually is invoking a
method on the proxy. The proxy then fetches the real
<classname>UserPreferences</classname> object from (in this case) the
HTTP <interfacename>Session</interfacename>, and delegates the method
invocation onto the retrieved real
<classname>UserPreferences</classname> object.</para>
<para>Thus you need the following, correct and complete, configuration
when injecting <literal>request-</literal>, <literal>session-</literal>,
and <literal>globalSession-scoped</literal> beans into collaborating
objects:</para>
<programlisting language="xml">&lt;bean id="userPreferences" class="com.foo.UserPreferences" scope="session"&gt;
<emphasis role="bold"><literal>&lt;aop:scoped-proxy/&gt;</literal></emphasis>
&lt;/bean&gt;
&lt;bean id="userManager" class="com.foo.UserManager"&gt;
&lt;property name="userPreferences" ref="userPreferences"/&gt;
&lt;/bean&gt;</programlisting>
<section id="beans-factory-scopes-other-injection-proxies">
<title>Choosing the type of proxy to create</title>
<para>By default, when the Spring container creates a proxy for a bean
that is marked up with the
<literal>&lt;aop:scoped-proxy/&gt;</literal> element, <emphasis>a
CGLIB-based class proxy is created</emphasis>. This means that you
need to have the CGLIB library in the classpath of your
application.</para>
<para><emphasis>Note: CGLIB proxies only intercept public method
calls!</emphasis> Do not call non-public methods on such a proxy; they
will not be delegated to the scoped target object.</para>
<para>Alternatively, you can configure the Spring container to create
standard JDK interface-based proxies for such scoped beans, by
specifying <literal>false</literal> for the value of the
<literal>proxy-target-class</literal> attribute of the
<literal>&lt;aop:scoped-proxy/&gt;</literal> element. Using JDK
interface-based proxies means that you do not need additional
libraries in your application classpath to effect such proxying.
However, it also means that the class of the scoped bean must
implement at least one interface, and <emphasis>that all</emphasis>
collaborators into which the scoped bean is injected must reference
the bean through one of its interfaces.</para>
<programlisting language="xml"><lineannotation>&lt;!-- <classname>DefaultUserPreferences</classname> implements the <interfacename>UserPreferences</interfacename> interface --&gt;</lineannotation>
&lt;bean id="userPreferences" class="com.foo.DefaultUserPreferences" scope="session"&gt;
&lt;aop:scoped-proxy <emphasis role="bold">proxy-target-class="false"<literal/></emphasis>/&gt;
&lt;/bean&gt;
&lt;bean id="userManager" class="com.foo.UserManager"&gt;
&lt;property name="userPreferences" ref="userPreferences"/&gt;
&lt;/bean&gt;</programlisting>
<para>For more detailed information about choosing class-based or
interface-based proxying, see <xref linkend="aop-proxying"/>.</para>
</section>
</section>
</section>
<section id="beans-factory-scopes-custom">
<title>Custom scopes</title>
<para>As of Spring 2.0, the bean scoping mechanism is extensible. You can
define your own scopes, or even redefine existing scopes, although the
latter is considered bad practice and you <emphasis>cannot</emphasis>
override the built-in <literal>singleton</literal> and
<literal>prototype</literal> scopes.</para>
<section id="beans-factory-scopes-custom-creating">
<title>Creating a custom scope</title>
<para>To integrate your custom scope(s) into the Spring container, you
need to implement the
<interfacename>org.springframework.beans.factory.config.Scope</interfacename>
interface, which is described in this section. For an idea of how to
implement your own scopes, see the <interfacename>Scope</interfacename>
implementations that are supplied with the Spring Framework itself and
the <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/config/Scope.html"
>Scope Javadoc</ulink>, which explains the methods you need to implement
in more detail.</para>
<para>The <literal>Scope</literal> interface has four methods to get
objects from the scope, remove them from the scope, and allow them to be
destroyed.</para>
<para>The following method returns the object from the underlying scope.
The session scope implementation, for example, returns the
session-scoped bean (and if it does not exist, the method returns a new
instance of the bean, after having bound it to the session for future
reference).<!--How can it return a a new instance of a bean that doesn't exist? Revise to clarify.--></para>
<programlisting language="java">Object get(String name, ObjectFactory objectFactory)</programlisting>
<para>The following method removes the object from the underlying scope.
The session scope implementation for example, removes the session-scoped
bean from the underlying session. The object should be returned, but you
can return null if the object with the specified name is not
found.</para>
<programlisting language="java">Object remove(String name)</programlisting>
<para>The following method registers the callbacks the scope should
execute when it is destroyed or when the specified object in the scope
is destroyed. Refer to the Javadoc or a Spring scope implementation for
more information on destruction callbacks.</para>
<programlisting language="java">void registerDestructionCallback(String name, Runnable destructionCallback)</programlisting>
<para>The following method obtains the conversation identifier for the
underlying scope. This identifier is different for each scope. For a
session scoped implementation, this identifier can be the session
identifier.</para>
<programlisting language="java">String getConversationId()</programlisting>
</section>
<section id="beans-factory-scopes-custom-using">
<title>Using a custom scope</title>
<para>After you write and test one or more custom
<interfacename>Scope</interfacename> implementations, you need to make
the Spring container aware of your new scope(s). The following method is
the central method to register a new
<interfacename>Scope</interfacename> with the Spring container:</para>
<programlisting language="java">void registerScope(String scopeName, Scope scope);</programlisting>
<para>This method is declared on the
<interfacename>ConfigurableBeanFactory</interfacename> interface, which
is available on most of the concrete
<interfacename>ApplicationContext</interfacename> implementations that
ship with Spring via the BeanFactory property.</para>
<para>The first argument to the <methodname>registerScope(..)</methodname>
method is the unique name associated with a scope; examples of such
names in the Spring container itself are <literal>singleton</literal>
and <literal>prototype</literal>. The second argument to the
<methodname>registerScope(..)</methodname> method is an actual instance
of the custom <interfacename>Scope</interfacename> implementation that
you wish to register and use.</para>
<para>Suppose that you write your custom
<interfacename>Scope</interfacename> implementation, and then register
it as below.</para>
<note>
<para>The example below uses <literal>SimpleThreadScope</literal> which
is included with Spring, but not registered by default. The
instructions would be the same for your own custom
<literal>Scope</literal> implementations.</para>
</note>
<programlisting language="java">
Scope threadScope = new SimpleThreadScope();
beanFactory.registerScope("<emphasis role="bold">thread</emphasis>", threadScope);</programlisting>
<para>You then create bean definitions that adhere to the scoping rules of
your custom <interfacename>Scope</interfacename>:</para>
<programlisting language="xml">&lt;bean id="..." class="..." scope="thread"&gt;</programlisting>
<para>With a custom <interfacename>Scope</interfacename> implementation,
you are not limited to programmatic registration of the scope. You can
also do the <interfacename>Scope</interfacename> registration
declaratively, using the <classname>CustomScopeConfigurer</classname>
class:</para>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"&gt;
&lt;bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"&gt;
&lt;property name="scopes"&gt;
&lt;map&gt;<emphasis role="bold">
&lt;entry key="thread"&gt;
&lt;bean class="org.springframework.context.support.SimpleThreadScope"/&gt;
&lt;/entry&gt;</emphasis>
&lt;/map&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="bar" class="x.y.Bar" scope="thread"&gt;
&lt;property name="name" value="Rick"/&gt;
&lt;aop:scoped-proxy/&gt;
&lt;/bean&gt;
&lt;bean id="foo" class="x.y.Foo"&gt;
&lt;property name="bar" ref="bar"/&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting>
<note>
<para>When you place &lt;aop:scoped-proxy/&gt; in a
<interfacename>FactoryBean</interfacename> implementation, it is the
factory bean itself that is scoped, not the object returned from
<methodname>getObject()</methodname>.</para>
</note>
</section>
</section>
</section>

View File

@@ -0,0 +1,200 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="beans-standard-annotations">
<title>Using JSR 330 Standard Annotations</title>
<para>Starting with Spring 3.0, Spring offers support for JSR-330 standard annotations (Dependency Injection).
Those annotations are scanned in the same way as the Spring annotations. You just need to have the relevant jars in your classpath.
</para>
<note>
<para>
If you are using Maven, the <interfacename>javax.inject</interfacename> artifact is available
in the standard Maven repository
(<ulink url="http://repo1.maven.org/maven2/javax/inject/javax.inject/1/">http://repo1.maven.org/maven2/javax/inject/javax.inject/1/</ulink>).
You can add the following dependency to your file pom.xml:
</para>
<programlisting language="xml">
&lt;dependency&gt;
&lt;groupId&gt;javax.inject&lt;/groupId&gt;
&lt;artifactId&gt;javax.inject&lt;/artifactId&gt;
&lt;version&gt;1&lt;/version&gt;
&lt;/dependency&gt;</programlisting>
</note>
<section id="beans-inject-named">
<title>Dependency Injection with <interfacename>@Inject</interfacename> and <interfacename>@Named</interfacename></title>
<para>Instead of <interfacename>@Autowired</interfacename>,
<interfacename>@javax.inject.Inject</interfacename> may be used as follows:
<programlisting language="java">import javax.inject.Inject;
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Inject
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
</para>
<para>As with <interfacename>@Autowired</interfacename>, it is possible to use <interfacename>@Inject</interfacename>
at the class-level, field-level, method-level and constructor-argument level.
If you would like to use a qualified name for the dependency that should be injected,
you should use the <interfacename>@Named</interfacename> annotation as follows:
<programlisting language="java">import javax.inject.Inject;
import javax.inject.Named;
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Inject
public void setMovieFinder(@Named("main") MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
</para>
</section>
<section id="beans-named">
<title><interfacename>@Named</interfacename>: a standard equivalent to the <interfacename>@Component</interfacename> annotation</title>
<para>
Instead of <interfacename>@Component</interfacename>, <interfacename>@javax.inject.Named</interfacename> may be used as follows:
<programlisting language="java">import javax.inject.Inject;
import javax.inject.Named;
@Named("movieListener")
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Inject
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
</para>
<para>
It is very common to use <interfacename>@Component</interfacename> without
specifying a name for the component. <interfacename>@Named</interfacename>
can be used in a similar fashion:
<programlisting language="java">import javax.inject.Inject;
import javax.inject.Named;
@Named
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Inject
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
</para>
<para>
When using <interfacename>@Named</interfacename>, it is possible to use
component-scanning in the exact same way as when using Spring annotations:
<programlisting language="xml">&lt;beans&gt;
&lt;context:component-scan base-package="org.example"/&gt;
&lt;/beans&gt;</programlisting>
</para>
</section>
<section id="beans-standard-annotations-limitations">
<title>Limitations of the standard approach</title>
<para>When working with standard annotations, it is important to know that
some significant features are not available as shown in the table below:</para>
<para><table id="annotations-comparison">
<title>Spring annotations vs. standard annotations</title>
<tgroup cols="3">
<colspec colnum="1" colwidth="0.7*" />
<colspec colnum="2" colwidth="0.6*" />
<colspec colnum="3" colwidth="1.5*" />
<thead>
<row>
<entry>Spring</entry>
<entry>javax.inject.*</entry>
<entry>javax.inject restrictions / comments</entry>
</row>
</thead>
<tbody>
<row>
<entry>@Autowired</entry>
<entry>@Inject</entry>
<entry>@Inject has no 'required' attribute</entry>
</row>
<row>
<entry>@Component</entry>
<entry>@Named</entry>
<entry>&mdash;</entry>
</row>
<row>
<entry>@Scope("singleton")</entry>
<entry>@Singleton</entry>
<entry>
<para>
The JSR-330 default scope is like Spring's <interfacename>prototype</interfacename>.
However, in order to keep it consistent with Spring's general defaults,
a JSR-330 bean declared in the Spring container is a
<interfacename>singleton</interfacename> by default. In order to use a
scope other than <interfacename>singleton</interfacename>, you should use Spring's
<interfacename>@Scope</interfacename> annotation.
</para>
<para>
<interfacename>javax.inject</interfacename> also provides a
<ulink url="http://download.oracle.com/javaee/6/api/javax/inject/Scope.html">@Scope</ulink> annotation.
Nevertheless, this one is only intended to be used for creating your own annotations.
</para>
</entry>
</row>
<row>
<entry>@Qualifier</entry>
<entry>@Named</entry>
<entry>&mdash;</entry>
</row>
<row>
<entry>@Value</entry>
<entry>&mdash;</entry>
<entry>no equivalent</entry>
</row>
<row>
<entry>@Required</entry>
<entry>&mdash;</entry>
<entry>no equivalent</entry>
</row>
<row>
<entry>@Lazy</entry>
<entry>&mdash;</entry>
<entry>no equivalent</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
</section>
</section>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,584 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="cache">
<title>Cache Abstraction</title>
<section id="cache-introduction">
<title>Introduction</title>
<para>Since version 3.1, Spring Framework provides support for transparently
adding caching into an existing Spring application. Similar to the <link linkend="transaction">transaction</link>
support, the caching abstraction allows consistent use of various caching
solutions with minimal impact on the code.</para>
</section>
<section id="cache-strategies">
<title>Understanding the cache abstraction</title>
<sidebar>
<title>Cache vs Buffer</title>
<para>The terms "buffer" and "cache" tend to be used interchangeably; note however they represent different things.
A buffer is used traditionally as an intermediate temporary store for data between a fast and a slow entity. As one
party would have to <emphasis>wait</emphasis> for the other affecting performance, the buffer alleviates this by
allowing entire blocks of data to move at once rather then in small chunks. The data is written and read only once from
the buffer. Furthermore, the buffers are <emphasis>visible</emphasis> to at least one party which is aware of it.</para>
<para>A cache on the other hand by definition is hidden and neither party is aware that caching occurs.It as well improves
performance but does that by allowing the same data to be read multiple times in a fast fashion.</para>
<para>A further explanation of the differences between two can be found
<ulink url="http://en.wikipedia.org/wiki/Cache#The_difference_between_buffer_and_cache">here</ulink>.</para>
</sidebar>
<para>At its core, the abstraction applies caching to Java methods, reducing thus the number of executions based on the
information available in the cache. That is, each time a <emphasis>targeted</emphasis> method is invoked, the abstraction
will apply a caching behaviour checking whether the method has been already executed for the given arguments. If it has,
then the cached result is returned without having to execute the actual method; if it has not, then method is executed, the
result cached and returned to the user so that, the next time the method is invoked, the cached result is returned.
This way, expensive methods (whether CPU or IO bound) can be executed only once for a given set of parameters and the result
reused without having to actually execute the method again. The caching logic is applied transparently without any interference
to the invoker.</para>
<important>Obviously this approach works only for methods that are guaranteed to return the same output (result) for a given input
(or arguments) no matter how many times it is being executed.</important>
<para>To use the cache abstraction, the developer needs to take care of two aspects:
<itemizedlist>
<listitem>caching declaration - identify the methods that need to be cached and their policy</listitem>
<listitem>cache configuration - the backing cache where the data is stored and read from</listitem>
</itemizedlist>
</para>
<para>Note that just like other services in Spring Framework, the caching service is an abstraction (not a cache implementation) and requires
the use of an actual storage to store the cache data - that is, the abstraction frees the developer from having to write the caching
logic but does not provide the actual stores. There are two integrations available out of the box, for JDK <literal>java.util.concurrent.ConcurrentMap</literal>
and <ulink url="http://ehcache.org/">Ehcache</ulink> - see <xref linkend="cache-plug"/> for more information on plugging in other cache stores/providers.</para>
</section>
<section id="cache-annotations">
<title>Declarative annotation-based caching</title>
<para>For caching declaration, the abstraction provides two Java annotations: <literal>@Cacheable</literal> and <literal>@CacheEvict</literal> which allow methods
to trigger cache population or cache eviction. Let us take a closer look at each annotation:</para>
<section id="cache-annotations-cacheable">
<title><literal>@Cacheable</literal> annotation</title>
<para>As the name implies, <literal>@Cacheable</literal> is used to demarcate methods that are cacheable - that is, methods for whom the result is stored into the cache
so on subsequent invocations (with the same arguments), the value in the cache is returned without having to actually execute the method. In its simplest form,
the annotation declaration requires the name of the cache associated with the annotated method:</para>
<programlisting language="java"><![CDATA[@Cacheable("books")
public Book findBook(ISBN isbn) {...}]]></programlisting>
<para>In the snippet above, the method <literal>findBook</literal> is associated with the cache named <literal>books</literal>. Each time the method is called, the cache
is checked to see whether the invocation has been already executed and does not have to be repeated. While in most cases, only one cache is declared, the annotation allows multiple
names to be specified so that more then one cache are being used. In this case, each of the caches will be checked before executing the method - if at least one cache is hit,
then the associated value will be returned:</para>
<note>All the other caches that do not contain the method will be updated as well even though the cached method was not actually
executed.</note>
<programlisting language="java"><![CDATA[@Cacheable({ "books", "isbns" })
public Book findBook(ISBN isbn) {...}]]></programlisting>
<section id="cache-annotations-cacheable-default-key">
<title>Default Key Generation</title>
<para>Since caches are essentially key-value stores, each invocation of a cached method needs to be translated into a suitable key for cache access.
Out of the box, the caching abstraction uses a simple <interfacename>KeyGenerator</interfacename> based on the following algorithm:</para>
<itemizedlist>
<listitem>If no params are given, return 0.</listitem>
<listitem>If only one param is given, return that instance.</listitem>
<listitem>If more the one param is given, return a key computed from the hashes of all parameters.</listitem>
</itemizedlist>
<para>
This approach works well for objects with <emphasis>natural keys</emphasis> as long as the <literal>hashCode()</literal> reflects that. If that is not the case then
for distributed or persistent environments, the strategy needs to be changed as the objects hashCode is not preserved.
In fact, depending on the JVM implementation or running conditions, the same hashCode can be reused for different objects, in the same VM instance.</para>
<para>To provide a different <emphasis>default</emphasis> key generator, one needs to implement the <interfacename>org.springframework.cache.KeyGenerator</interfacename> interface.
Once configured, the generator will be used for each declaration that doesn not specify its own key generation strategy (see below).
</para>
</section>
<section id="cache-annotations-cacheable-key">
<title>Custom Key Generation Declaration</title>
<para>Since caching is generic, it is quite likely the target methods have various signatures that cannot be simply mapped on top of the cache structure. This tends to become
obvious when the target method has multiple arguments out of which only some are suitable for caching (while the rest are used only by the method logic). For example:</para>
<programlisting language="java"><![CDATA[@Cacheable("books")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed]]></programlisting>
<para>At first glance, while the two <literal>boolean</literal> arguments influence the way the book is found, they are no use for the cache. Further more what if only one of the two
is important while the other is not?</para>
<para>For such cases, the <literal>@Cacheable</literal> annotation allows the user to specify how the key is generated through its <literal>key</literal> attribute.
The developer can use <link linkend="expressions">SpEL</link> to pick the arguments of interest (or their nested properties), perform operations or even invoke arbitrary methods without
having to write any code or implement any interface. This is the recommended approach over the <link linkend="cache-annotations-cacheable-default-key">default</link> generator since
methods tend to be quite different in signatures as the code base grows; while the default strategy might work for some methods, it rarely does for all methods.</para>
<para>
Below are some examples of various SpEL declarations - if you are not familiar with it, do yourself a favour and read <xref linkend="expressions"/>:
</para>
<programlisting language="java"><!-- select 'isbn' argument -->
@Cacheable(value="books", <emphasis role="bold">key="#isbn"</emphasis>
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
<!-- select nested property of a certain argument -->
@Cacheable(value="books", <emphasis role="bold">key="#isbn.rawNumber"</emphasis>)
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
<!-- invoke arbitrary method using certain arguments -->
@Cacheable(value="books", <emphasis role="bold">key="T(someType).hash(#isbn)"</emphasis>)
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)</programlisting>
<para>The snippets above, show how easy it is to select a certain argument, one of its properties or even an arbitrary (static) method.</para>
</section>
<section id="cache-annotations-cacheable-condition">
<title>Conditional caching</title>
<para>Sometimes, a method might not be suitable for caching all the time (for example, it might depend on the given arguments). The cache annotations support such functionality
through the <literal>conditional</literal> parameter which takes a <literal>SpEL</literal> expression that is evaluated to either <literal>true</literal> or <literal>false</literal>.
If <literal>true</literal>, the method is cached - if not, it behaves as if the method is not cached, that is executed every since time no matter what values are in the cache or what
arguments are used. A quick example - the following method will be cached, only if the argument <literal>name</literal> has a length shorter then 32:</para>
<programlisting language="java"><![CDATA[@Cacheable(value="book", condition="#name.length < 32")
public Book findBook(String name)]]></programlisting>
</section>
<section id="cache-spel-context">
<title>Available caching <literal>SpEL</literal> evaluation context</title>
<para>Each <literal>SpEL</literal> expression evaluates again a dedicated <literal><link linkend="expressions-language-ref">context</link></literal>. In addition
to the build in parameters, the framework provides dedicated caching related metadata such as the argument names. The next table lists the items made available to the context
so one can use them for key and conditional(see next section) computations:</para>
<table id="cache-spel-context-tbl" pgwide="1">
<title>Cache SpEL available metadata</title>
<tgroup cols="4">
<colspec align="center" />
<thead>
<row>
<entry>Name</entry>
<entry>Location</entry>
<entry>Description</entry>
<entry>Example</entry>
</row>
</thead>
<tbody>
<row>
<entry>methodName</entry>
<entry>root object</entry>
<entry>The name of the method being invoked</entry>
<entry><screen>#root.methodName</screen></entry>
</row>
<row>
<entry>method</entry>
<entry>root object</entry>
<entry>The method being invoked</entry>
<entry><screen>#root.method.name</screen></entry>
</row>
<row>
<entry>target</entry>
<entry>root object</entry>
<entry>The target object being invoked</entry>
<entry><screen>#root.target</screen></entry>
</row>
<row>
<entry>targetClass</entry>
<entry>root object</entry>
<entry>The class of the target being invoked</entry>
<entry><screen>#root.targetClass</screen></entry>
</row>
<row>
<entry>args</entry>
<entry>root object</entry>
<entry>The arguments (as array) used for invoking the target</entry>
<entry><screen>#root.args[0]</screen></entry>
</row>
<row>
<entry>caches</entry>
<entry>root object</entry>
<entry>Collection of caches against which the current method is executed</entry>
<entry><screen>#root.caches[0].name</screen></entry>
</row>
<row>
<entry><emphasis>argument name</emphasis></entry>
<entry>evaluation context</entry>
<entry>Name of any of the method argument. If for some reason the names are not available (ex: no debug information),
the argument names are also available under the <literal><![CDATA[a<#arg>]]></literal> where
<emphasis><![CDATA[#arg]]></emphasis> stands for the argument index (starting from 0).</entry>
<entry><screen>iban</screen> or <screen>a0</screen> (one can also use <screen>p0</screen> or <literal><![CDATA[p<#arg>]]></literal> notation as an alias).</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
</section>
<section id="cache-annotations-put">
<title><literal>@CachePut</literal> annotation</title>
<para>For cases where the cache needs to be updated without interferring with the method execution, one can use the <literal>@CachePut</literal> annotation. That is, the method will always
be executed and its result placed into the cache (according to the <literal>@CachePut</literal> options). It supports the same options as <literal>@Cacheable</literal> and should be used
for cache population rather then method flow optimization.</para>
<para>Note that using <literal>@CachePut</literal> and <literal>@Cacheable</literal> annotations on the same method is generaly discouraged because they have different behaviours. While the latter
causes the method execution to be skipped by using the cache, the former forces the execution in order to execute a cache update. This leads to unexpected behaviour and with the exception of specific
corner-cases (such as annotations having conditions that exclude them from each other), such declarations should be avoided.</para>
</section>
<section id="cache-annotations-evict">
<title><literal>@CacheEvict</literal> annotation</title>
<para>The cache abstraction allows not just population of a cache store but also eviction. This process is useful for removing stale or unused data from the cache. Opposed to
<literal>@Cacheable</literal>, annotation <literal>@CacheEvict</literal> demarcates methods that perform cache <emphasis>eviction</emphasis>, that is methods that act as triggers
for removing data from the cache. Just like its sibling, <literal>@CacheEvict</literal> requires one to specify one (or multiple) caches that are affected by the action, allows a
key or a condition to be specified but in addition, features an extra parameter <literal>allEntries</literal> which indicates whether a cache-wide eviction needs to be performed
rather then just an entry one (based on the key):</para>
<programlisting language="java"><![CDATA[@CacheEvict(value = "books", allEntries=true)
public void loadBooks(InputStream batch)]]></programlisting>
<para>This option comes in handy when an entire cache region needs to be cleared out - rather then evicting each entry (which would take a long time since it is inefficient),
all the entires are removed in one operation as shown above. Note that the framework will ignore any key specified in this scenario as it does not apply (the entire cache is evicted not just
one entry).</para>
<para>One can also indicate whether the eviction should occur after (the default) or before the method executes through the <literal>beforeInvocation</literal> attribute.
The former provides the same semantics as the rest of the annotations - once the method completes successfully, an action (in this case eviction) on the cache is executed. If the method does not
execute (as it might be cached) or an exception is thrown, the eviction does not occur. The latter (<literal>beforeInvocation=true</literal>) causes the eviction to occur always, before the method
is invoked - this is useful in cases where the eviction does not need to be tied to the method outcome.</para>
<para>It is important to note that void methods can be used with <literal>@CacheEvict</literal> - as the methods act as triggers, the return values are ignored (as they don't interact with
the cache) - this is not the case with <literal>@Cacheable</literal> which adds/update data into the cache and thus requires a result.</para>
</section>
<section id="cache-annotations-caching">
<title><literal>@Caching</literal> annotation</title>
<para>There are cases when multiple annotations of the same type, such as <literal>@CacheEvict</literal> or <literal>@CachePut</literal> need to be specified, for example because the condition or the key
expression is different between different caches. Unfortunately Java does not support such declarations however there is a workaround - using a <emphasis>enclosing</emphasis> annotation, in this case,
<literal>@Caching</literal>. <literal>@Caching</literal> allows multiple nested <literal>@Cacheable</literal>, <literal>@CachePut</literal> and <literal>@CacheEvict</literal> to be used on the same method:</para>
<programlisting language="java"><![CDATA[@Caching(evict = { @CacheEvict("primary"), @CacheEvict(value = "secondary", key = "#p0") })
public Book importBooks(String deposit, Date date)]]></programlisting>
</section>
<section id="cache-annotation-enable">
<title>Enable caching annotations</title>
<para>It is important to note that even though declaring the cache annotations does not automatically triggers their actions - like many things in Spring, the feature has to be declaratively
enabled (which means if you ever suspect caching is to blame, you can disable it by removing only one configuration line rather then all the annotations in your code). In practice, this
translates to one line that informs Spring that it should process the cache annotations, namely:</para>
<programlisting language="xml"><![CDATA[<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"]]>
<emphasis role="bold">xmlns:cache="http://www.springframework.org/schema/cache"</emphasis><![CDATA[
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd]]>
<emphasis role="bold">http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd</emphasis><![CDATA[">]]>
<emphasis role="bold"><![CDATA[<cache:annotation-driven />]]></emphasis>
<![CDATA[</beans>]]></programlisting>
<para>The namespace allows various options to be specified that influence the way the caching behaviour is added to the application through AOP. The configuration is similar (on purpose)
with that of <literal><ulink url="tx-annotation-driven-settings">tx:annotation-driven</ulink></literal>:
</para>
<para><table id="cache-annotation-driven-settings">
<title><literal>&lt;cache:annotation-driven/&gt;</literal>
settings</title>
<tgroup cols="3">
<thead>
<row>
<entry>Attribute</entry>
<entry>Default</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>cache-manager</literal></entry>
<entry>cacheManager</entry>
<entry><para>Name of cache manager to use. Only required
if the name of the cache manager is not
<literal>cacheManager</literal>, as in the example
above.</para></entry>
</row>
<row>
<entry><literal>mode</literal></entry>
<entry>proxy</entry>
<entry><para>The default mode "proxy" processes annotated
beans to be proxied using Spring's AOP framework (following
proxy semantics, as discussed above, applying to method calls
coming in through the proxy only). The alternative mode
"aspectj" instead weaves the affected classes with Spring's
AspectJ caching aspect, modifying the target class byte
code to apply to any kind of method call. AspectJ weaving
requires spring-aspects.jar in the classpath as well as
load-time weaving (or compile-time weaving) enabled. (See
<xref linkend="aop-aj-ltw-spring" /> for details on how to set
up load-time weaving.)</para></entry>
</row>
<row>
<entry><literal>proxy-target-class</literal></entry>
<entry>false</entry>
<entry><para>Applies to proxy mode only. Controls what type of
caching proxies are created for classes annotated with
the <interfacename>@Cacheable</interfacename> or <interfacename>@CacheEvict</interfacename> annotations.
If the <literal>proxy-target-class</literal> attribute is set
to <literal>true</literal>, then class-based proxies are
created. If <literal>proxy-target-class</literal> is
<literal>false</literal> or if the attribute is omitted, then
standard JDK interface-based proxies are created. (See <xref
linkend="aop-proxying" /> for a detailed examination of the
different proxy types.)</para></entry>
</row>
<row>
<entry><literal>order</literal></entry>
<entry>Ordered.LOWEST_PRECEDENCE</entry>
<entry><para>Defines the order of the cache advice that
is applied to beans annotated with
<interfacename>@Cacheable</interfacename> or <interfacename>@CacheEvict</interfacename>.
(For more
information about the rules related to ordering of AOP advice,
see <xref linkend="aop-ataspectj-advice-ordering" />.) No
specified ordering means that the AOP subsystem determines the
order of the advice.</para></entry>
</row>
</tbody>
</tgroup>
</table></para>
<note>
<para><literal>&lt;cache:annotation-driven/&gt;</literal> only looks for
<interfacename>@Cacheable/@CacheEvict</interfacename> on beans in the same
application context it is defined in. This means that, if you put
<literal>&lt;cache:annotation-driven/&gt;</literal> in a
<interfacename>WebApplicationContext</interfacename> for a
<classname>DispatcherServlet</classname>, it only checks for
<interfacename>@Cacheable/@CacheEvict</interfacename> beans in your
controllers, and not your services. See <xref
linkend="mvc-servlet" /> for more information.</para>
</note>
<sidebar>
<title>Method visibility and
<interfacename>@Cacheable/@CachePut/@CacheEvict</interfacename></title>
<para>When using proxies, you should apply the
<interfacename>@Cache*</interfacename> annotations only to
methods with <emphasis>public</emphasis> visibility. If you do
annotate protected, private or package-visible methods with these annotations,
no error is raised, but the annotated method does not exhibit the configured
caching settings. Consider the use of AspectJ (see below) if you
need to annotate non-public methods as it changes the bytecode itself.</para>
</sidebar>
<para><tip>
<para>Spring recommends that you only annotate concrete classes (and
methods of concrete classes) with the
<interfacename>@Cache*</interfacename> annotation, as opposed
to annotating interfaces. You certainly can place the
<interfacename>@Cache*</interfacename> annotation on an
interface (or an interface method), but this works only as you would
expect it to if you are using interface-based proxies. The fact that
Java annotations are <emphasis>not inherited from interfaces</emphasis>
means that if you are using class-based proxies
(<literal>proxy-target-class="true"</literal>) or the weaving-based
aspect (<literal>mode="aspectj"</literal>), then the caching
settings are not recognized by the proxying and weaving
infrastructure, and the object will not be wrapped in a
caching proxy, which would be decidedly
<emphasis>bad</emphasis>.</para>
</tip></para>
<note>
<para>In proxy mode (which is the default), only external method calls
coming in through the proxy are intercepted. This means that
self-invocation, in effect, a method within the target object calling
another method of the target object, will not lead to an actual
caching at runtime even if the invoked method is marked with
<interfacename>@Cacheable</interfacename> - considering using the aspectj mode in this case.</para>
</note>
</section>
<section id="cache-annotation-stereotype">
<title>Using custom annotations</title>
<para>The caching abstraction allows one to use her own annotations to identify what method trigger cache population or eviction. This is quite handy as a template mechanism as it eliminates
the need to duplicate cache annotation declarations (especially useful if the key or condition are specified) or if the foreign imports (<literal>org.springframework</literal>) are not allowed
in your code base. Similar to the rest of the <link linkend="beans-stereotype-annotations">stereotype</link> annotations, both <literal>@Cacheable</literal> and <literal>@CacheEvict</literal>
can be used as meta-annotations, that is annotations that can annotate other annotations. To wit, let us replace a common <literal>@Cacheable</literal> declaration with our own, custom
annotation:
</para>
<programlisting language="java"><![CDATA[@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Cacheable(value=“books”, key="#isbn")
public @interface SlowService {
}]]></programlisting>
<para>Above, we have defined our own <literal>SlowService</literal> annotation which itself is annotated with <literal>@Cacheable</literal> - now we can replace the following code:</para>
<programlisting language="java"><![CDATA[@Cacheable(value="books", key="#isbn")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)]]></programlisting>
<para>with:</para>
<programlisting language="java"><![CDATA[@SlowService
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)]]></programlisting>
<para>Even though <literal>@SlowService</literal> is not a Spring annotation, the container automatically picks up its declaration at runtime and understands its meaning. Note that as
mentined <link linkend="cache-annotation-enable">above</link>, the annotation-driven behaviour needs to be enabled.</para>
</section>
</section>
<section id="cache-declarative-xml">
<title>Declarative XML-based caching</title>
<para>If annotations are not an option (no access to the sources or no external code), one can use XML for declarative caching. So instead of annotating the methods for caching, one specifies
the target method and the caching directives externally (similar to the declarative transaction management <link linkend="transaction-declarative-first-example">advice</link>). The previous example
can be translated into:</para>
<programlisting language="xml"><![CDATA[<!-- the service we want to make cacheable -->
<bean id="bookService" class="x.y.service.DefaultBookService"/>
<!-- cache definitions -->
<cache:advice id="cacheAdvice" cache-manager="cacheManager">
<cache:caching cache="books">
<cache:cacheable method="findBook" key="#isbn"/>
<cache:cache-evict method="loadBooks" all-entries="true"/>
</cache:caching>
</cache:advice>
<!-- apply the cacheable behaviour to all BookService interfaces -->
<aop:config>
<aop:advisor advice-ref="cacheAdvice" pointcut="execution(* x.y.BookService.*(..))"/>
</aop:config>
...
// cache manager definition omitted
]]>
</programlisting>
<para>In the configuration above, the <literal>bookService</literal> is made cacheable. The caching semantics to apply are encapsulated in the <literal>cache:advice</literal> definition which
instructs method <literal>findBooks</literal> to be used for putting data into the cache while method <literal>loadBooks</literal> for evicting data. Both definitions are working against the
<literal>books</literal> cache.</para>
<para>The <literal>aop:config</literal> definition applies the cache advice to the appropriate points in the program by using the AspectJ pointcut expression (more information is available
in <xref linkend="aop" />). In the example above, all methods from the <interfacename>BookService</interfacename> are considered and the cache advice applied to them.</para>
<para>The declarative XML caching supports all of the annotation-based model so moving between the two should be fairly easy - further more both can be used inside the same application.
The XML based approach does not touch the target code however it is inherently more verbose; when dealing with classes with overloaded methods that are targeted for caching, identifying the
proper methods does take an extra effort since the <literal>method</literal> argument is not a good discriminator - in these cases, the AspectJ pointcut can be used to cherry pick the target
methods and apply the appropriate caching functionality. Howeve through XML, it is easier to apply a package/group/interface-wide caching (again due to the AspectJ poincut) and to create
template-like definitions (as we did in the example above by defining the target cache through the <literal>cache:definitions </literal><literal>cache</literal> attribute).
</para>
</section>
<section id="cache-store-configuration">
<title>Configuring the cache storage</title>
<para>Out of the box, the cache abstraction provides integration with two storages - one on top of the JDK <interfacename>ConcurrentMap</interfacename> and one
for <ulink url="ehcache.org">ehcache</ulink> library. To use them, one needs to simply declare an appropriate <interfacename>CacheManager</interfacename> - an entity that controls and manages
<interfacename>Cache</interfacename>s and can be used to retrieve these for storage.</para>
<section id="cache-store-configuration-jdk">
<title>JDK <interfacename>ConcurrentMap</interfacename>-based <interfacename>Cache</interfacename></title>
<para>The JDK-based <interfacename>Cache</interfacename> implementation resides under <literal>org.springframework.cache.concurrent</literal> package. It allows one to use <classname>
ConcurrentHashMap</classname> as a backing <interfacename>Cache</interfacename> store.</para>
<programlisting language="xml"><![CDATA[<!-- generic cache manager -->
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="default"/>
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="books"/>
</set>
</property>
</bean>]]></programlisting>
<para>The snippet above uses the <classname>SimpleCacheManager</classname> to create a <interfacename>CacheManager</interfacename> for the two, nested <interfacename>Concurrent</interfacename>
<interfacename>Cache</interfacename> implementations named <emphasis>default</emphasis> and <emphasis>books</emphasis>.
Note that the names are configured directly for each cache.</para>
<para>As the cache is created by the application, it is bound to its lifecycle, making it suitable for basic use cases, tests or simple applications. The cache scales well and is very fast
but it does not provide any management or persistence capabilities nor eviction contracts.</para>
</section>
<section id="cache-store-configuration-ehcache">
<title>Ehcache-based <interfacename>Cache</interfacename></title>
<para>The Ehcache implementation is located under <literal>org.springframework.cache.ehcache</literal> package. Again, to use it, one simply needs to declare the appropriate
<interfacename>CacheManager</interfacename>:</para>
<programlisting language="xml"><![CDATA[<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcache"/>
<!-- Ehcache library setup -->
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:config-location="ehcache.xml"/>]]></programlisting>
<para>This setup bootstraps ehcache library inside Spring IoC (through bean <literal>ehcache</literal>) which is then wired into the dedicated <interfacename>CacheManager</interfacename>
implementation. Note the entire ehcache-specific configuration is read from the resource <literal>ehcache.xml</literal>.</para>
</section>
<section id="cache-store-configuration-noop">
<title>Dealing with caches without a backing store</title>
<para>Sometimes when switching environments or doing testing, one might have cache declarations without an actual backing cache configured. As this is an invalid configuration, at runtime an
exception will be through since the caching infrastructure is unable to find a suitable store. In situations like this, rather then removing the cache declarations (which can prove tedious),
one can wire in a simple, dummy cache that performs no caching - that is, forces the cached methods to be executed every time:</para>
<programlisting language="xml"><![CDATA[<bean id="cacheManager" class="org.springframework.cache.support.CompositeCacheManager">
<property name="cacheManagers"><list>
<ref bean="jdkCache"/>
<ref bean="gemfireCache"/>
</list></property>
<property name="addNoOpCache" value="true"/>
</bean>]]></programlisting>
<para>The <literal>CompositeCacheManager</literal> above chains multiple <literal>CacheManager</literal>s and aditionally, through the <literal>addNoOpManager</literal> flag, adds a
<emphasis>no op</emphasis> cache that for all the definitions not handled by the configured cache managers. That is, every cache definition not found in either <literal>jdkCache</literal>
or <literal>gemfireCache</literal> (configured above) will be handled by the no op cache, which will not store any information causing the target method to be executed every time.
</para>
</section>
</section>
<section id="cache-plug">
<title>Plugging-in different back-end caches</title>
<para>Clearly there are plenty of caching products out there that can be used as a backing store. To plug them in, one needs to provide a <interfacename>CacheManager</interfacename> and
<interfacename>Cache</interfacename> implementation since unfortunately there is no available standard that we can use instead. This may sound harder then it is since in practice,
the classes tend to be simple <ulink url="http://en.wikipedia.org/wiki/Adapter_pattern">adapter</ulink>s that map the caching abstraction framework on top of the storage API as the <literal>ehcache</literal> classes can show.
Most <interfacename>CacheManager</interfacename> classes can use the classes in <literal>org.springframework.cache.support</literal> package, such as <classname>AbstractCacheManager</classname>
which takes care of the boiler-plate code leaving only the actual <emphasis>mapping</emphasis> to be completed. We hope that in time, the libraries that provide integration with Spring
can fill in this small configuration gap.</para>
</section>
<section id="cache-specific-config">
<title>How can I set the TTL/TTI/Eviction policy/XXX feature?</title>
<para>Directly through your cache provider. The cache abstraction is... well, an abstraction not a cache implementation. The solution you are using might support various data policies and different
topologies which other solutions do not (take for example the JDK <literal>ConcurrentHashMap</literal>) - exposing that in the cache abstraction would be useless simply because there would
no backing support. Such functionality should be controlled directly through the backing cache, when configuring it or through its native API.
</para>
</section>
</chapter>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,453 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<appendix id="classic-spring">
<title>Classic Spring Usage</title>
<para>This appendix discusses some classic Spring usage patterns as a
reference for developers maintaining legacy Spring applications. These usage
patterns no longer reflect the recommended way of using these features and
the current recommended usage is covered in the respective sections of the
reference manual.</para>
<section id="classic-spring-orm">
<title>Classic ORM usage</title>
<para>This section documents the classic usage patterns that you might
encounter in a legacy Spring application. For the currently recommended
usage patterns, please refer to the <xref linkend="orm" /> chapter.</para>
<section id="classic-spring-hibernate">
<title>Hibernate</title>
<para>For the currently recommended usage patterns for Hibernate see
<xref linkend="orm-hibernate" /></para>
<section id="orm-hibernate-template">
<title>The <classname>HibernateTemplate</classname></title>
<para>The basic programming model for templating looks as follows, for
methods that can be part of any custom data access object or business
service. There are no restrictions on the implementation of the
surrounding object at all, it just needs to provide a Hibernate
<interfacename>SessionFactory</interfacename>. It can get the latter
from anywhere, but preferably as bean reference from a Spring IoC
container - via a simple
<methodname>setSessionFactory(..)</methodname> bean property setter.
The following snippets show a DAO definition in a Spring container,
referencing the above defined
<interfacename>SessionFactory</interfacename>, and an example for a
DAO method implementation.</para>
<programlisting language="xml">&lt;beans&gt;
&lt;bean id="myProductDao" class="product.ProductDaoImpl"&gt;
&lt;property name="sessionFactory" ref="mySessionFactory"/&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting>
<programlisting language="java">public class ProductDaoImpl implements ProductDao {
private HibernateTemplate hibernateTemplate;
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
public Collection loadProductsByCategory(String category) throws DataAccessException {
return this.hibernateTemplate.find("from test.Product product where product.category=?", category);
}
}</programlisting>
<para>The <classname>HibernateTemplate</classname> class provides many
methods that mirror the methods exposed on the Hibernate
<interfacename>Session</interfacename> interface, in addition to a
number of convenience methods such as the one shown above. If you need
access to the <interfacename>Session</interfacename> to invoke methods
that are not exposed on the <classname>HibernateTemplate</classname>,
you can always drop down to a callback-based approach like so.</para>
<programlisting language="java">public class ProductDaoImpl implements ProductDao {
private HibernateTemplate hibernateTemplate;
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
public Collection loadProductsByCategory(final String category) throws DataAccessException {
return this.hibernateTemplate.execute(new HibernateCallback() {
public Object doInHibernate(Session session) {
Criteria criteria = session.createCriteria(Product.class);
criteria.add(Expression.eq("category", category));
criteria.setMaxResults(6);
return criteria.list();
}
};
}
}</programlisting>
<para>A callback implementation effectively can be used for any
Hibernate data access. <classname>HibernateTemplate</classname> will
ensure that <interfacename>Session</interfacename> instances are
properly opened and closed, and automatically participate in
transactions. The template instances are thread-safe and reusable,
they can thus be kept as instance variables of the surrounding class.
For simple single step actions like a single find, load, saveOrUpdate,
or delete call, <classname>HibernateTemplate</classname> offers
alternative convenience methods that can replace such one line
callback implementations. Furthermore, Spring provides a convenient
<classname>HibernateDaoSupport</classname> base class that provides a
<methodname>setSessionFactory(..)</methodname> method for receiving a
<interfacename>SessionFactory</interfacename>, and
<methodname>getSessionFactory()</methodname> and
<methodname>getHibernateTemplate()</methodname>for use by subclasses.
In combination, this allows for very simple DAO implementations for
typical requirements:</para>
<programlisting language="java">public class ProductDaoImpl extends HibernateDaoSupport implements ProductDao {
public Collection loadProductsByCategory(String category) throws DataAccessException {
return this.getHibernateTemplate().find(
"from test.Product product where product.category=?", category);
}
}</programlisting>
</section>
<section id="orm-hibernate-daos">
<title>Implementing Spring-based DAOs without callbacks</title>
<para>As alternative to using Spring's
<classname>HibernateTemplate</classname> to implement DAOs, data
access code can also be written in a more traditional fashion, without
wrapping the Hibernate access code in a callback, while still
respecting and participating in Spring's generic
<classname>DataAccessException</classname> hierarchy. The
<classname>HibernateDaoSupport</classname> base class offers methods
to access the current transactional
<interfacename>Session</interfacename> and to convert exceptions in
such a scenario; similar methods are also available as static helpers
on the <classname>SessionFactoryUtils</classname> class. Note that
such code will usually pass '<literal>false</literal>' as the value of
the <methodname>getSession(..)</methodname> methods
'<literal>allowCreate</literal>' argument, to enforce running within a
transaction (which avoids the need to close the returned
<interfacename>Session</interfacename>, as its lifecycle is managed by
the transaction).</para>
<programlisting language="java">public class HibernateProductDao extends HibernateDaoSupport implements ProductDao {
public Collection loadProductsByCategory(String category) throws DataAccessException, MyException {
Session session = getSession(false);
try {
Query query = session.createQuery("from test.Product product where product.category=?");
query.setString(0, category);
List result = query.list();
if (result == null) {
throw new MyException("No search results.");
}
return result;
}
catch (HibernateException ex) {
throw convertHibernateAccessException(ex);
}
}
}</programlisting>
<para>The advantage of such direct Hibernate access code is that it
allows <emphasis>any</emphasis> checked application exception to be
thrown within the data access code; contrast this to the
<classname>HibernateTemplate</classname> class which is restricted to
throwing only unchecked exceptions within the callback. Note that you
can often defer the corresponding checks and the throwing of
application exceptions to after the callback, which still allows
working with <classname>HibernateTemplate</classname>. In general, the
<classname>HibernateTemplate</classname> class' convenience methods
are simpler and more convenient for many scenarios.</para>
</section>
</section>
<section id="classic-spring-jdo">
<title>JDO</title>
<para>For the currently recommended usage patterns for JDO see <xref
linkend="orm-jdo" /></para>
<section id="orm-jdo-template">
<title><classname>JdoTemplate</classname> and
<classname>JdoDaoSupport</classname></title>
<para>Each JDO-based DAO will then receive the
<interfacename>PersistenceManagerFactory</interfacename> through
dependency injection. Such a DAO could be coded against plain JDO API,
working with the given
<interfacename>PersistenceManagerFactory</interfacename>, but will
usually rather be used with the Spring Framework's
<classname>JdoTemplate</classname>:</para>
<programlisting language="xml">&lt;beans&gt;
&lt;bean id="myProductDao" class="product.ProductDaoImpl"&gt;
&lt;property name="persistenceManagerFactory" ref="myPmf"/&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting>
<programlisting language="java">public class ProductDaoImpl implements ProductDao {
private JdoTemplate jdoTemplate;
public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
this.jdoTemplate = new JdoTemplate(pmf);
}
public Collection loadProductsByCategory(final String category) throws DataAccessException {
return (Collection) this.jdoTemplate.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm) throws JDOException {
Query query = pm.newQuery(Product.class, "category = pCategory");
query.declareParameters("String pCategory");
List result = query.execute(category);
<lineannotation>// do some further stuff with the result list</lineannotation>
return result;
}
});
}
}</programlisting>
<para>A callback implementation can effectively be used for any JDO
data access. <classname>JdoTemplate</classname> will ensure that
<classname>PersistenceManager</classname>s are properly opened and
closed, and automatically participate in transactions. The template
instances are thread-safe and reusable, they can thus be kept as
instance variables of the surrounding class. For simple single-step
actions such as a single <literal>find</literal>,
<literal>load</literal>, <literal>makePersistent</literal>, or
<literal>delete</literal> call, <classname>JdoTemplate</classname>
offers alternative convenience methods that can replace such one line
callback implementations. Furthermore, Spring provides a convenient
<classname>JdoDaoSupport</classname> base class that provides a
<literal>setPersistenceManagerFactory(..)</literal> method for
receiving a <classname>PersistenceManagerFactory</classname>, and
<methodname>getPersistenceManagerFactory()</methodname> and
<methodname>getJdoTemplate()</methodname> for use by subclasses. In
combination, this allows for very simple DAO implementations for
typical requirements:</para>
<programlisting language="java">public class ProductDaoImpl extends JdoDaoSupport implements ProductDao {
public Collection loadProductsByCategory(String category) throws DataAccessException {
return getJdoTemplate().find(
Product.class, "category = pCategory", "String category", new Object[] {category});
}
}</programlisting>
<para>As alternative to working with Spring's
<classname>JdoTemplate</classname>, you can also code Spring-based
DAOs at the JDO API level, explicitly opening and closing a
<interfacename>PersistenceManager</interfacename>. As elaborated in
the corresponding Hibernate section, the main advantage of this
approach is that your data access code is able to throw checked
exceptions. <classname>JdoDaoSupport</classname> offers a variety of
support methods for this scenario, for fetching and releasing a
transactional <interfacename>PersistenceManager</interfacename> as
well as for converting exceptions.</para>
</section>
</section>
<section id="classic-spring-jpa">
<title>JPA</title>
<para>For the currently recommended usage patterns for JPA see <xref
linkend="orm-jpa" /></para>
<section id="orm-jpa-template">
<title><classname>JpaTemplate</classname> and
<classname>JpaDaoSupport</classname></title>
<para>Each JPA-based DAO will then receive a
<interfacename>EntityManagerFactory</interfacename> via dependency
injection. Such a DAO can be coded against plain JPA and work with the
given <interfacename>EntityManagerFactory</interfacename> or through
Spring's <classname>JpaTemplate</classname>:</para>
<programlisting language="xml">&lt;beans&gt;
&lt;bean id="myProductDao" class="product.ProductDaoImpl"&gt;
&lt;property name="entityManagerFactory" ref="myEmf"/&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting>
<programlisting language="java">public class JpaProductDao implements ProductDao {
private JpaTemplate jpaTemplate;
public void setEntityManagerFactory(EntityManagerFactory emf) {
this.jpaTemplate = new JpaTemplate(emf);
}
public Collection loadProductsByCategory(final String category) throws DataAccessException {
return (Collection) this.jpaTemplate.execute(new JpaCallback() {
public Object doInJpa(EntityManager em) throws PersistenceException {
Query query = em.createQuery("from Product as p where p.category = :category");
query.setParameter("category", category);
List result = query.getResultList();
<lineannotation>// do some further processing with the result list</lineannotation>
return result;
}
});
}
}</programlisting>
<para>The <interfacename>JpaCallback</interfacename> implementation
allows any type of JPA data access. The
<classname>JpaTemplate</classname> will ensure that
<interfacename>EntityManager</interfacename>s are properly opened and
closed and automatically participate in transactions. Moreover, the
<classname>JpaTemplate</classname> properly handles exceptions, making
sure resources are cleaned up and the appropriate transactions rolled
back. The template instances are thread-safe and reusable and they can
be kept as instance variable of the enclosing class. Note that
<classname>JpaTemplate</classname> offers single-step actions such as
find, load, merge, etc along with alternative convenience methods that
can replace one line callback implementations.</para>
<para>Furthermore, Spring provides a convenient
<classname>JpaDaoSupport</classname> base class that provides the
<literal>get/setEntityManagerFactory</literal> and
<methodname>getJpaTemplate()</methodname> to be used by
subclasses:</para>
<programlisting language="java">public class ProductDaoImpl extends JpaDaoSupport implements ProductDao {
public Collection loadProductsByCategory(String category) throws DataAccessException {
Map&lt;String, String&gt; params = new HashMap&lt;String, String&gt;();
params.put("category", category);
return getJpaTemplate().findByNamedParams("from Product as p where p.category = :category", params);
}
}</programlisting>
<para>Besides working with Spring's
<classname>JpaTemplate</classname>, one can also code Spring-based
DAOs against the JPA, doing one's own explicit
<interfacename>EntityManager</interfacename> handling. As also
elaborated in the corresponding Hibernate section, the main advantage
of this approach is that your data access code is able to throw
checked exceptions. <classname>JpaDaoSupport</classname> offers a
variety of support methods for this scenario, for retrieving and
releasing a transaction <interfacename>EntityManager</interfacename>,
as well as for converting exceptions.</para>
<para><emphasis>JpaTemplate mainly exists as a sibling of JdoTemplate
and HibernateTemplate, offering the same style for people used to
it.</emphasis></para>
</section>
</section>
</section>
<section id="clasic-spring-mvc">
<title>Classic Spring MVC</title>
<para>...</para>
</section>
<section>
<title>JMS Usage</title>
<para>One of the benefits of Spring's JMS support is to shield the user
from differences between the JMS 1.0.2 and 1.1 APIs. (For a description of
the differences between the two APIs see sidebar on Domain Unification).
Since it is now common to encounter only the JMS 1.1 API the use of
classes that are based on the JMS 1.0.2 API has been deprecated in Spring
3.0. This section describes Spring JMS support for the JMS 1.0.2
deprecated classes. </para>
<sidebar>
<title>Domain Unification</title>
<para>There are two major releases of the JMS specification, 1.0.2 and
1.1.</para>
<para>JMS 1.0.2 defined two types of messaging domains, point-to-point
(Queues) and publish/subscribe (Topics). The 1.0.2 API reflected these
two messaging domains by providing a parallel class hierarchy for each
domain. As a result, a client application became domain specific in its
use of the JMS API. JMS 1.1 introduced the concept of domain unification
that minimized both the functional differences and client API
differences between the two domains. As an example of a functional
difference that was removed, if you use a JMS 1.1 provider you can
transactionally consume a message from one domain and produce a message
on the other using the same
<interfacename>Session</interfacename>.</para>
<note>
<para>The JMS 1.1 specification was released in April 2002 and
incorporated as part of J2EE 1.4 in November 2003. As a result, common
J2EE 1.3 application servers which are still in widespread use (such
as BEA WebLogic 8.1 and IBM WebSphere 5.1) are based on JMS
1.0.2.</para>
</note>
</sidebar>
<section>
<title>JmsTemplate</title>
<para>Located in the package
<literal>org.springframework.jms.core</literal> the class
<classname>JmsTemplate102</classname> provides all of the features of
the <classname>JmsTemplate</classname> described the JMS chapter, but is
based on the JMS 1.0.2 API instead of the JMS 1.1 API. As a consequence,
if you are using JmsTemplate102 you need to set the boolean property
<property>pubSubDomain</property> to configure the
<classname>JmsTemplate</classname> with knowledge of what JMS domain is
being used. By default the value of this property is false, indicating
that the point-to-point domain, Queues, will be used.</para>
</section>
<section>
<title>Asynchronous Message Reception </title>
<para><link
linkend="jms-receiving-async-message-listener-adapter">MessageListenerAdapter's</link>
are used in conjunction with Spring's <link linkend="jms-mdp">message
listener containers</link> to support asynchronous message reception by
exposing almost any class as a Message-driven POJO. If you are using the
JMS 1.0.2 API, you will want to use the 1.0.2 specific classes such as
<classname>MessageListenerAdapter102</classname>,
<classname>SimpleMessageListenerContainer102</classname>, and
<classname>DefaultMessageListenerContainer102</classname>. These classes
provide the same functionality as the JMS 1.1 based counterparts but
rely only on the JMS 1.0.2 API. </para>
</section>
<section>
<title>Connections</title>
<para>The <classname>ConnectionFactory</classname> interface is part of
the JMS specification and serves as the entry point for working with
JMS. Spring provides an implementation of the
<classname>ConnectionFactory</classname> interface,
<classname>SingleConnectionFactory102</classname>, based on the JMS
1.0.2 API that will return the same <classname>Connection</classname> on
all <methodname>createConnection()</methodname> calls and ignore calls to
<methodname>close()</methodname>. You will need to set the boolean
property <property>pubSubDomain</property> to indicate which messaging
domain is used as <classname>SingleConnectionFactory102</classname> will
always explicitly differentiate between a
<classname>javax.jms.QueueConnection</classname> and a
<classname>javax.jmsTopicConnection</classname>.</para>
</section>
<section>
<title>Transaction Management</title>
<para>In a JMS 1.0.2 environment the class
<classname>JmsTransactionManager102</classname> provides support for
managing JMS transactions for a single Connection Factory. Please refer
to the reference documentation on <link linkend="jms-tx">JMS Transaction
Management</link> for more information on this functionality.</para>
</section>
</section>
</appendix>

View File

@@ -0,0 +1,151 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="dao">
<title>DAO support</title>
<section id="dao-introduction">
<title>Introduction</title>
<para>The Data Access Object (DAO) support in Spring is aimed at making it
easy to work with data access technologies like JDBC, Hibernate, JPA or
JDO in a consistent way. This allows one to switch between the
aforementioned persistence technologies fairly easily and it also allows
one to code without worrying about catching exceptions that are specific
to each technology.</para>
</section>
<section id="dao-exceptions">
<title>Consistent exception hierarchy</title>
<para>Spring provides a convenient translation from technology-specific
exceptions like <classname>SQLException</classname> to its own exception
class hierarchy with the <classname>DataAccessException</classname> as the
root exception. These exceptions wrap the original exception so there is
never any risk that one might lose any information as to what might have
gone wrong.</para>
<para>In addition to JDBC exceptions, Spring can also wrap
Hibernate-specific exceptions, converting them from proprietary, checked
exceptions (in the case of versions of Hibernate prior to Hibernate 3.0),
to a set of focused runtime exceptions (the same is true for JDO and JPA
exceptions). This allows one to handle most persistence exceptions, which
are non-recoverable, only in the appropriate layers, without having
annoying boilerplate catch-and-throw blocks and exception declarations in
one's DAOs. (One can still trap and handle exceptions anywhere one needs
to though.) As mentioned above, JDBC exceptions (including
database-specific dialects) are also converted to the same hierarchy,
meaning that one can perform some operations with JDBC within a consistent
programming model.</para>
<para>The above holds true for the various template classes in Springs
support for various ORM frameworks. If one uses the interceptor-based
classes then the application must care about handling
<classname>HibernateExceptions</classname> and
<classname>JDOExceptions</classname> itself, preferably via delegating to
<classname>SessionFactoryUtils</classname>'
<methodname>convertHibernateAccessException(..)</methodname> or
<methodname>convertJdoAccessException()</methodname> methods respectively.
These methods convert the exceptions to ones that are compatible with the
exceptions in the <literal>org.springframework.dao</literal> exception
hierarchy. As <classname>JDOExceptions</classname> are unchecked, they can
simply get thrown too, sacrificing generic DAO abstraction in terms of
exceptions though.</para>
<para>The exception hierarchy that Spring provides can be seen below.
(Please note that the class hierarchy detailed in the image shows only a
subset of the entire <classname>DataAccessException</classname>
hierarchy.)</para>
<mediaobject>
<imageobject>
<imagedata align="center" fileref="images/DataAccessException.gif" />
</imageobject>
</mediaobject>
</section>
<section id="dao-annotations">
<title>Annotations used for configuring DAO or Repository classes</title>
<para>The best way to guarantee that your Data Access Objects (DAOs) or
repositories provide exception translation is to use the
<interfacename>@Repository</interfacename> annotation. This annotation
also allows the component scanning support to find and configure your DAOs
and repositories without having to provide XML configuration entries for
them.</para>
<programlisting language="java"><emphasis role="bold">@Repository</emphasis>
public class SomeMovieFinder implements MovieFinder {
// ...
}</programlisting>
<para>Any DAO or repository implementation will need to access to a
persistence resource, depending on the persistence technology used; for
example, a JDBC-based repository will need access to a JDBC
<interfacename>DataSource</interfacename>; a JPA-based repository will need
access to an <interfacename>EntityManager</interfacename>. The easiest way
to accomplish this is to have this resource dependency injected using one of
the <interfacename>@Autowired,</interfacename>, <interfacename>@Inject</interfacename>,
<interfacename>@Resource</interfacename> or
<interfacename>@PersistenceContext</interfacename> annotations. Here is an
example for a JPA repository:</para>
<programlisting language="java">@Repository
public class JpaMovieFinder implements MovieFinder {
@PersistenceContext
private EntityManager entityManager;
// ...
}</programlisting>
<para>If you are using the classic Hibernate APIs than you can inject the
SessionFactory:</para>
<programlisting language="java">@Repository
public class HibernateMovieFinder implements MovieFinder {
private SessionFactory sessionFactory;
@Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
// ...
}</programlisting>
<para>Last example we will show here is for typical JDBC support. You
would have the <classname>DataSource</classname> injected into an
initialization method where you would create a
<classname>JdbcTemplate</classname> and other data access support classes
like <classname>SimpleJdbcCall</classname> etc using this
<classname>DataSource</classname>.</para>
<programlisting language="java">@Repository
public class JdbcMovieFinder implements MovieFinder {
private JdbcTemplate jdbcTemplate;
@Autowired
public void init(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
// ...
}</programlisting>
<note>
<para>Please see the specific coverage of each persistence technology
for details on how to configure the application context to take
advantage of these annotations.</para>
</note>
<para></para>
</section>
</chapter>

View File

@@ -0,0 +1,684 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<appendix id="springbeansdtd">
<title><literal>spring-beans-2.0.dtd</literal></title>
<para><programlisting language="xml">&lt;!--
Spring XML Beans DTD, version 2.0
Authors: Rod Johnson, Juergen Hoeller, Alef Arendsen, Colin Sampaleanu, Rob Harrop
This defines a simple and consistent way of creating a namespace
of JavaBeans objects, managed by a Spring BeanFactory, read by
XmlBeanDefinitionReader (with DefaultBeanDefinitionDocumentReader).
This document type is used by most Spring functionality, including
web application contexts, which are based on bean factories.
Each "bean" element in this document defines a JavaBean.
Typically the bean class is specified, along with JavaBean properties
and/or constructor arguments.
A bean instance can be a "singleton" (shared instance) or a "prototype"
(independent instance). Further scopes can be provided by extended
bean factories, for example in a web environment.
References among beans are supported, that is, setting a JavaBean property
or a constructor argument to refer to another bean in the same factory
(or an ancestor factory).
As alternative to bean references, "inner bean definitions" can be used.
Singleton flags of such inner bean definitions are effectively ignored:
Inner beans are typically anonymous prototypes.
There is also support for lists, sets, maps, and java.util.Properties
as bean property types or constructor argument types.
For simple purposes, this DTD is sufficient. As of Spring 2.0,
XSD-based bean definitions are supported as more powerful alternative.
XML documents that conform to this DTD should declare the following doctype:
&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
-->
&lt;!--
The document root. A document can contain bean definitions only,
imports only, or a mixture of both (typically with imports first).
-->
&lt;!ELEMENT beans (
description?,
(import | alias | bean)*
)>
&lt;!--
Default values for all bean definitions. Can be overridden at
the "bean" level. See those attribute definitions for details.
-->
&lt;!ATTLIST beans default-lazy-init (true | false) "false">
&lt;!ATTLIST beans default-autowire (no | byName | byType | constructor | autodetect) "no">
&lt;!ATTLIST beans default-dependency-check (none | objects | simple | all) "none">
&lt;!ATTLIST beans default-init-method CDATA #IMPLIED>
&lt;!ATTLIST beans default-destroy-method CDATA #IMPLIED>
&lt;!ATTLIST beans default-merge (true | false) "false">
&lt;!--
Element containing informative text describing the purpose of the enclosing
element. Always optional.
Used primarily for user documentation of XML bean definition documents.
-->
&lt;!ELEMENT description (#PCDATA)>
&lt;!--
Specifies an XML bean definition resource to import.
-->
&lt;!ELEMENT import EMPTY>
&lt;!--
The relative resource location of the XML bean definition file to import,
for example "myImport.xml" or "includes/myImport.xml" or "../myImport.xml".
-->
&lt;!ATTLIST import resource CDATA #REQUIRED>
&lt;!--
Defines an alias for a bean, which can reside in a different definition file.
-->
&lt;!ELEMENT alias EMPTY>
&lt;!--
The name of the bean to define an alias for.
-->
&lt;!ATTLIST alias name CDATA #REQUIRED>
&lt;!--
The alias name to define for the bean.
-->
&lt;!ATTLIST alias alias CDATA #REQUIRED>
&lt;!--
Allows for arbitrary metadata to be attached to a bean definition.
-->
&lt;!ELEMENT meta EMPTY>
&lt;!--
Specifies the key name of the metadata parameter being defined.
-->
&lt;!ATTLIST meta key CDATA #REQUIRED>
&lt;!--
Specifies the value of the metadata parameter being defined as a String.
-->
&lt;!ATTLIST meta value CDATA #REQUIRED>
&lt;!--
Defines a single (usually named) bean.
A bean definition may contain nested tags for constructor arguments,
property values, lookup methods, and replaced methods. Mixing constructor
injection and setter injection on the same bean is explicitly supported.
-->
&lt;!ELEMENT bean (
description?,
(meta | constructor-arg | property | lookup-method | replaced-method)*
)>
&lt;!--
Beans can be identified by an id, to enable reference checking.
There are constraints on a valid XML id: if you want to reference your bean
in Java code using a name that's illegal as an XML id, use the optional
"name" attribute. If neither is given, the bean class name is used as id
(with an appended counter like "#2" if there is already a bean with that name).
-->
&lt;!ATTLIST bean id ID #IMPLIED>
&lt;!--
Optional. Can be used to create one or more aliases illegal in an id.
Multiple aliases can be separated by any number of spaces, commas, or
semi-colons (or indeed any mixture of the three).
-->
&lt;!ATTLIST bean name CDATA #IMPLIED>
&lt;!--
Each bean definition must specify the fully qualified name of the class,
except if it pure serves as parent for child bean definitions.
-->
&lt;!ATTLIST bean class CDATA #IMPLIED>
&lt;!--
Optionally specify a parent bean definition.
Will use the bean class of the parent if none specified, but can
also override it. In the latter case, the child bean class must be
compatible with the parent, i.e. accept the parent's property values
and constructor argument values, if any.
A child bean definition will inherit constructor argument values,
property values and method overrides from the parent, with the option
to add new values. If init method, destroy method, factory bean and/or factory
method are specified, they will override the corresponding parent settings.
The remaining settings will always be taken from the child definition:
depends on, autowire mode, dependency check, scope, lazy init.
-->
&lt;!ATTLIST bean parent CDATA #IMPLIED>
&lt;!--
The scope of this bean: typically "singleton" (one shared instance,
which will be returned by all calls to getBean() with the id),
or "prototype" (independent instance resulting from each call to
getBean(). Default is "singleton".
Singletons are most commonly used, and are ideal for multi-threaded
service objects. Further scopes, such as "request" or "session",
might be supported by extended bean factories (for example, in a
web environment).
Note: This attribute will not be inherited by child bean definitions.
Hence, it needs to be specified per concrete bean definition.
Inner bean definitions inherit the singleton status of their containing
bean definition, unless explicitly specified: The inner bean will be a
singleton if the containing bean is a singleton, and a prototype if
the containing bean has any other scope.
-->
&lt;!ATTLIST bean scope CDATA #IMPLIED>
&lt;!--
Is this bean "abstract", i.e. not meant to be instantiated itself but
rather just serving as parent for concrete child bean definitions.
Default is "false". Specify "true" to tell the bean factory to not try to
instantiate that particular bean in any case.
Note: This attribute will not be inherited by child bean definitions.
Hence, it needs to be specified per abstract bean definition.
-->
&lt;!ATTLIST bean abstract (true | false) #IMPLIED>
&lt;!--
If this bean should be lazily initialized.
If false, it will get instantiated on startup by bean factories
that perform eager initialization of singletons.
Note: This attribute will not be inherited by child bean definitions.
Hence, it needs to be specified per concrete bean definition.
-->
&lt;!ATTLIST bean lazy-init (true | false | default) "default">
&lt;!--
Indicates whether or not this bean should be considered when looking
for candidates to satisfy another beans autowiring requirements.
-->
&lt;!ATTLIST bean autowire-candidate (true | false) #IMPLIED>
&lt;!--
Optional attribute controlling whether to "autowire" bean properties.
This is an automagical process in which bean references don't need to be coded
explicitly in the XML bean definition file, but Spring works out dependencies.
There are 5 modes:
1. "no"
The traditional Spring default. No automagical wiring. Bean references
must be defined in the XML file via the &lt;ref> element. We recommend this
in most cases as it makes documentation more explicit.
2. "byName"
Autowiring by property name. If a bean of class Cat exposes a dog property,
Spring will try to set this to the value of the bean "dog" in the current factory.
If there is no matching bean by name, nothing special happens;
use dependency-check="objects" to raise an error in that case.
3. "byType"
Autowiring if there is exactly one bean of the property type in the bean factory.
If there is more than one, a fatal error is raised, and you can't use byType
autowiring for that bean. If there is none, nothing special happens;
use dependency-check="objects" to raise an error in that case.
4. "constructor"
Analogous to "byType" for constructor arguments. If there isn't exactly one bean
of the constructor argument type in the bean factory, a fatal error is raised.
5. "autodetect"
Chooses "constructor" or "byType" through introspection of the bean class.
If a default no-arg constructor is found, "byType" gets applied.
The latter two are similar to PicoContainer and make bean factories simple to
configure for small namespaces, but doesn't work as well as standard Spring
behaviour for bigger applications.
Note that explicit dependencies, i.e. "property" and "constructor-arg" elements,
always override autowiring. Autowire behavior can be combined with dependency
checking, which will be performed after all autowiring has been completed.
Note: This attribute will not be inherited by child bean definitions.
Hence, it needs to be specified per concrete bean definition.
-->
&lt;!ATTLIST bean autowire (no | byName | byType | constructor | autodetect | default) "default">
&lt;!--
Optional attribute controlling whether to check whether all this
beans dependencies, expressed in its properties, are satisfied.
Default is no dependency checking.
"simple" type dependency checking includes primitives and String;
"objects" includes collaborators (other beans in the factory);
"all" includes both types of dependency checking.
Note: This attribute will not be inherited by child bean definitions.
Hence, it needs to be specified per concrete bean definition.
-->
&lt;!ATTLIST bean dependency-check (none | objects | simple | all | default) "default">
&lt;!--
The names of the beans that this bean depends on being initialized.
The bean factory will guarantee that these beans get initialized before.
Note that dependencies are normally expressed through bean properties or
constructor arguments. This property should just be necessary for other kinds
of dependencies like statics (*ugh*) or database preparation on startup.
Note: This attribute will not be inherited by child bean definitions.
Hence, it needs to be specified per concrete bean definition.
-->
&lt;!ATTLIST bean depends-on CDATA #IMPLIED>
&lt;!--
Optional attribute for the name of the custom initialization method
to invoke after setting bean properties. The method must have no arguments,
but may throw any exception.
-->
&lt;!ATTLIST bean init-method CDATA #IMPLIED>
&lt;!--
Optional attribute for the name of the custom destroy method to invoke
on bean factory shutdown. The method must have no arguments,
but may throw any exception.
Note: Only invoked on beans whose lifecycle is under full control
of the factory - which is always the case for singletons, but not
guaranteed for any other scope.
-->
&lt;!ATTLIST bean destroy-method CDATA #IMPLIED>
&lt;!--
Optional attribute specifying the name of a factory method to use to
create this object. Use constructor-arg elements to specify arguments
to the factory method, if it takes arguments. Autowiring does not apply
to factory methods.
If the "class" attribute is present, the factory method will be a static
method on the class specified by the "class" attribute on this bean
definition. Often this will be the same class as that of the constructed
object - for example, when the factory method is used as an alternative
to a constructor. However, it may be on a different class. In that case,
the created object will *not* be of the class specified in the "class"
attribute. This is analogous to FactoryBean behavior.
If the "factory-bean" attribute is present, the "class" attribute is not
used, and the factory method will be an instance method on the object
returned from a getBean call with the specified bean name. The factory
bean may be defined as a singleton or a prototype.
The factory method can have any number of arguments. Autowiring is not
supported. Use indexed constructor-arg elements in conjunction with the
factory-method attribute.
Setter Injection can be used in conjunction with a factory method.
Method Injection cannot, as the factory method returns an instance,
which will be used when the container creates the bean.
-->
&lt;!ATTLIST bean factory-method CDATA #IMPLIED>
&lt;!--
Alternative to class attribute for factory-method usage.
If this is specified, no class attribute should be used.
This should be set to the name of a bean in the current or
ancestor factories that contains the relevant factory method.
This allows the factory itself to be configured using Dependency
Injection, and an instance (rather than static) method to be used.
-->
&lt;!ATTLIST bean factory-bean CDATA #IMPLIED>
&lt;!--
Bean definitions can specify zero or more constructor arguments.
This is an alternative to "autowire constructor".
Arguments correspond to either a specific index of the constructor argument
list or are supposed to be matched generically by type.
Note: A single generic argument value will just be used once, rather than
potentially matched multiple times (as of Spring 1.1).
constructor-arg elements are also used in conjunction with the factory-method
element to construct beans using static or instance factory methods.
-->
&lt;!ELEMENT constructor-arg (
description?,
(bean | ref | idref | value | null | list | set | map | props)?
)>
&lt;!--
The constructor-arg tag can have an optional index attribute,
to specify the exact index in the constructor argument list. Only needed
to avoid ambiguities, e.g. in case of 2 arguments of the same type.
-->
&lt;!ATTLIST constructor-arg index CDATA #IMPLIED>
&lt;!--
The constructor-arg tag can have an optional type attribute,
to specify the exact type of the constructor argument. Only needed
to avoid ambiguities, e.g. in case of 2 single argument constructors
that can both be converted from a String.
-->
&lt;!ATTLIST constructor-arg type CDATA #IMPLIED>
&lt;!--
A short-cut alternative to a child element "ref bean=".
-->
&lt;!ATTLIST constructor-arg ref CDATA #IMPLIED>
&lt;!--
A short-cut alternative to a child element "value".
-->
&lt;!ATTLIST constructor-arg value CDATA #IMPLIED>
&lt;!--
Bean definitions can have zero or more properties.
Property elements correspond to JavaBean setter methods exposed
by the bean classes. Spring supports primitives, references to other
beans in the same or related factories, lists, maps and properties.
-->
&lt;!ELEMENT property (
description?, meta*,
(bean | ref | idref | value | null | list | set | map | props)?
)>
&lt;!--
The property name attribute is the name of the JavaBean property.
This follows JavaBean conventions: a name of "age" would correspond
to setAge()/optional getAge() methods.
-->
&lt;!ATTLIST property name CDATA #REQUIRED>
&lt;!--
A short-cut alternative to a child element "ref bean=".
-->
&lt;!ATTLIST property ref CDATA #IMPLIED>
&lt;!--
A short-cut alternative to a child element "value".
-->
&lt;!ATTLIST property value CDATA #IMPLIED>
&lt;!--
A lookup method causes the IoC container to override the given method and return
the bean with the name given in the bean attribute. This is a form of Method Injection.
It's particularly useful as an alternative to implementing the BeanFactoryAware
interface, in order to be able to make getBean() calls for non-singleton instances
at runtime. In this case, Method Injection is a less invasive alternative.
-->
&lt;!ELEMENT lookup-method EMPTY>
&lt;!--
Name of a lookup method. This method should take no arguments.
-->
&lt;!ATTLIST lookup-method name CDATA #IMPLIED>
&lt;!--
Name of the bean in the current or ancestor factories that the lookup method
should resolve to. Often this bean will be a prototype, in which case the
lookup method will return a distinct instance on every invocation. This
is useful for single-threaded objects.
-->
&lt;!ATTLIST lookup-method bean CDATA #IMPLIED>
&lt;!--
Similar to the lookup method mechanism, the replaced-method element is used to control
IoC container method overriding: Method Injection. This mechanism allows the overriding
of a method with arbitrary code.
-->
&lt;!ELEMENT replaced-method (
(arg-type)*
)>
&lt;!--
Name of the method whose implementation should be replaced by the IoC container.
If this method is not overloaded, there's no need to use arg-type subelements.
If this method is overloaded, arg-type subelements must be used for all
override definitions for the method.
-->
&lt;!ATTLIST replaced-method name CDATA #IMPLIED>
&lt;!--
Bean name of an implementation of the MethodReplacer interface in the current
or ancestor factories. This may be a singleton or prototype bean. If it's
a prototype, a new instance will be used for each method replacement.
Singleton usage is the norm.
-->
&lt;!ATTLIST replaced-method replacer CDATA #IMPLIED>
&lt;!--
Subelement of replaced-method identifying an argument for a replaced method
in the event of method overloading.
-->
&lt;!ELEMENT arg-type (#PCDATA)>
&lt;!--
Specification of the type of an overloaded method argument as a String.
For convenience, this may be a substring of the FQN. E.g. all the
following would match "java.lang.String":
- java.lang.String
- String
- Str
As the number of arguments will be checked also, this convenience can often
be used to save typing.
-->
&lt;!ATTLIST arg-type match CDATA #IMPLIED>
&lt;!--
Defines a reference to another bean in this factory or an external
factory (parent or included factory).
-->
&lt;!ELEMENT ref EMPTY>
&lt;!--
References must specify a name of the target bean.
The "bean" attribute can reference any name from any bean in the context,
to be checked at runtime.
Local references, using the "local" attribute, have to use bean ids;
they can be checked by this DTD, thus should be preferred for references
within the same bean factory XML file.
-->
&lt;!ATTLIST ref bean CDATA #IMPLIED>
&lt;!ATTLIST ref local IDREF #IMPLIED>
&lt;!ATTLIST ref parent CDATA #IMPLIED>
&lt;!--
Defines a string property value, which must also be the id of another
bean in this factory or an external factory (parent or included factory).
While a regular 'value' element could instead be used for the same effect,
using idref in this case allows validation of local bean ids by the XML
parser, and name completion by supporting tools.
-->
&lt;!ELEMENT idref EMPTY>
&lt;!--
ID refs must specify a name of the target bean.
The "bean" attribute can reference any name from any bean in the context,
potentially to be checked at runtime by bean factory implementations.
Local references, using the "local" attribute, have to use bean ids;
they can be checked by this DTD, thus should be preferred for references
within the same bean factory XML file.
-->
&lt;!ATTLIST idref bean CDATA #IMPLIED>
&lt;!ATTLIST idref local IDREF #IMPLIED>
&lt;!--
Contains a string representation of a property value.
The property may be a string, or may be converted to the required
type using the JavaBeans PropertyEditor machinery. This makes it
possible for application developers to write custom PropertyEditor
implementations that can convert strings to arbitrary target objects.
Note that this is recommended for simple objects only.
Configure more complex objects by populating JavaBean
properties with references to other beans.
-->
&lt;!ELEMENT value (#PCDATA)>
&lt;!--
The value tag can have an optional type attribute, to specify the
exact type that the value should be converted to. Only needed
if the type of the target property or constructor argument is
too generic: for example, in case of a collection element.
-->
&lt;!ATTLIST value type CDATA #IMPLIED>
&lt;!--
Denotes a Java null value. Necessary because an empty "value" tag
will resolve to an empty String, which will not be resolved to a
null value unless a special PropertyEditor does so.
-->
&lt;!ELEMENT null (#PCDATA)>
&lt;!--
A list can contain multiple inner bean, ref, collection, or value elements.
Java lists are untyped, pending generics support in Java 1.5,
although references will be strongly typed.
A list can also map to an array type. The necessary conversion
is automatically performed by the BeanFactory.
-->
&lt;!ELEMENT list (
(bean | ref | idref | value | null | list | set | map | props)*
)>
&lt;!--
Enable/disable merging for collections when using parent/child beans.
-->
&lt;!ATTLIST list merge (true | false | default) "default">
&lt;!--
Specify the default Java type for nested values.
-->
&lt;!ATTLIST list value-type CDATA #IMPLIED>
&lt;!--
A set can contain multiple inner bean, ref, collection, or value elements.
Java sets are untyped, pending generics support in Java 1.5,
although references will be strongly typed.
-->
&lt;!ELEMENT set (
(bean | ref | idref | value | null | list | set | map | props)*
)>
&lt;!--
Enable/disable merging for collections when using parent/child beans.
-->
&lt;!ATTLIST set merge (true | false | default) "default">
&lt;!--
Specify the default Java type for nested values.
-->
&lt;!ATTLIST set value-type CDATA #IMPLIED>
&lt;!--
A Spring map is a mapping from a string key to object.
Maps may be empty.
-->
&lt;!ELEMENT map (
(entry)*
)>
&lt;!--
Enable/disable merging for collections when using parent/child beans.
-->
&lt;!ATTLIST map merge (true | false | default) "default">
&lt;!--
Specify the default Java type for nested entry keys.
-->
&lt;!ATTLIST map key-type CDATA #IMPLIED>
&lt;!--
Specify the default Java type for nested entry values.
-->
&lt;!ATTLIST map value-type CDATA #IMPLIED>
&lt;!--
A map entry can be an inner bean, ref, value, or collection.
The key of the entry is given by the "key" attribute or child element.
-->
&lt;!ELEMENT entry (
key?,
(bean | ref | idref | value | null | list | set | map | props)?
)>
&lt;!--
Each map element must specify its key as attribute or as child element.
A key attribute is always a String value.
-->
&lt;!ATTLIST entry key CDATA #IMPLIED>
&lt;!--
A short-cut alternative to a "key" element with a "ref bean=" child element.
-->
&lt;!ATTLIST entry key-ref CDATA #IMPLIED>
&lt;!--
A short-cut alternative to a child element "value".
-->
&lt;!ATTLIST entry value CDATA #IMPLIED>
&lt;!--
A short-cut alternative to a child element "ref bean=".
-->
&lt;!ATTLIST entry value-ref CDATA #IMPLIED>
&lt;!--
A key element can contain an inner bean, ref, value, or collection.
-->
&lt;!ELEMENT key (
(bean | ref | idref | value | null | list | set | map | props)
)>
&lt;!--
Props elements differ from map elements in that values must be strings.
Props may be empty.
-->
&lt;!ELEMENT props (
(prop)*
)>
&lt;!--
Enable/disable merging for collections when using parent/child beans.
-->
&lt;!ATTLIST props merge (true | false | default) "default">
&lt;!--
Element content is the string value of the property.
Note that whitespace is trimmed off to avoid unwanted whitespace
caused by typical XML formatting.
-->
&lt;!ELEMENT prop (#PCDATA)>
&lt;!--
Each property element must specify its key.
-->
&lt;!ATTLIST prop key CDATA #REQUIRED></programlisting></para>
</appendix>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,439 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="ejb">
<title>Enterprise JavaBeans (EJB) integration</title>
<section id="ejb-introduction">
<title>Introduction</title>
<para>
As a lightweight container, Spring is often considered an EJB
replacement. We do believe that for many if not most applications and use
cases, Spring as a container, combined with its rich supporting
functionality in the area of transactions, ORM and JDBC access, is a better
choice than implementing equivalent functionality via an EJB container and
EJBs.
</para>
<para>
However, it is important to note that using Spring does not prevent
you from using EJBs. In fact, Spring makes it much easier to access EJBs and
implement EJBs and functionality within them. Additionally, using Spring to
access services provided by EJBs allows the implementation of those services
to later transparently be switched between local EJB, remote EJB, or POJO
(plain old Java object) variants, without the client code having to
be changed.
</para>
<para>
In this chapter, we look at how Spring can help you access and
implement EJBs. Spring provides particular value when accessing stateless
session beans (SLSBs), so we'll begin by discussing this.
</para>
</section>
<section id="ejb-access">
<title>Accessing EJBs</title>
<section id="ejb-access-concepts">
<title>Concepts</title>
<para>
To invoke a method on a local or remote stateless session bean,
client code must normally perform a JNDI lookup to obtain the (local or
remote) EJB Home object, then use a 'create' method call on that object
to obtain the actual (local or remote) EJB object. One or more methods
are then invoked on the EJB.
</para>
<para>
To avoid repeated low-level code, many EJB applications use the
Service Locator and Business Delegate patterns. These are better than
spraying JNDI lookups throughout client code, but their usual
implementations have significant disadvantages. For example:
</para>
<itemizedlist>
<listitem>
<para>
Typically code using EJBs depends on Service Locator or
Business Delegate singletons, making it hard to test.
</para>
</listitem>
<listitem>
<para>
In the case of the Service Locator pattern used without a
Business Delegate, application code still ends up having to invoke
the create() method on an EJB home, and deal with the resulting
exceptions. Thus it remains tied to the EJB API and the complexity
of the EJB programming model.
</para>
</listitem>
<listitem>
<para>
Implementing the Business Delegate pattern typically results
in significant code duplication, where we have to write numerous
methods that simply call the same method on the EJB.
</para>
</listitem>
</itemizedlist>
<para>
The Spring approach is to allow the creation and use of proxy objects,
normally configured inside a Spring container, which act as codeless
business delegates. You do not need to write another Service Locator, another
JNDI lookup, or duplicate methods in a hand-coded Business Delegate unless
you are actually adding real value in such code.
</para>
</section>
<section id="ejb-access-local">
<title>Accessing local SLSBs</title>
<para>
Assume that we have a web controller that needs to use a local
EJB. Well follow best practice and use the EJB Business Methods
Interface pattern, so that the EJBs local interface extends a non
EJB-specific business methods interface. Lets call this business
methods interface <classname>MyComponent</classname>.
</para>
<programlisting language="java"><![CDATA[public interface MyComponent {
...
}]]></programlisting>
<para>
One of the main reasons to use the Business Methods Interface pattern
is to ensure that synchronization between method signatures in local
interface and bean implementation class is automatic. Another reason is
that it later makes it much easier for us to switch to a POJO (plain old
Java object) implementation of the service if it makes sense to do so.
Of course well also need to implement the local home interface and
provide an implementation class that implements <classname>SessionBean</classname>
and the <classname>MyComponent</classname> business methods interface. Now the
only Java coding well need to do to hook up our web tier controller to the
EJB implementation is to expose a setter method of type <classname>MyComponent</classname>
on the controller. This will save the reference as an instance variable in the
controller:
</para>
<programlisting language="java"><![CDATA[private MyComponent myComponent;
public void setMyComponent(MyComponent myComponent) {
this.myComponent = myComponent;
}]]></programlisting>
<para>
We can subsequently use this instance variable in any business
method in the controller. Now assuming we are obtaining our controller
object out of a Spring container, we can (in the same context) configure a
<classname>LocalStatelessSessionProxyFactoryBean</classname> instance, which
will be the EJB proxy object. The configuration of the proxy, and setting of
the <literal>myComponent</literal> property of the controller is done
with a configuration entry such as:
</para>
<programlisting language="xml"><![CDATA[<bean id="myComponent"
class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">
<property name="jndiName" value="ejb/myBean"/>
<property name="businessInterface" value="com.mycom.MyComponent"/>
</bean>
<bean id="myController" class="com.mycom.myController">
<property name="myComponent" ref="myComponent"/>
</bean>]]></programlisting>
<para>
Theres a lot of work happening behind the scenes, courtesy of
the Spring AOP framework, although you arent forced to work with AOP
concepts to enjoy the results. The <literal>myComponent</literal> bean
definition creates a proxy for the EJB, which implements the business
method interface. The EJB local home is cached on startup, so theres
only a single JNDI lookup. Each time the EJB is invoked, the proxy
invokes the <literal>classname</literal> method on the local EJB and
invokes the corresponding business method on the EJB.
</para>
<para>
The <literal>myController</literal> bean definition sets the
<literal>myComponent</literal> property of the controller class to the
EJB proxy.
</para>
<para>
Alternatively (and preferably in case of many such proxy definitions),
consider using the <literal>&lt;jee:local-slsb&gt;</literal>
configuration element in Spring's "jee" namespace:
</para>
<programlisting language="xml"><![CDATA[<jee:local-slsb id="myComponent" jndi-name="ejb/myBean"
business-interface="com.mycom.MyComponent"/>
<bean id="myController" class="com.mycom.myController">
<property name="myComponent" ref="myComponent"/>
</bean>]]></programlisting>
<para>
This EJB access mechanism delivers huge simplification of
application code: the web tier code (or other EJB client code) has no
dependence on the use of EJB. If we want to replace this EJB reference
with a POJO or a mock object or other test stub, we could simply change
the <literal>myComponent</literal> bean definition without changing a
line of Java code. Additionally, we havent had to write a single line of
JNDI lookup or other EJB plumbing code as part of our application.
</para>
<para>
Benchmarks and experience in real applications indicate that the
performance overhead of this approach (which involves reflective
invocation of the target EJB) is minimal, and is typically undetectable
in typical use. Remember that we dont want to make fine-grained calls
to EJBs anyway, as theres a cost associated with the EJB infrastructure
in the application server.
</para>
<para>
There is one caveat with regards to the JNDI lookup. In a bean
container, this class is normally best used as a singleton (there simply
is no reason to make it a prototype). However, if that bean container
pre-instantiates singletons (as do the various XML
<classname>ApplicationContext</classname> variants)
you may have a problem if the bean container is loaded before the EJB
container loads the target EJB. That is because the JNDI lookup will be
performed in the <literal>init()</literal> method of this class and then
cached, but the EJB will not have been bound at the target location yet.
The solution is to not pre-instantiate this factory object, but allow it
to be created on first use. In the XML containers, this is controlled via
the <literal>lazy-init</literal> attribute.
</para>
<para>
Although this will not be of interest to the majority of Spring
users, those doing programmatic AOP work with EJBs may want to look at
<classname>LocalSlsbInvokerInterceptor</classname>.
</para>
</section>
<section id="ejb-access-remote">
<title>Accessing remote SLSBs</title>
<para>
Accessing remote EJBs is essentially identical to accessing local
EJBs, except that the
<classname>SimpleRemoteStatelessSessionProxyFactoryBean</classname> or
<literal>&lt;jee:remote-slsb&gt;</literal> configuration element is used.
Of course, with or without Spring, remote invocation semantics apply; a
call to a method on an object in another VM in another computer does
sometimes have to be treated differently in terms of usage scenarios and
failure handling.
</para>
<para>
Spring's EJB client support adds one more advantage over the
non-Spring approach. Normally it is problematic for EJB client code to
be easily switched back and forth between calling EJBs locally or
remotely. This is because the remote interface methods must declare that
they throw <classname>RemoteException</classname>, and client code must deal
with this, while the local interface methods don't. Client code
written for local EJBs which needs to be moved to remote EJBs
typically has to be modified to add handling for the remote exceptions,
and client code written for remote EJBs which needs to be moved to local
EJBs, can either stay the same but do a lot of unnecessary handling of
remote exceptions, or needs to be modified to remove that code. With the
Spring remote EJB proxy, you can instead not declare any thrown
<classname>RemoteException</classname> in your Business Method Interface and
implementing EJB code, have a remote interface which is identical except
that it does throw <classname>RemoteException</classname>, and rely on the
proxy to dynamically treat the two interfaces as if they were the same.
That is, client code does not have to deal with the checked
<classname>RemoteException</classname> class. Any actual
<classname>RemoteException</classname> that is thrown during the EJB
invocation will be re-thrown as the non-checked
<classname>RemoteAccessException</classname> class, which is a subclass of
<classname>RuntimeException</classname>. The target service can then be
switched at will between a local EJB or remote EJB (or even plain Java
object) implementation, without the client code knowing or caring. Of
course, this is optional; there is nothing stopping you from declaring
<classname>RemoteExceptions</classname> in your business interface.
</para>
</section>
<section id="ejb-access-ejb2-ejb3">
<title>Accessing EJB 2.x SLSBs versus EJB 3 SLSBs</title>
<para>
Accessing EJB 2.x Session Beans and EJB 3 Session Beans via Spring
is largely transparent. Spring's EJB accessors, including the
<literal>&lt;jee:local-slsb&gt;</literal> and <literal>&lt;jee:remote-slsb&gt;</literal>
facilities, transparently adapt to the actual component at runtime.
They handle a home interface if found (EJB 2.x style), or perform straight
component invocations if no home interface is available (EJB 3 style).
</para>
<para>
Note: For EJB 3 Session Beans, you could effectively use a
<classname>JndiObjectFactoryBean</classname> / <literal>&lt;jee:jndi-lookup&gt;</literal>
as well, since fully usable component references are exposed for plain
JNDI lookups there. Defining explicit <literal>&lt;jee:local-slsb&gt;</literal>
/ <literal>&lt;jee:remote-slsb&gt;</literal> lookups simply provides
consistent and more explicit EJB access configuration.
</para>
</section>
</section>
<section id="ejb-implementation">
<title>Using Spring's EJB implementation support classes</title>
<section id="ejb-implementation-ejb2">
<title>EJB 2.x base classes</title>
<para>
Spring provides convenience classes to help you implement EJBs.
These are designed to encourage the good practice of putting business
logic behind EJBs in POJOs, leaving EJBs responsible for transaction
demarcation and (optionally) remoting.
</para>
<para>
To implement a Stateless or Stateful session bean, or a Message Driven
bean, you need only derive your implementation class from
<classname>AbstractStatelessSessionBean</classname>,
<classname>AbstractStatefulSessionBean</classname>, and
<classname>AbstractMessageDrivenBean</classname>/<classname>AbstractJmsMessageDrivenBean</classname>,
respectively.
</para>
<para>
Consider an example Stateless Session bean which actually delegates
the implementation to a plain java service object. We have the business
interface:
</para>
<programlisting language="java"><![CDATA[public interface MyComponent {
public void myMethod(...);
...
}]]></programlisting>
<para>We also have the plain Java implementation object:</para>
<programlisting language="java"><![CDATA[public class MyComponentImpl implements MyComponent {
public String myMethod(...) {
...
}
...
}]]></programlisting>
<para>And finally the Stateless Session Bean itself:</para>
<programlisting language="java"><![CDATA[public class MyFacadeEJB extends AbstractStatelessSessionBean
implements MyFacadeLocal {
private MyComponent myComp;
/**
* Obtain our POJO service object from the BeanFactory/ApplicationContext
* @see org.springframework.ejb.support.AbstractStatelessSessionBean#onEjbCreate()
*/
protected void onEjbCreate() throws CreateException {
myComp = (MyComponent) getBeanFactory().getBean(
ServicesConstants.CONTEXT_MYCOMP_ID);
}
// for business method, delegate to POJO service impl.
public String myFacadeMethod(...) {
return myComp.myMethod(...);
}
...
}]]></programlisting>
<para>
The Spring EJB support base classes will by default create and load
a Spring IoC container as part of their lifecycle, which is then available
to the EJB (for example, as used in the code above to obtain the POJO
service object). The loading is done via a strategy object which is a subclass of
<classname>BeanFactoryLocator</classname>. The actual implementation of
<classname>BeanFactoryLocator</classname> used by default is
<classname>ContextJndiBeanFactoryLocator</classname>, which creates the
ApplicationContext from a resource locations specified as a JNDI
environment variable (in the case of the EJB classes, at
<literal>java:comp/env/ejb/BeanFactoryPath</literal>). If there is a need
to change the BeanFactory/ApplicationContext loading strategy, the default
<classname>BeanFactoryLocator</classname> implementation used may be overridden
by calling the <literal>setBeanFactoryLocator()</literal> method, either
in <literal>setSessionContext()</literal>, or in the actual constructor of
the EJB. Please see the Javadocs for more details.
</para>
<para>
As described in the Javadocs, Stateful Session beans expecting to be
passivated and reactivated as part of their lifecycle, and which use a
non-serializable container instance (which is the normal case) will have
to manually call <literal>unloadBeanFactory()</literal> and
<literal>loadBeanFactory()</literal> from <literal>ejbPassivate()</literal>
and <literal>ejbActivate()</literal>, respectively, to unload and reload the
BeanFactory on passivation and activation, since it can not be saved by
the EJB container.
</para>
<para>
The default behavior of the
<classname>ContextJndiBeanFactoryLocator</classname> class is to load an
<classname>ApplicationContext</classname> for use by an EJB, and is
adequate for some situations. However, it is problematic when the
<classname>ApplicationContext</classname> is loading a number of beans,
or the initialization of those beans is time consuming or memory
intensive (such as a Hibernate <classname>SessionFactory</classname>
initialization, for example), since every EJB will have their own copy.
In this case, the user may want to override the default
<classname>ContextJndiBeanFactoryLocator</classname> usage and use
another <classname>BeanFactoryLocator</classname> variant, such as the
<classname>ContextSingletonBeanFactoryLocator</classname> which can load
and use a shared container to be used by multiple EJBs or other clients.
Doing this is relatively simple, by adding code similar to this to the
EJB:
</para>
<programlisting language="java"><![CDATA[ /**
* Override default BeanFactoryLocator implementation
* @see javax.ejb.SessionBean#setSessionContext(javax.ejb.SessionContext)
*/
public void setSessionContext(SessionContext sessionContext) {
super.setSessionContext(sessionContext);
setBeanFactoryLocator(ContextSingletonBeanFactoryLocator.getInstance());
setBeanFactoryLocatorKey(ServicesConstants.PRIMARY_CONTEXT_ID);
}]]></programlisting>
<para>
You would then need to create a bean definition file named <literal>beanRefContext.xml</literal>.
This file defines all bean factories (usually in the form of application contexts) that may be used
in the EJB. In many cases, this file will only contain a single bean definition such as this (where
<literal>businessApplicationContext.xml</literal> contains the bean definitions for all business
service POJOs):
</para>
<programlisting language="xml"><![CDATA[<beans>
<bean id="businessBeanFactory" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg value="businessApplicationContext.xml" />
</bean>
</beans>]]></programlisting>
<para>
In the above example, the <literal>ServicesConstants.PRIMARY_CONTEXT_ID</literal> constant
would be defined as follows:
</para>
<programlisting language="java"><![CDATA[public static final String ServicesConstants.PRIMARY_CONTEXT_ID = "businessBeanFactory";]]></programlisting>
<para>
Please see the respective Javadocs for the <classname>BeanFactoryLocator</classname> and
<classname>ContextSingletonBeanFactoryLocator</classname> classes for more information on
their usage.
</para>
</section>
<section id="ejb-implementation-ejb3">
<title>EJB 3 injection interceptor</title>
<para>
For EJB 3 Session Beans and Message-Driven Beans, Spring provides a convenient
interceptor that resolves Spring 2.5's <literal>@Autowired</literal> annotation
in the EJB component class:
<classname>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</classname>.
This interceptor can be applied through an <code>@Interceptors</code> annotation
in the EJB component class, or through an <literal>interceptor-binding</literal>
XML element in the EJB deployment descriptor.
</para>
<programlisting language="java"><![CDATA[@Stateless
@Interceptors(SpringBeanAutowiringInterceptor.class)
public class MyFacadeEJB implements MyFacadeLocal {
// automatically injected with a matching Spring bean
@Autowired
private MyComponent myComp;
// for business method, delegate to POJO service impl.
public String myFacadeMethod(...) {
return myComp.myMethod(...);
}
...
}]]></programlisting>
<para>
<classname>SpringBeanAutowiringInterceptor</classname> by default obtains target
beans from a <classname>ContextSingletonBeanFactoryLocator</classname>, with the
context defined in a bean definition file named <literal>beanRefContext.xml</literal>.
By default, a single context definition is expected, which is obtained by type rather
than by name. However, if you need to choose between multiple context definitions,
a specific locator key is required. The locator key (i.e. the name of the context
definition in <literal>beanRefContext.xml</literal>) can be explicitly specified
either through overriding the <literal>getBeanFactoryLocatorKey</literal> method
in a custom <classname>SpringBeanAutowiringInterceptor</classname> subclass.
</para>
<para>
Alternatively, consider overriding <classname>SpringBeanAutowiringInterceptor</classname>'s
<literal>getBeanFactory</literal> method, e.g. obtaining a shared
<interfacename>ApplicationContext</interfacename> from a custom holder class.
</para>
</section>
</section>
</chapter>

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<!-- Generated by Microsoft Visio 11.0, SVG Export, v1.0 ejb.svg Page-1 -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="4.25667in"
height="2.64in" viewBox="0 0 306.48 190.08" xml:space="preserve" color-interpolation-filters="sRGB" class="st9">
<v:documentProperties v:langID="1033" v:metric="true"/>
<style type="text/css">
<![CDATA[
.st1 {fill:#f4f7f0;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st2 {fill:#000000;font-family:Arial;font-size:0.833336em}
.st3 {fill:#ecefe2;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st4 {visibility:visible}
.st5 {fill:#84877b;stroke:#84877b;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st6 {fill:#dde2cd;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st7 {fill:#000000;font-family:Arial;font-size:0.75em}
.st8 {font-size:1em}
.st9 {fill:none;fill-rule:evenodd;font-size:12;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
]]>
</style>
<g v:mID="0" v:index="1" v:groupContext="foregroundPage">
<title>Page-1</title>
<v:pageProperties v:drawingScale="1" v:pageScale="1" v:drawingUnits="0" v:shadowOffsetX="9" v:shadowOffsetY="-9"/>
<g id="shape1-1" v:mID="1" v:groupContext="shape" transform="translate(0.24012,-0.24)">
<title>Box.1</title>
<desc>Application Server (e.g. JBoss, WebLogic)</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="153" cy="104.622" width="306" height="170.916"/>
<rect x="0" y="19.164" width="306" height="170.916" class="st1"/>
<text x="59.35" y="185.62" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/>Application Server (e.g. JBoss, WebLogic)</text> </g>
<g id="shape2-4" v:mID="2" v:groupContext="shape" transform="translate(30.1749,-23.3831)">
<title>Box.2</title>
<desc>Spring Core</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="49.8912" cy="159.506" width="99.79" height="61.1476"/>
<rect x="0" y="128.932" width="99.7826" height="61.1476" class="st3"/>
<text x="4" y="174.51" class="st2" v:langID="1033"><v:paragraph/><v:tabList/><v:newlineChar/><v:newlineChar/>Spring Core </text> </g>
<g id="shape3-7" v:mID="3" v:groupContext="shape" transform="translate(161.223,-89.6263)">
<title>Box.3</title>
<desc>Spring Context</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="51.8869" cy="159.506" width="103.78" height="61.1476"/>
<rect x="0" y="128.932" width="103.774" height="61.1476" class="st3"/>
<text x="33.65" y="174.51" class="st2" v:langID="1033"><v:paragraph v:horizAlign="2"/><v:tabList/><v:newlineChar/><v:newlineChar/>Spring Context</text> </g>
<g id="shape4-10" v:mID="4" v:groupContext="shape" transform="translate(6.89229,-150.773)">
<title>Box</title>
<desc>EJB Access layer using SlsbInvokers</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="69.8477" cy="170.547" width="139.71" height="39.0665"/>
<g id="shadow4-11" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="151.014" width="139.696" height="39.0665" class="st5"/>
</g>
<rect x="0" y="151.014" width="139.696" height="39.0665" class="st6"/>
<text x="22.83" y="167.85" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>EJB Access layer using <tspan
x="44.09" dy="1.2em" class="st8">SlsbInvokers</tspan></text> </g>
<g id="shape5-16" v:mID="5" v:groupContext="shape" transform="translate(161.888,-23.3831)">
<title>Box.4</title>
<desc>Spring DAO</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="51.2216" cy="159.506" width="102.46" height="61.1476"/>
<rect x="0" y="128.932" width="102.443" height="61.1476" class="st3"/>
<text x="45.09" y="174.51" class="st2" v:langID="1033"><v:paragraph v:horizAlign="2"/><v:tabList/><v:newlineChar/><v:newlineChar/>Spring DAO</text> </g>
<g id="shape6-19" v:mID="6" v:groupContext="shape" transform="translate(26.5572,-60.768)">
<title>Box.5</title>
<desc>Spring-managed EJBs (using AbstractEnterpriseBean</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="81.1564" cy="149.315" width="162.33" height="81.5301"/>
<g id="shadow6-20" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="108.55" width="162.313" height="81.5301" class="st5"/>
</g>
<rect x="0" y="108.55" width="162.313" height="81.5301" class="st6"/>
<text x="36.12" y="152.02" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Spring-managed EJBs</text> </g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -0,0 +1,254 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<!-- Generated by Microsoft Visio 11.0, SVG Export, v1.0 full.svg Page-1 -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="4.97167in"
height="3.59998in" viewBox="0 0 357.96 259.199" xml:space="preserve" color-interpolation-filters="sRGB" class="st9">
<v:documentProperties v:langID="1033" v:viewMarkup="false"/>
<style type="text/css">
<![CDATA[
.st1 {fill:#f4f7f0;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st2 {fill:#000000;font-family:Arial;font-size:0.666664em}
.st3 {fill:#ecefe2;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st4 {visibility:visible}
.st5 {fill:#84877b;stroke:#84877b;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st6 {fill:#dde2cd;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st7 {fill:#000000;font-family:Arial;font-size:0.499992em}
.st8 {font-size:1em}
.st9 {fill:none;fill-rule:evenodd;font-size:12;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
]]>
</style>
<g v:mID="0" v:index="1" v:groupContext="foregroundPage">
<title>Page-1</title>
<v:pageProperties v:drawingScale="1" v:pageScale="1" v:drawingUnits="0" v:shadowOffsetX="9" v:shadowOffsetY="-9"/>
<g id="shape1-1" v:mID="1" v:groupContext="shape" transform="translate(3.12,-11.3134)">
<title>Box.1</title>
<desc>Servlet Container (Tomcat / Jetty)</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="176.4" cy="140.913" width="352.8" height="236.571"/>
<rect x="0" y="22.6271" width="352.8" height="236.571" class="st1"/>
<text x="116.6" y="248.91" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/>Servlet Container (Tomcat / Jetty)<v:newlineChar/><v:newlineChar/></text> </g>
<g id="shape2-4" v:mID="2" v:groupContext="shape" transform="translate(16.08,-37.4777)">
<title>Box.2</title>
<desc>Spring Core</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="81.9" cy="239.778" width="163.8" height="38.8414"/>
<rect x="0" y="220.357" width="163.8" height="38.8414" class="st3"/>
<text x="60.56" y="246.98" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/>Spring Core</text> </g>
<g id="shape3-7" v:mID="3" v:groupContext="shape" transform="translate(180.24,-37.4777)">
<title>Box.3</title>
<desc>Spring DAO</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="81.9" cy="239.778" width="163.81" height="38.8414"/>
<rect x="0" y="220.357" width="163.8" height="38.8414" class="st3"/>
<text x="60.56" y="246.98" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/>Spring DAO</text> </g>
<g id="shape4-10" v:mID="4" v:groupContext="shape" transform="translate(180.24,-74.7955)">
<title>Box.4</title>
<desc>Spring ORM</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="81.9" cy="240.395" width="163.8" height="37.6071"/>
<rect x="0" y="221.591" width="163.8" height="37.6071" class="st3"/>
<text x="11" y="238" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/> Spring ORM <v:newlineChar/></text> </g>
<g id="shape5-13" v:mID="5" v:groupContext="shape" transform="translate(16.44,-143.999)">
<title>Box.5</title>
<desc>Spring Web</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="163.8" cy="241.199" width="327.6" height="36"/>
<rect x="0" y="223.199" width="327.6" height="36" class="st3"/>
<text x="142.9" y="243.6" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Spring Web</text> </g>
<g id="shape7-16" v:mID="7" v:groupContext="shape" transform="translate(16.26,-74.7955)">
<title>Box.7</title>
<desc>Spring AOP</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="81.9" cy="240.395" width="163.8" height="37.6071"/>
<rect x="0" y="221.591" width="163.8" height="37.6071" class="st3"/>
<text x="4" y="238" class="st2" v:langID="1033"><v:paragraph/><v:tabList/> Spring AOP<v:newlineChar/></text> </g>
<g id="shape9-19" v:mID="9" v:groupContext="shape" transform="translate(114,-65.4848)">
<title>Box</title>
<desc>Hibernate mappings Custom Hibernate DAOs</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="72.45" cy="245.484" width="144.91" height="27.4286"/>
<g id="shadow9-20" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="231.77" width="144.9" height="27.4286" class="st5"/>
</g>
<rect x="0" y="231.77" width="144.9" height="27.4286" class="st6"/>
<text x="45.6" y="243.68" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Hibernate mappings<v:newlineChar/><tspan
x="39.44" dy="1.2em" class="st8">Custom Hibernate DAOs</tspan></text> </g>
<g id="shape10-25" v:mID="10" v:groupContext="shape" transform="translate(16.44,-179.999)">
<title>Box.10</title>
<desc>Spring Web MVC</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="163.8" cy="246.052" width="327.6" height="26.2929"/>
<rect x="0" y="232.906" width="327.6" height="26.2929" class="st3"/>
<text x="132.9" y="248.45" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Spring Web MVC</text> </g>
<g id="shape6-28" v:mID="6" v:groupContext="shape" transform="translate(20.4,-211.542)">
<title>Box.6</title>
<desc>Form Controllers handling form interaction</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="36" cy="236.81" width="72" height="44.7771"/>
<g id="shadow6-29" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="214.421" width="72" height="44.7771" class="st5"/>
</g>
<rect x="0" y="214.421" width="72" height="44.7771" class="st6"/>
<text x="13.66" y="231.41" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Form Controllers <tspan
x="17.82" dy="1.2em" class="st8">handling form </tspan><tspan x="22.16" dy="1.2em" class="st8">interaction</tspan></text> </g>
<g id="shape11-35" v:mID="11" v:groupContext="shape" transform="translate(102.48,-211.679)">
<title>Box.11</title>
<desc>Multipart Resolver to handle file uploads</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="36" cy="236.81" width="72" height="44.7771"/>
<g id="shadow11-36" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="214.421" width="72" height="44.7771" class="st5"/>
</g>
<rect x="0" y="214.421" width="72" height="44.7771" class="st6"/>
<text x="11.83" y="235.01" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Multipart Resolver<v:newlineChar/><tspan
x="7.65" dy="1.2em" class="st8">to handle file uploads</tspan></text> </g>
<g id="shape12-41" v:mID="12" v:groupContext="shape" transform="translate(181.68,-211.679)">
<title>Box.12</title>
<desc>Dynamic binding of data to the domain model</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="36" cy="236.81" width="72" height="44.7771"/>
<g id="shadow12-42" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="214.421" width="72" height="44.7771" class="st5"/>
</g>
<rect x="0" y="214.421" width="72" height="44.7771" class="st6"/>
<text x="10.49" y="231.41" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Dynamic binding of <tspan
x="11.15" dy="1.2em" class="st8">data to the domain </tspan><tspan x="27.83" dy="1.2em" class="st8">model</tspan></text> </g>
<g id="shape13-48" v:mID="13" v:groupContext="shape" transform="translate(263.76,-211.679)">
<title>Box.13</title>
<desc>Integration with JSP, Velocity, XSLT, PDF, Excel</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="36" cy="236.81" width="72" height="44.7771"/>
<g id="shadow13-49" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="214.421" width="72" height="44.7771" class="st5"/>
</g>
<rect x="0" y="214.421" width="72" height="44.7771" class="st6"/>
<text x="8.49" y="231.41" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Integration with JSP, <tspan
x="7.83" dy="1.2em" class="st8">Velocity</tspan>, XSLT, PDF, <tspan x="28.66" dy="1.2em" class="st8">Excel</tspan></text> </g>
<g id="shape15-55" v:mID="15" v:groupContext="shape" transform="translate(16.44,-112.319)">
<title>Box.15</title>
<desc>Spring Context</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="163.8" cy="243.359" width="327.6" height="31.68"/>
<rect x="0" y="227.519" width="327.6" height="31.68" class="st3"/>
<text x="137.34" y="245.76" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Spring Context</text> </g>
<g id="shape8-58" v:mID="8" v:groupContext="shape" transform="translate(114,-138.239)">
<title>Box.8</title>
<desc>Declarative transaction management for POJOs</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="72" cy="251.999" width="144" height="14.4"/>
<g id="shadow8-59" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="244.799" width="144" height="14.4" class="st5"/>
</g>
<rect x="0" y="244.799" width="144" height="14.4" class="st6"/>
<text x="8.31" y="253.8" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Declarative transaction management for POJOs</text> </g>
<g id="shape14-63" v:mID="14" v:groupContext="shape" transform="translate(114,-107.999)">
<title>Box.14</title>
<desc>Custom business logic</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="72" cy="251.999" width="144" height="14.4"/>
<g id="shadow14-64" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="244.799" width="144" height="14.4" class="st5"/>
</g>
<rect x="0" y="244.799" width="144" height="14.4" class="st6"/>
<text x="41.99" y="253.8" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Custom business logic</text> </g>
<g id="shape16-68" v:mID="16" v:groupContext="shape" transform="translate(0.24,-107.999)">
<title>Box.16</title>
<desc>Sending Email</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="23.04" cy="231.839" width="46.08" height="54.72"/>
<g id="shadow16-69" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="204.479" width="46.08" height="54.72" class="st5"/>
</g>
<rect x="0" y="204.479" width="46.08" height="54.72" class="st6"/>
<text x="12.04" y="230.04" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Sending <tspan
x="15.55" dy="1.2em" class="st8">Email</tspan></text> </g>
<g id="shape17-74" v:mID="17" v:groupContext="shape" transform="translate(309.84,-107.999)">
<title>Box.17</title>
<desc>Remote access via Hession, Burlap, SOAP</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="23.04" cy="231.839" width="46.08" height="54.72"/>
<g id="shadow17-75" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="204.479" width="46.08" height="54.72" class="st5"/>
</g>
<rect x="0" y="204.479" width="46.08" height="54.72" class="st6"/>
<text x="12.55" y="222.84" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Remote <tspan
x="9.04" dy="1.2em" class="st8">access via<v:newlineChar/></tspan><tspan x="11.38" dy="1.2em" class="st8">Hession</tspan>, <tspan
x="4.38" dy="1.2em" class="st8">Burlap</tspan>, SOAP</text> </g>
<g id="shape18-82" v:mID="18" v:groupContext="shape" transform="translate(114,-172.799)">
<title>Box.18</title>
<desc>WebApplicationContext providing e.g. messaging</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="72" cy="251.999" width="144" height="14.4"/>
<g id="shadow18-83" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="244.799" width="144" height="14.4" class="st5"/>
</g>
<rect x="0" y="244.799" width="144" height="14.4" class="st6"/>
<text x="6.63" y="253.8" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>WebApplicationContext providing e.g. messaging</text> </g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -0,0 +1,143 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<!-- Generated by Microsoft Visio 11.0, SVG Export, v1.0 remoting.svg Page-1 -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="4.70667in"
height="2.65333in" viewBox="0 0 338.88 191.04" xml:space="preserve" color-interpolation-filters="sRGB" class="st9">
<v:documentProperties v:langID="1033" v:metric="true"/>
<style type="text/css">
<![CDATA[
.st1 {fill:#f4f7f0;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st2 {fill:#000000;font-family:Arial;font-size:0.75em}
.st3 {fill:#ecefe2;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st4 {visibility:visible}
.st5 {fill:#84877b;stroke:#84877b;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st6 {fill:#dde2cd;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st7 {fill:#000000;font-family:Arial;font-size:0.666664em}
.st8 {font-size:1em}
.st9 {fill:none;fill-rule:evenodd;font-size:12;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
]]>
</style>
<g v:mID="0" v:index="1" v:groupContext="foregroundPage">
<title>Page-1</title>
<v:pageProperties v:drawingScale="1" v:pageScale="1" v:drawingUnits="0" v:shadowOffsetX="8.99999"
v:shadowOffsetY="-8.99999"/>
<g id="shape1-1" v:mID="1" v:groupContext="shape" transform="translate(0.240333,-10.8)">
<title>Box.1</title>
<desc>Servlet Container (e.g. Tomcat / Jetty)</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(3.99999,3.99999,3.99999,3.99999)"/>
<v:textRect cx="169.199" cy="126.24" width="338.4" height="129.6"/>
<rect x="0" y="61.4399" width="338.4" height="129.6" class="st1"/>
<text x="93.17" y="177.54" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/>Servlet Container (e.g. Tomcat / Jetty)<v:newlineChar/><v:newlineChar/></text> </g>
<g id="shape2-4" v:mID="2" v:groupContext="shape" transform="translate(12.326,-37.8001)">
<title>Box.2</title>
<desc>Spring Core</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(3.99999,3.99999,3.99999,3.99999)"/>
<v:textRect cx="78.5567" cy="158.64" width="157.12" height="64.7999"/>
<rect x="0" y="126.24" width="157.114" height="64.7999" class="st3"/>
<text x="54.54" y="177.54" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/><v:newlineChar/><v:newlineChar/>Spring Core</text> </g>
<g id="shape3-7" v:mID="3" v:groupContext="shape" transform="translate(169.44,-37.8001)">
<title>Box.3</title>
<desc>Spring Context</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(3.99999,3.99999,3.99999,3.99999)"/>
<v:textRect cx="78.5567" cy="158.64" width="157.12" height="64.7999"/>
<rect x="0" y="126.24" width="157.114" height="64.7999" class="st3"/>
<text x="48.78" y="177.54" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/><v:newlineChar/><v:newlineChar/>Spring Context </text> </g>
<g id="shape4-10" v:mID="4" v:groupContext="shape" transform="translate(8.09603,-151.2)">
<title>Box.10</title>
<desc>JAX RPC client</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(3.99999,3.99999,3.99999,3.99999)"/>
<v:textRect cx="38.3717" cy="171.24" width="76.75" height="39.6"/>
<g id="shadow4-11" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="151.44" width="76.7442" height="39.6" class="st5"/>
</g>
<rect x="0" y="151.44" width="76.7442" height="39.6" class="st6"/>
<text x="11.03" y="173.64" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>JAX RPC client</text> </g>
<g id="shape5-15" v:mID="5" v:groupContext="shape" transform="translate(18.9732,-97.2)">
<title>Box.4</title>
<desc>Transprarent remote access (using remote package)</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(3.99999,3.99999,3.99999,3.99999)"/>
<v:textRect cx="150.466" cy="176.64" width="300.94" height="28.8"/>
<g id="shadow5-16" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="162.24" width="300.934" height="28.8" class="st5"/>
</g>
<rect x="0" y="162.24" width="300.934" height="28.8" class="st6"/>
<text x="58.65" y="179.04" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Transp<tspan
class="st8" v:langID="2057">ar</tspan>ent remote access (using remote package)</text> </g>
<g id="shape6-21" v:mID="6" v:groupContext="shape" transform="translate(18.9732,-68.4)">
<title>Box</title>
<desc>Custom logic contained by beans</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(3.99999,3.99999,3.99999,3.99999)"/>
<v:textRect cx="150.466" cy="176.64" width="300.94" height="28.8"/>
<g id="shadow6-22" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="162.24" width="300.934" height="28.8" class="st5"/>
</g>
<rect x="0" y="162.24" width="300.934" height="28.8" class="st6"/>
<text x="91.55" y="179.04" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Custom logic contained by beans</text> </g>
<g id="shape7-26" v:mID="7" v:groupContext="shape" transform="translate(96.9259,-151.2)">
<title>Box.5</title>
<desc>Hessian client</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(3.99999,3.99999,3.99999,3.99999)"/>
<v:textRect cx="36.1057" cy="171.24" width="72.22" height="39.6"/>
<g id="shadow7-27" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="151.44" width="72.212" height="39.6" class="st5"/>
</g>
<rect x="0" y="151.44" width="72.212" height="39.6" class="st6"/>
<text x="11.2" y="173.64" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Hessian client</text> </g>
<g id="shape8-31" v:mID="8" v:groupContext="shape" transform="translate(184.094,-151.2)">
<title>Box.6</title>
<desc>Burlap client</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(3.99999,3.99999,3.99999,3.99999)"/>
<v:textRect cx="33.6885" cy="171.24" width="67.38" height="39.6"/>
<g id="shadow8-32" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="151.44" width="67.3778" height="39.6" class="st5"/>
</g>
<rect x="0" y="151.44" width="67.3778" height="39.6" class="st6"/>
<text x="11.69" y="173.64" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Burlap client</text> </g>
<g id="shape9-36" v:mID="9" v:groupContext="shape" transform="translate(266.126,-151.2)">
<title>Box.7</title>
<desc>RMI client</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(3.99999,3.99999,3.99999,3.99999)"/>
<v:textRect cx="33.6885" cy="171.24" width="67.38" height="39.6"/>
<g id="shadow9-37" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="151.44" width="67.3778" height="39.6" class="st5"/>
</g>
<rect x="0" y="151.44" width="67.3778" height="39.6" class="st6"/>
<text x="26.37" y="168.84" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>RMI<v:newlineChar/><tspan
x="24.36" dy="1.2em" class="st8">client</tspan></text> </g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View File

@@ -0,0 +1,198 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<!-- Generated by Microsoft Visio 11.0, SVG Export, v1.0 spring-overview.svg Page-1 -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="8.26772in"
height="11.6929in" viewBox="0 0 595.276 841.89" xml:space="preserve" color-interpolation-filters="sRGB" class="st5">
<v:documentProperties v:langID="1033" v:viewMarkup="false"/>
<style type="text/css">
<![CDATA[
.st1 {fill:#969696;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st2 {fill:#dde2cd;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st3 {fill:#000000;font-family:Arial;font-size:2.50001em;font-weight:bold}
.st4 {font-size:0.333333em;font-weight:normal}
.st5 {fill:none;fill-rule:evenodd;font-size:12;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
]]>
</style>
<g v:mID="0" v:index="1" v:groupContext="foregroundPage">
<v:userDefs>
<v:ud v:nameU="SchemeName" v:val="VT4(Default)"/>
</v:userDefs>
<title>Page-1</title>
<v:pageProperties v:drawingScale="0.0393701" v:pageScale="0.0393701" v:drawingUnits="24" v:shadowOffsetX="8.50394"
v:shadowOffsetY="-8.50394"/>
<v:layer v:name="Connector" v:index="0"/>
<g id="group9-1" transform="translate(549.921,-255.118) scale(-1,1)" v:mID="9" v:groupContext="group">
<v:userDefs>
<v:ud v:nameU="Scale" v:val="VT0(1):26"/>
<v:ud v:nameU="AntiScale" v:val="VT0(1):26"/>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<title>3-D box.9</title>
<desc>Core The IoC container</desc>
<g id="shape10-2" v:mID="10" v:groupContext="shape" transform="translate(0,14.1732)">
<title>Sheet.10</title>
<path d="M0 827.72 L521.57 827.72 L507.4 841.89 L-14.17 841.89 L0 827.72 Z" class="st1"/>
</g>
<g id="shape11-4" v:mID="11" v:groupContext="shape" transform="translate(-14.1732,0)">
<title>Sheet.11</title>
<path d="M0 856.06 L14.17 841.89 L14.17 756.85 L0 771.02 L0 856.06 Z" class="st1"/>
</g>
<g id="shape12-6" v:mID="12" v:groupContext="shape">
<title>Sheet.12</title>
<rect x="0" y="756.85" width="521.575" height="85.0394" class="st2"/>
</g>
<g id="shape9-8" v:mID="9" v:groupContext="groupContent">
<v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/>
<v:textRect cx="260.787" cy="799.37" width="521.58" height="85.0394"/>
<text x="-294.97" y="797.57" transform="scale(-1,1)" class="st3" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>Core<v:newlineChar/><v:newlineChar/><tspan
x="-300.54" dy="2.76em" class="st4">The IoC container</tspan></text> </g>
</g>
<g id="group1-11" transform="translate(269.291,-368.504) scale(-1,1)" v:mID="1" v:groupContext="group">
<v:userDefs>
<v:ud v:nameU="Scale" v:val="VT0(1):26"/>
<v:ud v:nameU="AntiScale" v:val="VT0(1):26"/>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<title>3-D box.1</title>
<desc>AOP Spring AOP AspectJ integration</desc>
<g id="shape2-12" v:mID="2" v:groupContext="shape" transform="translate(0,14.1732)">
<title>Sheet.2</title>
<path d="M0 827.72 L240.94 827.72 L226.77 841.89 L-14.17 841.89 L0 827.72 Z" class="st1"/>
</g>
<g id="shape3-14" v:mID="3" v:groupContext="shape" transform="translate(-14.1732,0)">
<title>Sheet.3</title>
<path d="M0 856.06 L14.17 841.89 L14.17 756.85 L0 771.02 L0 856.06 Z" class="st1"/>
</g>
<g id="shape4-16" v:mID="4" v:groupContext="shape">
<title>Sheet.4</title>
<rect x="0" y="756.85" width="240.945" height="85.0394" class="st2"/>
</g>
<g id="shape1-18" v:mID="1" v:groupContext="groupContent">
<v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/>
<v:textRect cx="120.472" cy="799.37" width="240.95" height="85.0394"/>
<text x="-152.97" y="791.57" transform="scale(-1,1)" class="st3" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>AOP<v:newlineChar/><v:newlineChar/><tspan
x="-146.87" dy="2.76em" class="st4">Spring AOP<v:newlineChar/></tspan><tspan x="-162.99" dy="1.2em"
class="st4">AspectJ integration</tspan></text> </g>
</g>
<g id="group5-22" transform="translate(133.228,-481.89) scale(-1,1)" v:mID="5" v:groupContext="group">
<v:userDefs>
<v:ud v:nameU="Scale" v:val="VT0(1):26"/>
<v:ud v:nameU="AntiScale" v:val="VT0(1):26"/>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<title>3-D box.5</title>
<desc>DAO Spring JDBC Transaction management</desc>
<g id="shape6-23" v:mID="6" v:groupContext="shape" transform="translate(0,14.1732)">
<title>Sheet.6</title>
<path d="M0 827.72 L104.88 827.72 L90.71 841.89 L-14.17 841.89 L0 827.72 Z" class="st1"/>
</g>
<g id="shape7-25" v:mID="7" v:groupContext="shape" transform="translate(-14.1732,0)">
<title>Sheet.7</title>
<path d="M0 856.06 L14.17 841.89 L14.17 657.64 L0 671.81 L0 856.06 Z" class="st1"/>
</g>
<g id="shape8-27" v:mID="8" v:groupContext="shape">
<title>Sheet.8</title>
<rect x="0" y="657.638" width="104.882" height="184.252" class="st2"/>
</g>
<g id="shape5-29" v:mID="5" v:groupContext="groupContent">
<v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/>
<v:textRect cx="52.4409" cy="749.764" width="104.89" height="184.252"/>
<text x="-85.76" y="735.96" transform="scale(-1,1)" class="st3" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>DAO<v:newlineChar/><v:newlineChar/><tspan
x="-81.33" dy="2.76em" class="st4">Spring JDBC<v:newlineChar/></tspan><tspan x="-78.56" dy="1.2em"
class="st4">Transaction </tspan><tspan x="-81.62" dy="1.2em" class="st4">management</tspan></text> </g>
</g>
<g id="group13-34" transform="translate(413.858,-368.504) scale(-1,1)" v:mID="13" v:groupContext="group">
<v:userDefs>
<v:ud v:nameU="Scale" v:val="VT0(1):26"/>
<v:ud v:nameU="AntiScale" v:val="VT0(1):26"/>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<title>3-D box.13</title>
<desc>JEE JMX JMS JCA Remoting EJBs Email</desc>
<g id="shape14-35" v:mID="14" v:groupContext="shape" transform="translate(0,14.1732)">
<title>Sheet.14</title>
<path d="M0 827.72 L113.39 827.72 L99.21 841.89 L-14.17 841.89 L0 827.72 Z" class="st1"/>
</g>
<g id="shape15-37" v:mID="15" v:groupContext="shape" transform="translate(-14.1732,0)">
<title>Sheet.15</title>
<path d="M0 856.06 L14.17 841.89 L14.17 544.25 L0 558.43 L0 856.06 Z" class="st1"/>
</g>
<g id="shape16-39" v:mID="16" v:groupContext="shape">
<title>Sheet.16</title>
<rect x="0" y="544.252" width="113.386" height="297.638" class="st2"/>
</g>
<g id="shape13-41" v:mID="13" v:groupContext="groupContent">
<v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/>
<v:textRect cx="56.6929" cy="693.071" width="113.39" height="297.638"/>
<text x="-85.04" y="661.27" transform="scale(-1,1)" class="st3" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>JEE<v:newlineChar/><v:newlineChar/><tspan
x="-66.69" dy="2.76em" class="st4">JMX<v:newlineChar/></tspan><tspan x="-66.69" dy="1.2em" class="st4">JMS<v:newlineChar/></tspan><tspan
x="-66.13" dy="1.2em" class="st4">JCA<v:newlineChar/></tspan><tspan x="-78.08" dy="1.2em" class="st4">Remoting<v:newlineChar/></tspan><tspan
x="-68.36" dy="1.2em" class="st4">EJBs<v:newlineChar/></tspan><tspan x="-69.19" dy="1.2em" class="st4">Email</tspan></text> </g>
</g>
<g id="group17-49" transform="translate(552.756,-368.504) scale(-1,1)" v:mID="17" v:groupContext="group">
<v:userDefs>
<v:ud v:nameU="Scale" v:val="VT0(1):26"/>
<v:ud v:nameU="AntiScale" v:val="VT0(1):26"/>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<title>3-D box.17</title>
<desc>Web Spring Web MVC Framework Integration Struts WebWork Tapes...</desc>
<g id="shape18-50" v:mID="18" v:groupContext="shape" transform="translate(0,14.1732)">
<title>Sheet.18</title>
<path d="M0 827.72 L113.39 827.72 L99.21 841.89 L-14.17 841.89 L0 827.72 Z" class="st1"/>
</g>
<g id="shape19-52" v:mID="19" v:groupContext="shape" transform="translate(-14.1732,0)">
<title>Sheet.19</title>
<path d="M0 856.06 L14.17 841.89 L14.17 544.25 L0 558.43 L0 856.06 Z" class="st1"/>
</g>
<g id="shape20-54" v:mID="20" v:groupContext="shape">
<title>Sheet.20</title>
<rect x="0" y="544.252" width="113.386" height="297.638" class="st2"/>
</g>
<g id="shape17-56" v:mID="17" v:groupContext="groupContent">
<v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/>
<v:textRect cx="56.6929" cy="693.071" width="113.39" height="297.638"/>
<text x="-88.35" y="613.27" transform="scale(-1,1)" class="st3" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>Web<v:newlineChar/><v:newlineChar/><tspan
x="-95.31" dy="2.76em" class="st4">Spring Web MVC<v:newlineChar/></tspan><tspan x="-106.71" dy="1.2em"
class="st4">Framework Integration<v:newlineChar/></tspan><tspan x="-69.75" dy="1.2em" class="st4">Struts<v:newlineChar/></tspan><tspan
x="-78.63" dy="1.2em" class="st4">WebWork<v:newlineChar/></tspan><tspan x="-76.14" dy="1.2em"
class="st4">Tapestry<v:newlineChar/></tspan><tspan x="-65.57" dy="1.2em" class="st4">JSF<v:newlineChar/></tspan><tspan
x="-97.82" dy="1.2em" class="st4">Rich View Support<v:newlineChar/></tspan><tspan x="-68.36" dy="1.2em"
class="st4">JSPs<v:newlineChar/></tspan><tspan x="-74.19" dy="1.2em" class="st4">Velocity<v:newlineChar/></tspan><tspan
x="-82.52" dy="1.2em" class="st4">FreeMarker<v:newlineChar/></tspan><tspan x="-66.69" dy="1.2em"
class="st4">PDF<v:newlineChar/></tspan><tspan x="-90.59" dy="1.2em" class="st4">Jasper Reports<v:newlineChar/></tspan><tspan
x="-68.91" dy="1.2em" class="st4">Excel<v:newlineChar/></tspan><tspan x="-99.48" dy="1.2em" class="st4">Spring Portlet MVC</tspan></text> </g>
</g>
<g id="group21-72" transform="translate(269.291,-481.89) scale(-1,1)" v:mID="21" v:groupContext="group">
<v:userDefs>
<v:ud v:nameU="Scale" v:val="VT0(1):26"/>
<v:ud v:nameU="AntiScale" v:val="VT0(1):26"/>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<title>3-D box.21</title>
<desc>ORM Hibernate JPA TopLink JDO OJB iBatis</desc>
<g id="shape22-73" v:mID="22" v:groupContext="shape" transform="translate(0,14.1732)">
<title>Sheet.22</title>
<path d="M0 827.72 L107.72 827.72 L93.54 841.89 L-14.17 841.89 L0 827.72 Z" class="st1"/>
</g>
<g id="shape23-75" v:mID="23" v:groupContext="shape" transform="translate(-14.1732,0)">
<title>Sheet.23</title>
<path d="M0 856.06 L14.17 841.89 L14.17 657.64 L0 671.81 L0 856.06 Z" class="st1"/>
</g>
<g id="shape24-77" v:mID="24" v:groupContext="shape">
<title>Sheet.24</title>
<rect x="0" y="657.638" width="107.717" height="184.252" class="st2"/>
</g>
<g id="shape21-79" v:mID="21" v:groupContext="groupContent">
<v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/>
<v:textRect cx="53.8583" cy="749.764" width="107.72" height="184.252"/>
<text x="-88.86" y="717.96" transform="scale(-1,1)" class="st3" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>ORM<v:newlineChar/><v:newlineChar/><tspan
x="-75.55" dy="2.76em" class="st4">Hibernate<v:newlineChar/></tspan><tspan x="-63.04" dy="1.2em"
class="st4">JPA<v:newlineChar/></tspan><tspan x="-71.65" dy="1.2em" class="st4">TopLink<v:newlineChar/></tspan><tspan
x="-63.87" dy="1.2em" class="st4">JDO<v:newlineChar/></tspan><tspan x="-63.59" dy="1.2em" class="st4">OJB<v:newlineChar/></tspan><tspan
x="-66.09" dy="1.2em" class="st4">iBatis</tspan></text> </g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<!-- Generated by Microsoft Visio 11.0, SVG Export, v1.0 thirdparty-web.svg Page-1 -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="4.90667in"
height="3.29238in" viewBox="0 0 353.28 237.051" xml:space="preserve" color-interpolation-filters="sRGB" class="st9">
<v:documentProperties v:langID="1033" v:viewMarkup="false"/>
<style type="text/css">
<![CDATA[
.st1 {fill:#f4f7f0;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st2 {fill:#000000;font-family:Arial;font-size:0.833336em}
.st3 {fill:#ecefe2;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st4 {visibility:visible}
.st5 {fill:#84877b;stroke:#84877b;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st6 {fill:#dde2cd;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st7 {fill:#000000;font-family:Arial;font-size:0.75em}
.st8 {font-size:1em}
.st9 {fill:none;fill-rule:evenodd;font-size:12;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
]]>
</style>
<g v:mID="0" v:index="1" v:groupContext="foregroundPage">
<title>Page-1</title>
<v:pageProperties v:drawingScale="1" v:pageScale="1" v:drawingUnits="0" v:shadowOffsetX="9" v:shadowOffsetY="-9"/>
<g id="shape11-1" v:mID="11" v:groupContext="shape" transform="translate(0.24,-0.24)">
<title>Box.11</title>
<desc>Servlet Container (Tomcat / Jetty)</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="176.4" cy="118.766" width="352.8" height="236.571"/>
<rect x="0" y="0.48" width="352.8" height="236.571" class="st1"/>
<text x="101.65" y="223.77" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/>Servlet Container (Tomcat / Jetty)</text> </g>
<g id="shape6-4" v:mID="6" v:groupContext="shape" transform="translate(12.84,-25.9543)">
<title>Box.6</title>
<desc>Spring Core</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="81.9" cy="206.194" width="163.8" height="61.7143"/>
<rect x="0" y="175.337" width="163.8" height="61.7143" class="st3"/>
<text x="55.22" y="221.19" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/><v:newlineChar/>Spring Core</text> </g>
<g id="shape7-7" v:mID="7" v:groupContext="shape" transform="translate(176.64,-25.9543)">
<title>Box.7</title>
<desc>Spring DAO</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="81.9" cy="206.194" width="163.81" height="61.7143"/>
<rect x="0" y="175.337" width="163.8" height="61.7143" class="st3"/>
<text x="55.22" y="221.19" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/><v:newlineChar/>Spring DAO</text> </g>
<g id="shape8-10" v:mID="8" v:groupContext="shape" transform="translate(176.64,-87.6686)">
<title>Box.8</title>
<desc>Spring ORM</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="81.9" cy="206.194" width="163.8" height="61.7143"/>
<rect x="0" y="175.337" width="163.8" height="61.7143" class="st3"/>
<text x="54.39" y="197.19" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Spring ORM<v:newlineChar/><v:newlineChar/></text> </g>
<g id="shape9-13" v:mID="9" v:groupContext="shape" transform="translate(12.84,-149.383)">
<title>Box.9</title>
<desc>Spring WEB</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="163.8" cy="206.194" width="327.6" height="61.7143"/>
<rect x="0" y="175.337" width="327.6" height="61.7143" class="st3"/>
<text x="136.57" y="221.19" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/><v:newlineChar/>Spring WEB</text> </g>
<g id="shape10-16" v:mID="10" v:groupContext="shape" transform="translate(107.34,-188.811)">
<title>Box.10</title>
<desc>Web frontend using Struts or WebWork</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="72.45" cy="218.194" width="144.91" height="37.7143"/>
<g id="shadow10-17" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="199.337" width="144.9" height="37.7143" class="st5"/>
</g>
<rect x="0" y="199.337" width="144.9" height="37.7143" class="st6"/>
<text x="33.43" y="215.49" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Web frontend using<v:newlineChar/><tspan
x="34.44" dy="1.2em" class="st8">Struts or WebWork</tspan></text> </g>
<g id="shape12-22" v:mID="12" v:groupContext="shape" transform="translate(12.84,-87.6686)">
<title>Box.12</title>
<desc>Spring AOP</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="81.9" cy="206.194" width="163.8" height="61.7143"/>
<rect x="0" y="175.337" width="163.8" height="61.7143" class="st3"/>
<text x="55.5" y="197.19" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Spring AOP<v:newlineChar/><v:newlineChar/></text> </g>
<g id="shape13-25" v:mID="13" v:groupContext="shape" transform="translate(107.34,-94.5257)">
<title>Box.13</title>
<desc>Transaction management Using Spring decl. trans.</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="72.45" cy="223.337" width="144.91" height="27.4286"/>
<g id="shadow13-26" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="209.623" width="144.9" height="27.4286" class="st5"/>
</g>
<rect x="0" y="209.623" width="144.9" height="27.4286" class="st6"/>
<text x="21.42" y="220.64" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Transaction management<v:newlineChar/><tspan
x="23.43" dy="1.2em" class="st8">Using Spring decl</tspan>. trans.</text> </g>
<g id="shape5-31" v:mID="5" v:groupContext="shape" transform="translate(107.34,-67.0971)">
<title>Box</title>
<desc>Hibernate mappings Custom Hibernate DAOs</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="72.45" cy="223.337" width="144.91" height="27.4286"/>
<g id="shadow5-32" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="209.623" width="144.9" height="27.4286" class="st5"/>
</g>
<rect x="0" y="209.623" width="144.9" height="27.4286" class="st6"/>
<text x="32.18" y="220.64" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Hibernate mappings<v:newlineChar/><tspan
x="22.93" dy="1.2em" class="st8">Custom Hibernate DAOs</tspan></text> </g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -0,0 +1,517 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<book>
<bookinfo>
<title>Reference Documentation</title>
<productname>Spring Framework</productname>
<releaseinfo>3.1</releaseinfo>
<mediaobject>
<imageobject role="fo">
<imagedata align="center" fileref="images/logo-pdf.png" format="PNG"
width="240" />
</imageobject>
</mediaobject>
<authorgroup>
<author>
<firstname>Rod</firstname>
<surname>Johnson</surname>
</author>
<author>
<firstname>Juergen</firstname>
<surname>Hoeller</surname>
</author>
<author>
<firstname>Keith</firstname>
<surname>Donald</surname>
</author>
<author>
<firstname>Colin</firstname>
<surname>Sampaleanu</surname>
</author>
<author>
<firstname>Rob</firstname>
<surname>Harrop</surname>
</author>
<author>
<firstname>Thomas</firstname>
<surname>Risberg</surname>
</author>
<author>
<firstname>Alef</firstname>
<surname>Arendsen</surname>
</author>
<author>
<firstname>Darren</firstname>
<surname>Davison</surname>
</author>
<author>
<firstname>Dmitriy</firstname>
<surname>Kopylenko</surname>
</author>
<author>
<firstname>Mark</firstname>
<surname>Pollack</surname>
</author>
<author>
<firstname>Thierry</firstname>
<surname>Templier</surname>
</author>
<author>
<firstname>Erwin</firstname>
<surname>Vervaet</surname>
</author>
<author>
<firstname>Portia</firstname>
<surname>Tung</surname>
</author>
<author>
<firstname>Ben</firstname>
<surname>Hale</surname>
</author>
<author>
<firstname>Adrian</firstname>
<surname>Colyer</surname>
</author>
<author>
<firstname>John</firstname>
<surname>Lewis</surname>
</author>
<author>
<firstname>Costin</firstname>
<surname>Leau</surname>
</author>
<author>
<firstname>Mark</firstname>
<surname>Fisher</surname>
</author>
<author>
<firstname>Sam</firstname>
<surname>Brannen</surname>
</author>
<author>
<firstname>Ramnivas</firstname>
<surname>Laddad</surname>
</author>
<author>
<firstname>Arjen</firstname>
<surname>Poutsma</surname>
</author>
<author>
<firstname>Chris</firstname>
<surname>Beams</surname>
</author>
<author>
<firstname>Tareq</firstname>
<surname>Abedrabbo</surname>
</author>
<author>
<firstname>Andy</firstname>
<surname>Clement</surname>
</author>
<author>
<firstname>Dave</firstname>
<surname>Syer</surname>
</author>
<author>
<firstname>Oliver</firstname>
<surname>Gierke</surname>
</author>
<author>
<firstname>Rossen</firstname>
<surname>Stoyanchev</surname>
</author>
</authorgroup>
<copyright>
<year>2004-2011</year>
<holder>Rod Johnson, Juergen Hoeller, Keith Donald, Colin Sampaleanu,
Rob Harrop, Alef Arendsen, Thomas Risberg, Darren Davison, Dmitriy
Kopylenko, Mark Pollack, Thierry Templier, Erwin Vervaet, Portia Tung,
Ben Hale, Adrian Colyer, John Lewis, Costin Leau, Mark Fisher, Sam
Brannen, Ramnivas Laddad, Arjen Poutsma, Chris Beams, Tareq Abedrabbo,
Andy Clement, Dave Syer, Oliver Gierke, Rossen Stoyanchev</holder>
</copyright>
<legalnotice>
<para>Copies of this document may be made for your own use and for
distribution to others, provided that you do not charge any fee for such
copies and further provided that each copy contains this Copyright
Notice, whether distributed in print or electronically.</para>
</legalnotice>
</bookinfo>
<!-- front matter -->
<toc></toc>
<part id="spring-introduction">
<title>Overview of Spring Framework</title>
<partintro id="spring-core-intro">
<para>The Spring Framework is a lightweight solution and a potential
one-stop-shop for building your enterprise-ready applications. However,
Spring is modular, allowing you to use only those parts that you need,
without having to bring in the rest. You can use the IoC container, with
Struts on top, but you can also use only the <link
linkend="orm-hibernate">Hibernate integration code</link> or the <link
linkend="jdbc-introduction">JDBC abstraction layer</link>. The Spring
Framework supports declarative transaction management, remote access to
your logic through RMI or web services, and various options for
persisting your data. It offers a full-featured <link
linkend="mvc-introduction">MVC framework</link>, and enables you to
integrate <link linkend="aop-introduction">AOP</link> transparently into
your software.</para>
<para>Spring is designed to be non-intrusive, meaning that your domain
logic code generally has no dependencies on the framework itself. In
your integration layer (such as the data access layer), some
dependencies on the data access technology and the Spring libraries will
exist. However, it should be easy to isolate these dependencies from the
rest of your code base.</para>
<para>This document is a reference guide to Spring Framework features.
If you have any requests, comments, or questions on this document,
please post them on the user mailing list or on the support forums at
<ulink url="http://forum.springsource.org/"></ulink>.<!--Missing link above. PDF shows it as http://forum.springsource.org/--></para>
</partintro>
<xi:include href="overview.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
<part id="spring-whats-new">
<title>What's New in Spring 3</title>
<xi:include href="new-in-3.0.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="new-in-3.1.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
<part id="spring-core">
<title>Core Technologies</title>
<partintro id="spring-core-intro">
<para>This part of the reference documentation covers all of those
technologies that are absolutely integral to the Spring
Framework.</para>
<para>Foremost amongst these is the Spring Framework's Inversion of
Control (IoC) container. A thorough treatment of the Spring Framework's
IoC container is closely followed by comprehensive coverage of Spring's
Aspect-Oriented Programming (AOP) technologies. The Spring Framework has
its own AOP framework, which is conceptually easy to understand, and
which successfully addresses the 80% sweet spot of AOP requirements in
Java enterprise programming.</para>
<para>Coverage of Spring's integration with AspectJ (currently the
richest - in terms of features - and certainly most mature AOP
implementation in the Java enterprise space) is also provided.</para>
<para>Finally, the adoption of the test-driven-development (TDD)
approach to software development is certainly advocated by the Spring
team, and so coverage of Spring's support for integration testing is
covered (alongside best practices for unit testing). The Spring team has
found that the correct use of IoC certainly does make both unit and
integration testing easier (in that the presence of setter methods and
appropriate constructors on classes makes them easier to wire together
in a test without having to set up service locator registries and
suchlike)... the chapter dedicated solely to testing will hopefully
convince you of this as well.</para>
<itemizedlist>
<listitem>
<para><xref linkend="beans" /></para>
</listitem>
<listitem>
<para><xref linkend="resources" /></para>
</listitem>
<listitem>
<para><xref linkend="validation" /></para>
</listitem>
<listitem>
<para><xref linkend="expressions" /></para>
</listitem>
<listitem>
<para><xref linkend="aop" /></para>
</listitem>
<listitem>
<para><xref linkend="aop-api" /></para>
</listitem>
<listitem>
<para><xref linkend="testing" /></para>
</listitem>
</itemizedlist>
</partintro>
<xi:include href="beans.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="resources.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="validation.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="expressions.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="aop.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="aop-api.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="testing.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
<part id="spring-data-tier">
<title>Data Access</title>
<partintro id="spring-data-tier-intro">
<para>This part of the reference documentation is concerned with data
access and the interaction between the data access layer and the
business or service layer.</para>
<para>Spring's comprehensive transaction management support is covered
in some detail, followed by thorough coverage of the various data access
frameworks and technologies that the Spring Framework integrates
with.</para>
<itemizedlist>
<listitem>
<para><xref linkend="transaction" /></para>
</listitem>
<listitem>
<para><xref linkend="dao" /></para>
</listitem>
<listitem>
<para><xref linkend="jdbc" /></para>
</listitem>
<listitem>
<para><xref linkend="orm" /></para>
</listitem>
<listitem>
<para><xref linkend="oxm" /></para>
</listitem>
</itemizedlist>
</partintro>
<xi:include href="transaction.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="dao.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="jdbc.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="orm.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="oxm.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
<part id="spring-web">
<title>The Web</title>
<partintro id="spring-web-intro">
<para>This part of the reference documentation covers the Spring
Framework's support for the presentation tier (and specifically
web-based presentation tiers).</para>
<para>The Spring Framework's own web framework, <link
linkend="mvc">Spring Web MVC</link>, is covered in the first couple of
chapters. A number of the remaining chapters in this part of the
reference documentation are concerned with the Spring Framework's
integration with other web technologies, such as <link
linkend="struts">Struts</link> and <link linkend="jsf">JSF</link> (to
name but two).</para>
<para>This section concludes with coverage of Spring's MVC <link
linkend="portlet">portlet framework</link>.</para>
<itemizedlist>
<listitem>
<para><xref linkend="mvc" /></para>
</listitem>
<listitem>
<para><xref linkend="view" /></para>
</listitem>
<listitem>
<para><xref linkend="web-integration" /></para>
</listitem>
<listitem>
<para><xref linkend="portlet" /></para>
</listitem>
</itemizedlist>
</partintro>
<xi:include href="mvc.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="view.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="web-integration.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="portlet.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
<part id="spring-integration">
<title>Integration</title>
<partintro id="spring-integration-intro">
<para>This part of the reference documentation covers the Spring
Framework's integration with a number of Java EE (and related)
technologies.</para>
<itemizedlist>
<listitem>
<para><xref linkend="remoting" /></para>
</listitem>
<listitem>
<para><xref linkend="ejb" /></para>
</listitem>
<listitem>
<para><xref linkend="jms" /></para>
</listitem>
<listitem>
<para><xref linkend="jmx" /></para>
</listitem>
<listitem>
<para><xref linkend="cci" /></para>
</listitem>
<listitem>
<para><xref linkend="mail" /></para>
</listitem>
<listitem>
<para><xref linkend="scheduling" /></para>
</listitem>
<listitem>
<para><xref linkend="dynamic-language" /></para>
</listitem>
<listitem>
<para><xref linkend="cache" /></para>
</listitem>
</itemizedlist>
</partintro>
<xi:include href="remoting.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="ejb.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="jms.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="jmx.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="cci.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="mail.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="scheduling.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="dynamic-languages.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="cache.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
<!-- back matter -->
<part id="spring-appendices">
<title>Appendices</title>
<xi:include href="classic-spring.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="classic-aop-spring.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="xsd-configuration.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="xml-custom.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="dtd.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="spring.tld.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="spring-form.tld.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
</book>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,400 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="mail">
<title>Email</title>
<section id="mail-introduction">
<title>Introduction</title>
<sidebar>
<title>Library dependencies</title>
<para>The following additional jars to be on the classpath of your
application in order to be able to use the Spring Framework's email library.</para>
<itemizedlist>
<listitem>
<para>The <ulink url="http://java.sun.com/products/javamail/">JavaMail</ulink> <filename class="libraryfile">mail.jar</filename> library</para>
</listitem>
<listitem>
<para>The <ulink url="http://java.sun.com/products/javabeans/jaf/downloads/index.html">JAF</ulink> <filename class="libraryfile">activation.jar</filename> library</para>
</listitem>
</itemizedlist>
<para>All of these libraries are freely available on the web.</para>
</sidebar>
<para>The Spring Framework provides a helpful utility library for sending
email that shields the user from the specifics of the underlying mailing
system and is responsible for low level resource handling on behalf of
the client.</para>
<para>The <literal>org.springframework.mail</literal> package is the root level package
for the Spring Framework's email support. The central interface for sending
emails is the <interfacename>MailSender</interfacename> interface; a simple value object
encapsulating the properties of a simple mail such as <emphasis>from</emphasis> and
<emphasis>to</emphasis> (plus many others) is the <classname>SimpleMailMessage</classname> class.
This package also contains a hierarchy of checked exceptions which provide
a higher level of abstraction over the lower level mail system exceptions
with the root exception being <exceptionname>MailException</exceptionname>. Please
refer to the JavaDocs for more information on the rich mail exception hierarchy.</para>
<para>The <interfacename>org.springframework.mail.javamail.JavaMailSender</interfacename>
interface adds specialized <emphasis>JavaMail</emphasis> features such as MIME
message support to the <interfacename>MailSender</interfacename> interface
(from which it inherits). <interfacename>JavaMailSender</interfacename> also provides a
callback interface for preparation of JavaMail MIME messages, called
<interfacename>org.springframework.mail.javamail.MimeMessagePreparator</interfacename></para>
</section>
<section id="mail-usage">
<title>Usage</title>
<para>Let's assume there is a business interface called <interfacename>OrderManager</interfacename>:</para>
<programlisting language="java"><![CDATA[public interface OrderManager {
void placeOrder(Order order);
}]]></programlisting>
<para>Let us also assume that there is a requirement stating that an email message
with an order number needs to be generated and sent to a customer placing the
relevant order.</para>
<section id="mail-usage-simple">
<title>Basic <interfacename>MailSender</interfacename> and <classname>SimpleMailMessage</classname> usage</title>
<programlisting language="java"><![CDATA[import org.springframework.mail.MailException;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
public class SimpleOrderManager implements OrderManager {
private MailSender mailSender;
private SimpleMailMessage templateMessage;
public void setMailSender(MailSender mailSender) {
this.mailSender = mailSender;
}
public void setTemplateMessage(SimpleMailMessage templateMessage) {
this.templateMessage = templateMessage;
}
public void placeOrder(Order order) {
]]><lineannotation>// Do the business calculations...</lineannotation><![CDATA[
]]><lineannotation>// Call the collaborators to persist the order...</lineannotation><![CDATA[
]]><lineannotation>// Create a thread safe "copy" of the template message and customize it</lineannotation><![CDATA[
SimpleMailMessage msg = new SimpleMailMessage(this.templateMessage);
msg.setTo(order.getCustomer().getEmailAddress());
msg.setText(
"Dear " + order.getCustomer().getFirstName()
+ order.getCustomer().getLastName()
+ ", thank you for placing order. Your order number is "
+ order.getOrderNumber());
try{
this.mailSender.send(msg);
}
catch(MailException ex) {
]]><lineannotation>// simply log it and go on...</lineannotation><![CDATA[
System.err.println(ex.getMessage());
}
}
}]]></programlisting>
<para>Find below the bean definitions for the above code:</para>
<programlisting language="xml"><![CDATA[<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="mail.mycompany.com"/>
</bean>
]]><lineannotation>&lt;!-- this is a template message that we can pre-load with default state --&gt;</lineannotation><![CDATA[
<bean id="templateMessage" class="org.springframework.mail.SimpleMailMessage">
<property name="from" value="customerservice@mycompany.com"/>
<property name="subject" value="Your order"/>
</bean>
<bean id="orderManager" class="com.mycompany.businessapp.support.SimpleOrderManager">
<property name="mailSender" ref="mailSender"/>
<property name="templateMessage" ref="templateMessage"/>
</bean>]]></programlisting>
</section>
<section id="mail-usage-mime">
<title>Using the <interfacename>JavaMailSender</interfacename> and the <classname>MimeMessagePreparator</classname></title>
<para>Here is another implementation of <interfacename>OrderManager</interfacename> using
the <interfacename>MimeMessagePreparator</interfacename> callback interface. Please note
in this case that the <literal>mailSender</literal> property is of type
<interfacename>JavaMailSender</interfacename> so that we are able to use the JavaMail
<classname>MimeMessage</classname> class:</para>
<programlisting language="java"><![CDATA[import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessagePreparator;
public class SimpleOrderManager implements OrderManager {
private JavaMailSender mailSender;
public void setMailSender(JavaMailSender mailSender) {
this.mailSender = mailSender;
}
public void placeOrder(final Order order) {
]]><lineannotation>// Do the business calculations...</lineannotation><![CDATA[
]]><lineannotation>// Call the collaborators to persist the order...</lineannotation><![CDATA[
MimeMessagePreparator preparator = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage) throws Exception {
mimeMessage.setRecipient(Message.RecipientType.TO,
new InternetAddress(order.getCustomer().getEmailAddress()));
mimeMessage.setFrom(new InternetAddress("mail@mycompany.com"));
mimeMessage.setText(
"Dear " + order.getCustomer().getFirstName() + " "
+ order.getCustomer().getLastName()
+ ", thank you for placing order. Your order number is "
+ order.getOrderNumber());
}
};
try {
this.mailSender.send(preparator);
}
catch (MailException ex) {
]]><lineannotation>// simply log it and go on...</lineannotation><![CDATA[
System.err.println(ex.getMessage());
}
}
}]]></programlisting>
<note>
<para>The mail code is a crosscutting concern and could well be a candidate
for refactoring into a <link linkend="aop">custom Spring AOP aspect</link>,
which then could be executed at appropriate joinpoints on the
<interfacename>OrderManager</interfacename> target.</para>
</note>
<para>The Spring Framework's mail support ships with the standard JavaMail
implementation. Please refer to the relevant JavaDocs for more information.</para>
</section>
</section>
<section id="mail-javamail-mime">
<title>Using the JavaMail <classname>MimeMessageHelper</classname></title>
<para>A class that comes in pretty handy when dealing with JavaMail messages is
the <classname>org.springframework.mail.javamail.MimeMessageHelper</classname> class,
which shields you from having to use the verbose JavaMail API. Using
the <classname>MimeMessageHelper</classname> it is pretty easy to
create a <classname>MimeMessage</classname>:</para>
<programlisting language="java"><lineannotation>// of course you would use DI in any real-world cases</lineannotation><![CDATA[
JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost("mail.host.com");
MimeMessage message = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message);
helper.setTo("test@host.com");
helper.setText("Thank you for ordering!");
sender.send(message);]]></programlisting>
<section id="mail-javamail-mime-attachments">
<title>Sending attachments and inline resources</title>
<para>Multipart email messages allow for both attachments and inline resources.
Examples of inline resources would be images or a stylesheet you want to use
in your message, but that you don't want displayed as an attachment.</para>
<section id="mail-javamail-mime-attachments-attachment">
<title>Attachments</title>
<para>The following example shows you how to use the
<classname>MimeMessageHelper</classname> to send an email along with a
single JPEG image attachment.</para>
<programlisting language="java"><![CDATA[JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost("mail.host.com");
MimeMessage message = sender.createMimeMessage();
]]><lineannotation>// use the true flag to indicate you need a multipart message</lineannotation><![CDATA[
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo("test@host.com");
helper.setText("Check out this image!");
]]><lineannotation>// let's attach the infamous windows Sample file (this time copied to c:/)</lineannotation><![CDATA[
FileSystemResource file = new FileSystemResource(new File("c:/Sample.jpg"));
helper.addAttachment("CoolImage.jpg", file);
sender.send(message);]]></programlisting>
</section>
<section id="mail-javamail-mime-attachments-inline">
<title>Inline resources</title>
<para>The following example shows you how to use the
<classname>MimeMessageHelper</classname> to send an email along with an
inline image.</para>
<programlisting language="java"><![CDATA[JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost("mail.host.com");
MimeMessage message = sender.createMimeMessage();
]]><lineannotation>// use the true flag to indicate you need a multipart message</lineannotation><![CDATA[
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo("test@host.com");
]]><lineannotation>// use the true flag to indicate the text included is HTML</lineannotation><![CDATA[
helper.setText("<html><body><img src='cid:identifier1234'></body></html>", true);
]]><lineannotation>// let's include the infamous windows Sample file (this time copied to c:/)</lineannotation><![CDATA[
FileSystemResource res = new FileSystemResource(new File("c:/Sample.jpg"));
helper.addInline("identifier1234", res);
sender.send(message);]]></programlisting>
<warning>
<para>Inline resources are added to the mime message using the
specified <literal>Content-ID</literal> (<literal>identifier1234</literal>
in the above example). The order in which you are adding the text and the
resource are <emphasis role="bold">very</emphasis> important. Be sure to
<emphasis>first add the text</emphasis> and after that the resources. If
you are doing it the other way around, it won't work!</para>
</warning>
</section>
</section>
<section id="mail-templates">
<title>Creating email content using a templating library</title>
<para>The code in the previous examples explicitly created the
content of the email message, using methods calls such as
<methodname>message.setText(..)</methodname>. This is fine for
simple cases, and it is okay in the context of the aforementioned
examples, where the intent was to show you the very basics of the API.</para>
<para>In your typical enterprise application though, you are not going
to create the content of your emails using the above approach for a number
of reasons.</para>
<para>
<itemizedlist>
<listitem>
<para>Creating HTML-based email content in Java code is tedious and error prone</para>
</listitem>
<listitem>
<para>There is no clear separation between display logic and business logic</para>
</listitem>
<listitem>
<para>Changing the display structure of the email content requires writing Java code, recompiling, redeploying...</para>
</listitem>
</itemizedlist>
</para>
<para>Typically the approach taken to address these issues is to use a template library
such as FreeMarker or Velocity to define the display structure of email content. This leaves
your code tasked only with creating the data that is to be rendered in the email
template and sending the email. It is definitely a best practice for when
the content of your emails becomes even moderately complex, and with
the Spring Framework's support classes for FreeMarker and Velocity becomes
quite easy to do. Find below an example of using the Velocity template library
to create email content.</para>
<section id="mail-templates-example">
<title>A Velocity-based example</title>
<para>To use <ulink url="http://velocity.apache.org">Velocity</ulink> to
create your email template(s), you will need to have the Velocity libraries
available on your classpath. You will also need to create one or more Velocity templates
for the email content that your application needs. Find below the Velocity
template that this example will be using. As you can see it is HTML-based,
and since it is plain text it can be created using your favorite HTML
or text editor.</para>
<programlisting language="xml"><lineannotation># in the <literal>com/foo/package</literal></lineannotation><![CDATA[
<html>
<body>
<h3>Hi ${user.userName}, welcome to the Chipping Sodbury On-the-Hill message boards!</h3>
<div>
Your email address is <a href="mailto:${user.emailAddress}">${user.emailAddress}</a>.
</div>
</body>
</html>]]></programlisting>
<para>Find below some simple code and Spring XML configuration that
makes use of the above Velocity template to create email content and
send email(s).</para>
<programlisting language="java"><![CDATA[package com.foo;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.ui.velocity.VelocityEngineUtils;
import javax.mail.internet.MimeMessage;
import java.util.HashMap;
import java.util.Map;
public class SimpleRegistrationService implements RegistrationService {
private JavaMailSender mailSender;
private VelocityEngine velocityEngine;
public void setMailSender(JavaMailSender mailSender) {
this.mailSender = mailSender;
}
public void setVelocityEngine(VelocityEngine velocityEngine) {
this.velocityEngine = velocityEngine;
}
public void register(User user) {
]]><lineannotation>// Do the registration logic...</lineannotation><![CDATA[
sendConfirmationEmail(user);
}
private void sendConfirmationEmail(final User user) {
MimeMessagePreparator preparator = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper message = new MimeMessageHelper(mimeMessage);
message.setTo(user.getEmailAddress());
message.setFrom("webmaster@csonth.gov.uk"); ]]><lineannotation>// could be parameterized...</lineannotation><![CDATA[
Map model = new HashMap();
model.put("user", user);
String text = VelocityEngineUtils.mergeTemplateIntoString(
velocityEngine, "com/dns/registration-confirmation.vm", model);
message.setText(text, true);
}
};
this.mailSender.send(preparator);
}
}]]></programlisting>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="mail.csonth.gov.uk"/>
</bean>
<bean id="registrationService" class="com.foo.SimpleRegistrationService">
<property name="mailSender" ref="mailSender"/>
<property name="velocityEngine" ref="velocityEngine"/>
</bean>
<bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
<property name="velocityProperties">
<value>
resource.loader=class
class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
</value>
</property>
</bean>
</beans>]]></programlisting>
</section>
</section>
</section>
</chapter>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,514 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="new-in-3.0">
<title>New Features and Enhancements in Spring 3.0</title>
<para>If you have been using the Spring Framework for some time, you will be
aware that Spring has undergone two major revisions: Spring 2.0, released in
October 2006, and Spring 2.5, released in November 2007. It is now time for
a third overhaul resulting in Spring 3.0.</para>
<sidebar id="new-in-3.0-intro-java">
<title>Java SE and Java EE Support</title>
<para>The Spring Framework is now based on Java 5, and Java 6 is fully
supported.</para>
<para>Furthermore, Spring is compatible with J2EE 1.4 and Java EE 5, while
at the same time introducing some early support for Java EE 6.</para>
</sidebar>
<section id="new-in-3.0-intro">
<title>Java 5</title>
<para>The entire framework code has been revised to take advantage of Java
5 features like generics, varargs and other language improvements. We have
done our best to still keep the code backwards compatible. We now have
consistent use of generic Collections and Maps, consistent use of generic
FactoryBeans, and also consistent resolution of bridge methods in the
Spring AOP API. Generic ApplicationListeners automatically receive
specific event types only. All callback interfaces such as
TransactionCallback and HibernateCallback declare a generic result value
now. Overall, the Spring core codebase is now freshly revised and
optimized for Java 5.</para>
<para>Spring's TaskExecutor abstraction has been updated for close
integration with Java 5's java.util.concurrent facilities. We provide
first-class support for Callables and Futures now, as well as
ExecutorService adapters, ThreadFactory integration, etc. This has been
aligned with JSR-236 (Concurrency Utilities for Java EE 6) as far as
possible. Furthermore, we provide support for asynchronous method
invocations through the use of the new @Async annotation (or EJB 3.1's
@Asynchronous annotation).</para>
</section>
<section id="new-in-3.0-improved-docs">
<title>Improved documentation</title>
<para>The Spring reference documentation has also substantially been
updated to reflect all of the changes and new features for Spring 3.0.
While every effort has been made to ensure that there are no errors in
this documentation, some errors may nevertheless have crept in. If you do
spot any typos or even more serious errors, and you can spare a few cycles
during lunch, please do bring the error to the attention of the Spring
team by <ulink url="http://jira.springframework.org/">raising an
issue</ulink>.</para>
</section>
<section id="new-in-3.0-new-tutorial">
<title>New articles and tutorials</title>
<para>
There are many excellent articles and tutorials that show how to get started with Spring 3 features.
Read them at the <ulink url="http://www.springsource.org/documentation">Spring Documentation</ulink> page.
</para>
<para id="new-in-3.0-samples">
The samples have been improved and updated to take advantage of the new features in Spring 3.
Additionally, the samples have been moved out of the source tree into a dedicated SVN
<ulink url="https://anonsvn.springframework.org/svn/spring-samples/">repository</ulink> available at:</para>
<para>
<literal>https://anonsvn.springframework.org/svn/spring-samples/</literal>
</para>
<para>As such, the samples are no longer distributed alongside Spring 3 and need to be downloaded separately from the repository mentioned above. However, this documentation
will continue to refer to some samples (in particular Petclinic) to illustrate various features.</para>
<note>For more information on Subversion (or in short SVN), see the project homepage at:
<literal>http://subversion.apache.org/</literal>
</note>
</section>
<section id="new-in-3.0-modules-build">
<title>New module organization and build system</title>
<para>The framework modules have been revised and are now managed
separately with one source-tree per module jar:</para>
<itemizedlist>
<listitem>
<para>org.springframework.aop</para>
</listitem>
<listitem>
<para>org.springframework.beans</para>
</listitem>
<listitem>
<para>org.springframework.context</para>
</listitem>
<listitem>
<para>org.springframework.context.support</para>
</listitem>
<listitem>
<para>org.springframework.expression</para>
</listitem>
<listitem>
<para>org.springframework.instrument</para>
</listitem>
<listitem>
<para>org.springframework.jdbc</para>
</listitem>
<listitem>
<para>org.springframework.jms</para>
</listitem>
<listitem>
<para>org.springframework.orm</para>
</listitem>
<listitem>
<para>org.springframework.oxm</para>
</listitem>
<listitem>
<para>org.springframework.test</para>
</listitem>
<listitem>
<para>org.springframework.transaction</para>
</listitem>
<listitem>
<para>org.springframework.web</para>
</listitem>
<listitem>
<para>org.springframework.web.portlet</para>
</listitem>
<listitem>
<para>org.springframework.web.servlet</para>
</listitem>
<listitem>
<para>org.springframework.web.struts</para>
</listitem>
</itemizedlist>
<sidebar id="new-in-3.0-intro-spring-jar">
<title>Note:</title>
<para>The spring.jar artifact that contained almost the entire framework
is no longer provided.</para>
</sidebar>
<para>We are now using a new Spring build system as known from Spring Web
Flow 2.0. This gives us:</para>
<itemizedlist>
<listitem>
<para>Ivy-based "Spring Build" system</para>
</listitem>
<listitem>
<para>consistent deployment procedure</para>
</listitem>
<listitem>
<para>consistent dependency management</para>
</listitem>
<listitem>
<para>consistent generation of OSGi manifests</para>
</listitem>
</itemizedlist>
</section>
<section id="new-in-3.0-features-overview">
<title>Overview of new features</title>
<para>This is a list of new features for Spring 3.0. We will cover these
features in more detail later in this section.</para>
<itemizedlist>
<listitem>
<para>Spring Expression Language</para>
</listitem>
<listitem>
<para>IoC enhancements/Java based bean metadata</para>
</listitem>
<listitem>
<para>General-purpose type conversion system and field formatting
system</para>
</listitem>
<listitem>
<para>Object to XML mapping functionality (OXM) moved from Spring Web
Services project</para>
</listitem>
<listitem>
<para>Comprehensive REST support</para>
</listitem>
<listitem>
<para>@MVC additions</para>
</listitem>
<listitem>
<para>Declarative model validation</para>
</listitem>
<listitem>
<para>Early support for Java EE 6</para>
</listitem>
<listitem>
<para>Embedded database support</para>
</listitem>
</itemizedlist>
<section id="new-feature-java5">
<title>Core APIs updated for Java 5</title>
<para>BeanFactory interface returns typed bean instances as far as
possible: <itemizedlist>
<listitem>
<para>T getBean(Class&lt;T&gt; requiredType)</para>
</listitem>
<listitem>
<para>T getBean(String name, Class&lt;T&gt; requiredType)</para>
</listitem>
<listitem>
<para>Map&lt;String, T&gt; getBeansOfType(Class&lt;T&gt;
type)</para>
</listitem>
</itemizedlist></para>
<para>Spring's TaskExecutor interface now extends
<classname>java.util.concurrent.Executor</classname>: <itemizedlist>
<listitem>
<para>extended AsyncTaskExecutor supports standard Callables with
Futures</para>
</listitem>
</itemizedlist></para>
<para>New Java 5 based converter API and SPI: <itemizedlist>
<listitem>
<para>stateless ConversionService and Converters</para>
</listitem>
<listitem>
<para>superseding standard JDK PropertyEditors</para>
</listitem>
</itemizedlist></para>
<para>Typed ApplicationListener&lt;E&gt;</para>
</section>
<section id="new-feature-el">
<title>Spring Expression Language</title>
<para>Spring introduces an expression language which is similar to
Unified EL in its syntax but offers significantly more features. The
expression language can be used when defining XML and Annotation based
bean definitions and also serves as the foundation for expression
language support across the Spring portfolio. Details of this new
functionality can be found in the chapter <link
linkend="expressions">Spring Expression Language (SpEL).</link></para>
<para>The Spring Expression Language was created to provide the Spring
community a single, well supported expression language that can be used
across all the products in the Spring portfolio. Its language features
are driven by the requirements of the projects in the Spring portfolio,
including tooling requirements for code completion support within the
Eclipse based <ulink url="http://www.springsource.com/products/sts">SpringSource
Tool Suite</ulink>.</para>
<para>The following is an example of how the Expression Language can be
used to configure some properties of a database setup <programlisting
language="xml">&lt;bean class="mycompany.RewardsTestDatabase"&gt;
&lt;property name="databaseName"
value="#{systemProperties.databaseName}"/&gt;
&lt;property name="keyGenerator"
value="#{strategyBean.databaseKeyGenerator}"/&gt;
&lt;/bean&gt;
</programlisting></para>
<para>This functionality is also available if you prefer to configure
your components using annotations: <programlisting language="java">@Repository
public class RewardsTestDatabase {
@Value("#{systemProperties.databaseName}")
public void setDatabaseName(String dbName) { … }
@Value("#{strategyBean.databaseKeyGenerator}")
public void setKeyGenerator(KeyGenerator kg) { … }
}
</programlisting></para>
</section>
<section id="new-feature-java-config">
<title>The Inversion of Control (IoC) container</title>
<section id="new-java-configuration">
<title>Java based bean metadata</title>
<para>Some core features from the <ulink
url="http://www.springsource.org/javaconfig">JavaConfig</ulink>
project have been added to the Spring Framework now. This means that
the following annotations are now directly supported: <itemizedlist>
<listitem>
<para>@Configuration</para>
</listitem>
<listitem>
<para>@Bean</para>
</listitem>
<listitem>
<para>@DependsOn</para>
</listitem>
<listitem>
<para>@Primary</para>
</listitem>
<listitem>
<para>@Lazy</para>
</listitem>
<listitem>
<para>@Import</para>
</listitem>
<listitem>
<para>@ImportResource</para>
</listitem>
<listitem>
<para>@Value</para>
</listitem>
</itemizedlist></para>
<para>Here is an example of a Java class providing basic configuration
using the new JavaConfig features: <programlisting language="java">package org.example.config;
@Configuration
public class AppConfig {
private @Value("#{jdbcProperties.url}") String jdbcUrl;
private @Value("#{jdbcProperties.username}") String username;
private @Value("#{jdbcProperties.password}") String password;
@Bean
public FooService fooService() {
return new FooServiceImpl(fooRepository());
}
@Bean
public FooRepository fooRepository() {
return new HibernateFooRepository(sessionFactory());
}
@Bean
public SessionFactory sessionFactory() {
// wire up a session factory
AnnotationSessionFactoryBean asFactoryBean =
new AnnotationSessionFactoryBean();
asFactoryBean.setDataSource(dataSource());
// additional config
return asFactoryBean.getObject();
}
@Bean
public DataSource dataSource() {
return new DriverManagerDataSource(jdbcUrl, username, password);
}
}
</programlisting> To get this to work you need to add the following component
scanning entry in your minimal application context XML file.
<programlisting language="xml">&lt;context:component-scan base-package="org.example.config"/&gt;
&lt;util:properties id="jdbcProperties" location="classpath:org/example/config/jdbc.properties"/&gt;
</programlisting>
Or you can bootstrap a <literal>@Configuration</literal> class directly using
<literal>AnnotationConfigApplicationContext</literal>:
<programlisting language="java">public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
FooService fooService = ctx.getBean(FooService.class);
fooService.doStuff();
}</programlisting>
See <xref linkend="beans-java-instantiating-container"/> for full information on
<literal>AnnotationConfigApplicationContext</literal>.</para>
</section>
<section>
<title>Defining bean metadata within components</title>
<para><literal>@Bean</literal> annotated methods are also supported
inside Spring components. They contribute a factory bean definition to
the container. See <link
linkend="beans-factorybeans-annotations">Defining bean metadata within
components</link> for more information</para>
</section>
</section>
<section id="new-feature-convert-and-format">
<title>General purpose type conversion system and field formatting
system</title>
<para>A general purpose <link linkend="core-convert">type conversion
system</link> has been introduced. The system is currently used by SpEL
for type conversion, and may also be used by a Spring Container and DataBinder when
binding bean property values.</para>
<para>In addition, a <link linkend="format">formatter</link> SPI
has been introduced for formatting field values. This SPI provides
a simpler and more robust alternative to JavaBean PropertyEditors for use in client
environments such as Spring MVC.</para>
</section>
<section id="new-feature-oxm">
<title>The Data Tier</title>
<para>Object to XML mapping functionality (OXM) from the Spring Web
Services project has been moved to the core Spring Framework now. The
functionality is found in the <literal>org.springframework.oxm</literal>
package. More information on the use of the <literal>OXM</literal>
module can be found in the <link linkend="oxm">Marshalling XML using O/X
Mappers</link> chapter.</para>
</section>
<section id="new-feature-rest">
<title>The Web Tier</title>
<para>The most exciting new feature for the Web Tier is the support for
building RESTful web services and web applications. There are also some
new annotations that can be used in any web application.</para>
<section>
<title>Comprehensive REST support</title>
<para>Server-side support for building RESTful applications has been
provided as an extension of the existing annotation driven MVC web
framework. Client-side support is provided by the
<classname>RestTemplate</classname> class in the spirit of other
template classes such as <classname>JdbcTemplate</classname> and
<classname>JmsTemplate</classname>. Both server and client side REST
functionality make use of
<interfacename>HttpConverter</interfacename>s to facilitate the
conversion between objects and their representation in HTTP requests
and responses.</para>
<para>The <classname>MarshallingHttpMessageConverter</classname> uses
the <emphasis>Object to XML mapping</emphasis> functionality mentioned
earlier.</para>
<para>Refer to the sections on <link linkend="mvc">MVC</link> and <link
linkend="rest-resttemplate">the RestTemplate</link> for more
information.</para>
</section>
<section>
<title>@MVC additions</title>
<para>A <literal>mvc</literal> namespace has been introduced that greatly simplifies Spring MVC configuration.</para>
<para>Additional annotations such as
<classname>@CookieValue</classname> and
<classname>@RequestHeaders</classname> have been added. See <link
linkend="mvc-ann-cookievalue">Mapping cookie values with the
@CookieValue annotation</link> and <link
linkend="mvc-ann-requestheader">Mapping request header attributes with
the @RequestHeader annotation</link> for more information.</para>
</section>
</section>
<section id="new-feature-validation">
<title>Declarative model validation</title>
<para>Several <link linkend="validation-beanvalidation">validation enhancements</link>,
including JSR 303 support that uses Hibernate Validator as the default provider.</para>
</section>
<section id="new-feature-jee-6">
<title>Early support for Java EE 6</title>
<para>We provide support for asynchronous method invocations through the
use of the new @Async annotation (or EJB 3.1's @Asynchronous
annotation).</para>
<para>JSR 303, JSF 2.0, JPA 2.0, etc</para>
</section>
<section id="new-feature-embedded-databases">
<title>Support for embedded databases</title>
<para>Convenient support for <link
linkend="jdbc-embedded-database-support">embedded Java database
engines</link>, including HSQL, H2, and Derby, is now provided.</para>
</section>
</section>
</chapter>

View File

@@ -0,0 +1,508 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="new-in-3.1">
<title>New Features and Enhancements in Spring 3.1</title>
<para>Building on the support introduced in Spring 3.0, Spring 3.1 is
currently under development, and at the time of this writing Spring 3.1 RC1
is being prepared for release.</para>
<section id="new-in-3.1-features-overview">
<title>Overview of new features</title>
<para>This is a list of new features for Spring 3.1. Most features do not
yet have dedicated reference documentation but do have Javadoc. In such
cases, fully-qualified class names are given.</para>
<section>
<title>Cache Abstraction</title>
<itemizedlist>
<listitem>
<para><xref linkend="cache" /></para>
</listitem>
<listitem>
<para><ulink
url="http://blog.springsource.com/2011/02/23/spring-3-1-m1-caching/">
Cache Abstraction</ulink> (SpringSource team blog)</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Bean Definition Profiles</title>
<itemizedlist>
<listitem>
<para><ulink
url="http://blog.springsource.com/2011/02/11/spring-framework-3-1-m1-released/">
XML profiles</ulink> (SpringSource Team Blog)</para>
</listitem>
<listitem>
<para><ulink
url="http://blog.springsource.com/2011/02/14/spring-3-1-m1-introducing-profile/">
Introducing @Profile</ulink> (SpringSource Team Blog)</para>
</listitem>
<listitem>
<para>See org.springframework.context.annotation.Configuration
Javadoc</para>
</listitem>
<listitem>
<para>See org.springframework.context.annotation.Profile
Javadoc</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Environment Abstraction</title>
<itemizedlist>
<listitem>
<para><ulink
url="http://blog.springsource.com/2011/02/11/spring-framework-3-1-m1-released/">
Environment Abstraction</ulink> (SpringSource Team Blog)</para>
</listitem>
<listitem>
<para>See org.springframework.core.env.Environment Javadoc</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>PropertySource Abstraction</title>
<itemizedlist>
<listitem>
<para><ulink
url="http://blog.springsource.com/2011/02/15/spring-3-1-m1-unified-property-management/">
Unified Property Management</ulink> (SpringSource Team Blog)</para>
</listitem>
<listitem>
<para>See org.springframework.core.env.Environment Javadoc</para>
</listitem>
<listitem>
<para>See org.springframework.core.env.PropertySource Javadoc</para>
</listitem>
<listitem>
<para>See org.springframework.context.annotation.PropertySource
Javadoc</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Code equivalents for Spring's XML namespaces</title>
<para>Code-based equivalents to popular Spring XML namespace elements
&lt;context:component-scan/&gt;, &lt;tx:annotation-driven/&gt;
and &lt;mvc:annotation-driven&gt; have been developed, most in the
form of <interfacename>@Enable</interfacename> annotations. These are
designed for use in conjunction with Spring's
<interfacename>@Configuration</interfacename> classes, which were
introduced in Spring 3.0.</para>
<itemizedlist>
<listitem>
<para>See org.springframework.context.annotation.Configuration
Javadoc</para>
</listitem>
<listitem>
<para>See org.springframework.context.annotation.ComponentScan
Javadoc</para>
</listitem>
<listitem>
<para>See
org.springframework.transaction.annotation.EnableTransactionManagement
Javadoc</para>
</listitem>
<listitem>
<para>See
org.springframework.cache.annotation.EnableCaching Javadoc</para>
</listitem>
<listitem>
<para>See org.springframework.web.servlet.config.annotation.EnableWebMvc
Javadoc</para>
</listitem>
<listitem>
<para>See org.springframework.scheduling.annotation.EnableScheduling
Javadoc</para>
</listitem>
<listitem>
<para>See org.springframework.scheduling.annotation.EnableAsync
Javadoc</para>
</listitem>
<listitem>
<para>See
org.springframework.context.annotation.EnableAspectJAutoProxy
Javadoc</para>
</listitem>
<listitem>
<para>See
org.springframework.context.annotation.EnableLoadTimeWeaving
Javadoc</para>
</listitem>
<listitem>
<para>See
org.springframework.beans.factory.aspectj.EnableSpringConfigured
Javadoc</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Support for Hibernate 4.x</title>
<itemizedlist>
<listitem>
<para>See Javadoc for classes within the new
org.springframework.orm.hibernate4 package</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>TestContext framework support for @Configuration classes and bean
definition profiles</title>
<para>The <interfacename>@ContextConfiguration</interfacename>
annotation now supports supplying
<interfacename>@Configuration</interfacename> classes for configuring
the Spring <classname>TestContext</classname>. In addition, a new
<interfacename>@ActiveProfiles</interfacename> annotation has been
introduced to support declarative configuration of active bean
definition profiles in <interfacename>ApplicationContext</interfacename>
integration tests.</para>
<itemizedlist>
<listitem>
<para><ulink
url="http://blog.springsource.com/2011/06/21/spring-3-1-m2-testing-with-configuration-classes-and-profiles/">Spring
3.1 M2: Testing with @Configuration Classes and Profiles</ulink>
(SpringSource Team Blog)</para>
</listitem>
<listitem>
<para>See <xref linkend="testcontext-framework" /></para>
</listitem>
<listitem>
<para>See <xref linkend="testcontext-ctx-management-javaconfig" />
and
<interfacename>org.springframework.test.context.ContextConfiguration</interfacename>
Javadoc</para>
</listitem>
<listitem>
<para>See
<interfacename>org.springframework.test.context.ActiveProfiles</interfacename>
Javadoc</para>
</listitem>
<listitem>
<para>See
<interfacename>org.springframework.test.context.SmartContextLoader</interfacename>
Javadoc</para>
</listitem>
<listitem>
<para>See
<interfacename>org.springframework.test.context.support.DelegatingSmartContextLoader</interfacename>
Javadoc</para>
</listitem>
<listitem>
<para>See
<interfacename>org.springframework.test.context.support.AnnotationConfigContextLoader</interfacename>
Javadoc</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>c: namespace for more concise constructor injection</title>
<itemizedlist>
<listitem>
<para><xref linkend="beans-c-namespace" /></para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Support for injection against non-standard JavaBeans
setters</title>
<para>Prior to Spring 3.1, in order to inject against a property method
it had to conform strictly to JavaBeans property signature rules, namely
that any 'setter' method must be void-returning. It is now possible in
Spring XML to specify setter methods that return any object type. This
is useful when considering designing APIs for method-chaining, where
setter methods return a reference to 'this'.</para>
</section>
<section>
<title>Support for Servlet 3 code-based configuration of Servlet
Container</title>
<para>The new <interfacename>WebApplicationInitializer</interfacename>
builds atop Servlet 3.0's
<interfacename>ServletContainerInitializer</interfacename> support to
provide a programmatic alternative to the traditional web.xml.</para>
<itemizedlist>
<listitem>
<para>See org.springframework.web.WebApplicationInitializer
Javadoc</para>
</listitem>
<listitem>
<para><ulink url="http://bit.ly/lrDHja">Diff from Spring's
Greenhouse reference application</ulink> demonstrating migration
from web.xml to
<interfacename>WebApplicationInitializer</interfacename></para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Support for Servlet 3 MultipartResolver</title>
<itemizedlist>
<listitem>
<para>See
org.springframework.web.multipart.support.StandardServletMultipartResolver
Javadoc</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>JPA EntityManagerFactory bootstrapping without
persistence.xml</title>
<para>In standard JPA, persistence units get defined through
<literal>META-INF/persistence.xml</literal> files in specific jar files
which will in turn get searched for <literal>@Entity</literal> classes.
In many cases, persistence.xml does not contain more than a unit name
and relies on defaults and/or external setup for all other concerns
(such as the DataSource to use, etc). For that reason, Spring 3.1
provides an alternative:
<classname>LocalContainerEntityManagerFactoryBean</classname> accepts a
'packagesToScan' property, specifying base packages to scan for
<literal>@Entity</literal> classes. This is analogous to
<classname>AnnotationSessionFactoryBean</classname>'s property of the
same name for native Hibernate setup, and also to Spring's
component-scan feature for regular Spring beans. Effectively, this
allows for XML-free JPA setup at the mere expense of specifying a base
package for entity scanning: a particularly fine match for Spring
applications which rely on component scanning for Spring beans as well,
possibly even bootstrapped using a code-based Servlet 3.0
initializer.</para>
</section>
<section>
<title>New HandlerMethod-based Support Classes For Annotated Controller
Processing</title>
<para>Spring 3.1 introduces a new set of support classes for processing
requests with annotated controllers:</para>
<itemizedlist>
<listitem>
<para><classname>RequestMappingHandlerMapping</classname></para>
</listitem>
<listitem>
<para><classname>RequestMappingHandlerAdapter</classname></para>
</listitem>
<listitem>
<para><classname>ExceptionHandlerExceptionResolver</classname></para>
</listitem>
</itemizedlist>
<para>These classes are a replacement for the existing:</para>
<itemizedlist>
<listitem>
<para><classname>DefaultAnnotationHandlerMapping</classname></para>
</listitem>
<listitem>
<para><classname>AnnotationMethodHandlerAdapter</classname></para>
</listitem>
<listitem>
<para><classname>AnnotationMethodHandlerExceptionResolver</classname></para>
</listitem>
</itemizedlist>
<para>The new classes were developed in response to many requests to
make annotation controller support classes more customizable and open
for extension. Whereas previously you could configure a custom annotated
controller method argument resolver, with the new support classes you
can customize the processing for any supported method argument or return
value type.</para>
<itemizedlist>
<listitem>
<para>See
org.springframework.web.method.support.HandlerMethodArgumentResolver
Javadoc</para>
</listitem>
<listitem>
<para>See
org.springframework.web.method.support.HandlerMethodReturnValueHandler
Javadoc</para>
</listitem>
</itemizedlist>
<para>A second notable difference is the introduction of a
<classname>HandlerMethod</classname> abstraction to represent an
<interface>@RequestMapping</interface> method. This abstraction is used
throughout by the new support classes as the <literal>handler</literal>
instance. For example a <classname>HandlerInterceptor</classname> can
cast the <literal>handler</literal> from <classname>Object</classname>
to <classname>HandlerMethod</classname> and get access to the target
controller method, its annotations, etc.</para>
<para>The new classes are enabled by default by the MVC namespace and by
Java-based configuration via <interface>@EnableWebMvc</interface>. The
existing classes will continue to be available but use of the new
classes is recommended going forward.</para>
</section>
<section>
<title>"consumes" and "produces" conditions in
<interface>@RequestMapping</interface></title>
<para>Improved support for specifying media types consumed by a method
through the <literal>'Content-Type'</literal> header as well as for
producible types specified through the <literal>'Accept'</literal>
header. See <xref linkend="mvc-ann-requestmapping-consumes" /> and <xref
linkend="mvc-ann-requestmapping-produces" /></para>
</section>
<section>
<title>Flash Attributes and
<interfacename>RedirectAttributes</interfacename></title>
<para>Flash attributes can now be stored in a
<classname>FlashMap</classname> and saved in the HTTP session to survive
a redirect. For an overview of the general support for flash attributes
in Spring MVC see <xref linkend="mvc-flash-attributes" />.</para>
<para>In annotated controllers, an
<interfacename>@RequestMapping</interfacename> method can add flash
attributes by declaring a method argument of type
<interfacename>RedirectAttributes</interfacename>. This method argument
can now also be used to get precise control over the attributes used in
a redirect scenario. See <xref linkend="mvc-ann-redirect-attributes" />
for more details.</para>
</section>
<section>
<title>URI Template Variable Enhancements</title>
<para>URI template variables from the current request are used in more
places: <itemizedlist>
<listitem>
<para>URI template variables are used in addition to request
parameters when binding a request to
<interfacename>@ModelAttribute</interfacename> method
arguments.</para>
</listitem>
<listitem>
<para>@PathVariable method argument values are merged into the
model before rendering, except in views that generate content in
an automated fashion such as JSON serialization or XML
marshalling.</para>
</listitem>
<listitem>
<para>A redirect string can contain placeholders for URI variables
(e.g. <literal>"redirect:/blog/{year}/{month}"</literal>). When
expanding the placeholders, URI template variables from the
current request are automatically considered.</para>
</listitem>
<listitem>
<para>An <interfacename>@ModelAttribute</interfacename> method
argument can be instantiated from a URI template variable provided
there is a registered Converter or PropertyEditor to convert from
a String to the target object type.</para>
</listitem>
</itemizedlist></para>
</section>
<section>
<title><interfacename>@Valid</interfacename> On
<interface>@RequestBody</interface> Controller Method Arguments</title>
<para>An <interface>@RequestBody</interface> method argument can be
annotated with <interface>@Valid</interface> to invoke automatic
validation similar to the support for
<interface>@ModelAttribute</interface> method arguments. A resulting
<classname>MethodArgumentNotValidException</classname> is handled in the
<classname>DefaultHandlerExceptionResolver</classname> and results in a
<literal>400</literal> response code.</para>
</section>
<section>
<title><interfacename>@RequestPart</interfacename> Annotation On
Controller Method Arguments</title>
<para>This new annotation provides access to the content of a
"multipart/form-data" request part. See <xref
linkend="mvc-multipart-forms-non-browsers" /> and <xref
linkend="mvc-multipart" />.</para>
</section>
<section>
<title><classname>UriComponentsBuilder</classname> and <classname>UriComponents</classname></title>
<para>A new <classname>UriComponents</classname> class has been added,
which is an immutable container of URI components providing
access to all contained URI components.
A nenw <classname>UriComponentsBuilder</classname> class is also
provided to help create <classname>UriComponents</classname> instances.
Together the two classes give fine-grained control over all
aspects of preparing a URI including construction, expansion
from URI template variables, and encoding.</para>
<para>In most cases the new classes can be used as a more flexible
alternative to the existing <classname>UriTemplate</classname>
especially since <classname>UriTemplate</classname> relies on those
same classes internally.
</para>
<para>A <classname>ServletUriComponentsBuilder</classname> sub-class
provides static factory methods to copy information from
a Servlet request. See <xref linkend="mvc-construct-encode-uri"/>.
</para>
</section>
</section>
</chapter>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,962 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="overview">
<title>Introduction to Spring Framework</title>
<para>Spring Framework is a Java platform that provides comprehensive
infrastructure support for developing Java applications. Spring handles the
infrastructure so you can focus on your application.<!--First text mention should be *Spring Framework* not just *Spring*. I revised next sentence because *plumbing* is idiomatic and --><!--*the domain problem* is an unclear reference. Isn't the point that Spring takes care of *under the covers* so you can focus on app? TR: OK.--></para>
<para>Spring enables you to build applications from “plain old Java objects”
(POJOs) and to apply enterprise services non-invasively to POJOs. This
capability applies to the Java SE programming model and to full and partial
Java EE.</para>
<para>Examples of how you, as an application developer, can use the Spring
platform advantage:<!--In each of the examples, clarify what you mean by *the implementer* (identify it, or is it a person?). ALSO in each sentence replace--><!--*dealing with* APIs with what you mean: what does not have to be done in regard to APIs? IMPORTANT, because this discusses advantage--><!--of product. TR: REVISED, PLS REVIEW. I changed *implementer* to *application developer* and put it upfront rather than repeat it.--></para>
<itemizedlist>
<listitem>
<para>Make a Java method execute in a database transaction without
having to deal with transaction APIs.</para>
</listitem>
<listitem>
<para>Make a local Java method a remote procedure without having to deal
with remote APIs.</para>
</listitem>
<listitem>
<para>Make a local Java method a management operation without having to
deal with JMX APIs.</para>
</listitem>
<listitem>
<para>Make a local Java method a message handler without having to deal
with JMS APIs.</para>
</listitem>
</itemizedlist>
<section id="overview-dependency-injection">
<title>Dependency Injection and Inversion of Control</title>
<sidebar id="background-ioc">
<title>Background</title>
<para><quote><emphasis>The question is, what aspect of control are
[they] inverting?</emphasis></quote> Martin Fowler posed this question
about Inversion of Control (IoC) on his site in 2004. Fowler suggested
renaming the principle to make it more self-explanatory and came up with
<firstterm>Dependency Injection</firstterm>.</para>
<para>For insight into IoC and DI, refer to Fowler's article at <ulink
url="http://martinfowler.com/articles/injection.html">http://martinfowler.com/articles/injection.html</ulink>.</para>
</sidebar>
<para>Java applications -- a loose term that runs the gamut from
constrained applets to n-tier server-side enterprise applications --
typically consist of objects that collaborate to form the application
proper. Thus the objects in an application have
<emphasis>dependencies</emphasis> on each other.</para>
<para>Although the Java platform provides a wealth of application
development functionality, it lacks the means to organize the basic
building blocks into a coherent whole, leaving that task to architects and
developers. True, you can use design patterns such as
<firstterm>Factory</firstterm>, <firstterm>Abstract Factory</firstterm>,
<firstterm>Builder</firstterm>, <firstterm>Decorator</firstterm>, and
<firstterm>Service Locator</firstterm> to compose the various classes and
object instances that make up an application. However, these patterns are
simply that: best practices given a name, with a description of what the
pattern does, where to apply it, the problems it addresses, and so forth.
Patterns are formalized best practices that <emphasis>you must implement
yourself</emphasis> in your application.</para>
<para>The Spring Framework <emphasis>Inversion of Control</emphasis> (IoC)
component addresses this concern by providing a formalized means of
composing disparate components into a fully working application ready for
use. <!--Preceding sentence sounds like a description of what patterns do (and Spring uses patterns). Distinguish from patterns.-->The
Spring Framework codifies formalized design patterns as first-class
objects that you can integrate into your own application(s). <!--Preceding sentence suggests that you already have the application and *then* you integrate design patterns into it. Again, I--><!--don't see a major distinction here from use of patterns (as described in earlier paragraph) and use of IoC component to build apps.
TR: This section doesn't read well and I think we should try to rewrite it.-->Numerous
organizations and institutions use the Spring Framework in this manner to
engineer robust, <emphasis>maintainable</emphasis> applications.</para>
</section>
<section id="overview-modules">
<title>Modules</title>
<para>The Spring Framework consists of features organized into about 20
modules. These modules are grouped into Core Container, Data
Access/Integration, Web, AOP (Aspect Oriented Programming),
Instrumentation, and Test, as shown in the following diagram.</para>
<para><mediaobject>
<imageobject role="fo">
<imagedata align="left" fileref="images/spring-overview.png"
format="PNG" />
</imageobject>
<imageobject role="html">
<imagedata align="center" fileref="images/spring-overview.png"
format="PNG" />
</imageobject>
<caption><para>Overview of the Spring Framework</para></caption>
</mediaobject></para>
<section>
<title>Core Container</title>
<para>The <link linkend="beans-introduction"><emphasis>Core
Container</emphasis></link> consists of the Core, Beans, Context, and
Expression Language modules.</para>
<para>The <link linkend="beans-introduction"><emphasis>Core and
Beans</emphasis></link> modules provide the fundamental parts of the
framework, including the IoC and Dependency Injection features. The
<classname>BeanFactory</classname> is a sophisticated implementation of
the factory pattern. It removes the need for programmatic singletons and
allows you to decouple the configuration and specification of
dependencies from your actual program logic.</para>
<para>The <link
linkend="context-introduction"><emphasis>Context</emphasis></link>
module builds on the solid base provided by the <link
linkend="beans-introduction"><emphasis>Core and Beans</emphasis></link>
modules: it is a means to access objects in a framework-style manner
that is similar to a JNDI registry. The Context module inherits its
features from the Beans module and adds support for internationalization
(using, for example, resource bundles), event-propagation,
resource-loading, and the transparent creation of contexts by, for
example, a servlet container. The Context module also supports Java EE
features such as EJB, JMX ,and basic remoting. The
<classname>ApplicationContext</classname> interface is the focal point
of the Context module.</para>
<para>The <link linkend="expressions"><emphasis>Expression
Language</emphasis></link> module <!--Provide link as you do with others TR: FIXED.-->provides
a powerful expression language for querying and manipulating an object
graph at runtime. It is an extension of the unified expression language
(unified EL) as specified in the JSP 2.1 specification. The language
supports setting and getting property values, property assignment,
method invocation, accessing the context of arrays, collections and
indexers, logical and arithmetic operators, named variables, and
retrieval of objects by name from Spring's IoC container. It also
supports list projection and selection as well as common list
aggregations.</para>
</section>
<section>
<title>Data Access/Integration</title>
<para>The <emphasis>Data Access/Integration</emphasis> layer consists of
the JDBC, ORM, OXM, JMS and Transaction modules.</para>
<para>The <link linkend="jdbc-introduction">JDBC</link> module provides
a JDBC-abstraction layer that removes the need to do tedious JDBC coding
and parsing of database-vendor specific error codes.</para>
<para>The <link
linkend="orm-introduction"><emphasis>ORM</emphasis></link> module
provides integration layers for popular object-relational mapping APIs,
including <link linkend="orm-jpa">JPA</link>, <link
linkend="orm-jdo">JDO</link>, <link
linkend="orm-hibernate">Hibernate</link>, and <link
linkend="orm-ibatis">iBatis</link>. Using the ORM package you can use
all of these O/R-mapping frameworks in combination with all of the other
features Spring offers, such as the simple declarative transaction
management feature mentioned previously.</para>
<para>The <link linkend="oxm">OXM</link> module provides an abstraction
layer that supports Object/XML mapping implementations for JAXB, Castor,
XMLBeans, JiBX and XStream.</para>
<para>The Java Messaging Service (<link linkend="jms">JMS</link>) module
contains features for producing and consuming messages.</para>
<para>The <link linkend="transaction">Transaction</link> module supports
programmatic and declarative transaction management for classes that
implement special interfaces and for <emphasis>all your POJOs (plain old
Java objects)</emphasis>.</para>
</section>
<section>
<title>Web</title>
<para>The <emphasis>Web</emphasis> layer consists of the Web,
Web-Servlet, Web-Struts, and Web-Portlet modules.</para>
<para>Spring's <emphasis>Web</emphasis> module provides basic
web-oriented integration features such as multipart file-upload
functionality and the initialization of the IoC container using servlet
listeners and a web-oriented application context. It also contains the
web-related parts of Spring's remoting support.</para>
<para>The <emphasis>Web-Servlet</emphasis> module contains Spring's
model-view-controller (<link
linkend="mvc-introduction"><emphasis>MVC</emphasis></link>)
implementation for web applications. Spring's MVC framework provides a
clean separation between domain model code and web forms, and integrates
with all the other features of the Spring Framework.<!--MVC allows you to use *all other features*? (Or just all other features in Web layer?) How do you mean? Does this need elaboration?
It sounds important.--><!--TR: REVISED, PLS REVIEW.--></para>
<para>The <emphasis>Web-Struts</emphasis> module contains the support
classes for integrating a classic Struts web tier within a Spring
application. Note that this support is now deprecated as of Spring 3.0.
Consider migrating your application to Struts 2.0 and its Spring
integration or to a Spring MVC solution.</para>
<para>The <emphasis>Web-Portlet</emphasis> module provides the MVC
implementation to be used in a portlet environment and mirrors the
functionality of Web-Servlet module.<!--mirrors it in what way?--><!--TR: REVISED, PLS REVIEW. The functionality is mirrored - one for Servlets and the other for Portlets--></para>
</section>
<section>
<title>AOP and Instrumentation</title>
<para>Spring's <link
linkend="aop-introduction"><emphasis>AOP</emphasis></link> module
provides an <emphasis>AOP Alliance</emphasis>-compliant aspect-oriented
programming implementation allowing you to define, for example,
method-interceptors and pointcuts to cleanly decouple code that
implements functionality that should be separated. Using source-level
metadata functionality, you can also incorporate behavioral information
into your code, in a manner similar to that of .NET attributes.</para>
<para>The separate <emphasis>Aspects</emphasis> module provides
integration with AspectJ.<!--Aspects module not shown in diagram, add it to that. Also, why is this line under AOP and Instrumentation if it's separate?
TR: OK. Added to diagram.--></para>
<para>The <emphasis>Instrumentation</emphasis> module provides class
instrumentation support and classloader implementations to be used in
certain application servers.</para>
</section>
<section>
<title>Test</title>
<para>The <emphasis>Test</emphasis> module supports the testing of
Spring components with JUnit or TestNG. It provides consistent loading
of Spring ApplicationContexts and caching of those contexts. It also
provides mock objects that you can use to test your code in
isolation.</para>
</section>
</section>
<section id="overview-usagescenarios">
<title>Usage scenarios</title>
<para>The building blocks described previously make Spring a logical
choice in many scenarios, from applets to full-fledged enterprise
applications that use Spring's transaction management functionality and
web framework integration.</para>
<para><mediaobject>
<imageobject role="fo">
<imagedata align="center" fileref="images/overview-full.png"
format="PNG" />
</imageobject>
<imageobject role="html">
<imagedata align="center" fileref="images/overview-full.png"
format="PNG" />
</imageobject>
<caption><para>Typical full-fledged Spring web
application</para></caption>
</mediaobject></para>
<para>Spring's <link linkend="transaction-declarative">declarative
transaction management features</link> make the web application fully
transactional, just as it would be if you used EJB container-managed
transactions. All your custom business logic can be implemented with
simple POJOs and managed by Spring's IoC container. Additional services
include support for sending email and validation that is independent of
the web layer, which lets you choose where to execute validation rules.
Spring's ORM support is integrated with JPA, Hibernate, JDO and iBatis;
for example, when using Hibernate, you can continue to use your existing
mapping files and standard Hibernate
<interfacename>SessionFactory</interfacename> configuration. Form
controllers seamlessly integrate the web-layer with the domain model,
removing the need for <classname>ActionForms</classname> or other classes
that transform HTTP parameters to values for your domain model.</para>
<para><mediaobject>
<imageobject role="fo">
<imagedata align="center"
fileref="images/overview-thirdparty-web.png" format="PNG" />
</imageobject>
<imageobject role="html">
<imagedata align="center"
fileref="images/overview-thirdparty-web.png" format="PNG" />
</imageobject>
<caption><para>Spring middle-tier using a third-party web
framework</para></caption>
</mediaobject></para>
<para>Sometimes circumstances do not allow you to completely switch to a
different framework. The Spring Framework does <emphasis>not</emphasis>
force you to use everything within it; it is not an
<emphasis>all-or-nothing</emphasis> solution. Existing front-ends built
with WebWork, Struts, Tapestry, or other UI frameworks can be integrated
with a Spring-based middle-tier, which allows you to use Spring
transaction features. You simply need to wire up your business logic using
an <classname>ApplicationContext</classname> and use a
<classname>WebApplicationContext </classname>to integrate your web
layer.</para>
<para><mediaobject>
<imageobject role="fo">
<imagedata align="center" fileref="images/overview-remoting.png"
format="PNG" />
</imageobject>
<imageobject role="html">
<imagedata align="center" fileref="images/overview-remoting.png"
format="PNG" />
</imageobject>
<caption><para>Remoting usage scenario</para></caption>
</mediaobject></para>
<para>When you need to access existing code through web services, you can
use Spring's <literal>Hessian-</literal>, <literal>Burlap-</literal>,
<literal>Rmi-</literal> or <classname>JaxRpcProxyFactory</classname>
classes. Enabling remote access to existing applications is not
difficult.</para>
<para><mediaobject>
<imageobject role="fo">
<imagedata align="center" fileref="images/overview-ejb.png"
format="PNG" />
</imageobject>
<imageobject role="html">
<imagedata align="center" fileref="images/overview-ejb.png"
format="PNG" />
</imageobject>
<caption><para>EJBs - Wrapping existing POJOs</para></caption>
</mediaobject></para>
<para>The Spring Framework also provides an <link linkend="ejb">access and
abstraction layer</link> for Enterprise JavaBeans, enabling you to reuse
your existing POJOs and wrap them in stateless session beans for use in
scalable, fail-safe web applications that might need declarative
security.</para>
<section id="dependency-management">
<title>Dependency Management and Naming Conventions</title>
<para>Dependency management and dependency injection are different
things. To get those nice features of Spring into your application (like
dependency injection) you need to assemble all the libraries needed (jar
files) and get them onto your classpath at runtime, and possibly at
compile time. These dependencies are not virtual components that are
injected, but physical resources in a file system (typically). The
process of dependency management involves locating those resources,
storing them and adding them to classpaths. Dependencies can be direct
(e.g. my application depends on Spring at runtime), or indirect (e.g. my
application depends on <code>commons-dbcp</code> which depends on
<code>commons-pool</code>). The indirect dependencies are also known as
"transitive" and it is those dependencies that are hardest to identify
and manage.</para>
<para>If you are going to use Spring you need to get a copy of the jar
libraries that comprise the pieces of Spring that you need. To make this
easier Spring is packaged as a set of modules that separate the
dependencies as much as possible, so for example if you don't want to
write a web application you don't need the spring-web modules. To refer
to Spring library modules in this guide we use a shorthand naming
convention <code>spring-*</code> or <code>spring-*.jar,</code> where "*"
represents the short name for the module (e.g. <code>spring-core</code>,
<code>spring-webmvc</code>, <code>spring-jms</code>, etc.). The actual
jar file name that you use may be in this form (see below) or it may
not, and normally it also has a version number in the file name (e.g.
<code>spring-core-3.0.0.RELEASE.jar</code>).</para>
<para>In general, Spring publishes its artifacts to four different
places:<itemizedlist>
<listitem>
<para>On the community download site <ulink
url="http://www.springsource.org/downloads/community">http://www.springsource.org/downloads/community</ulink>.
Here you find all the Spring jars bundled together into a zip file
for easy download. The names of the jars here since version 3.0
are in the form
<code>org.springframework.*-&lt;version&gt;.jar</code>.</para>
</listitem>
<listitem>
<para>Maven Central, which is the default repository that Maven
queries, and does not require any special configuration to use.
Many of the common libraries that Spring depends on also are
available from Maven Central and a large section of the Spring
community uses Maven for dependency management, so this is
convenient for them. The names of the jars here are in the form
<code>spring-*-&lt;version&gt;.jar</code> and the Maven groupId is
<code>org.springframework</code>.</para>
</listitem>
<listitem>
<para>The Enterprise Bundle Repository (EBR), which is run by
SpringSource and also hosts all the libraries that integrate with
Spring. Both Maven and Ivy repositories are available here for all
Spring jars and their dependencies, plus a large number of other
common libraries that people use in applications with Spring. Both
full releases and also milestones and development snapshots are
deployed here. The names of the jar files are in the same form as
the community download
(<code>org.springframework.*-&lt;version&gt;.jar</code>), and the
dependencies are also in this "long" form, with external libraries
(not from SpringSource) having the prefix
<code>com.springsource</code>. See the <ulink security=""
url="http://www.springsource.com/repository/app/faq">FAQ</ulink>
for more information.</para>
</listitem>
<listitem>
<para>In a public Maven repository hosted on Amazon S3 for
development snapshots and milestone releases (a copy of the final
releases is also held here). The jar file names are in the same
form as Maven Central, so this is a useful place to get
development versions of Spring to use with other libraries depoyed
in Maven Central.</para>
</listitem>
</itemizedlist></para>
<para>So the first thing you need to decide is how to manage your
dependencies: most people use an automated system like Maven or Ivy, but
you can also do it manually by downloading all the jars yourself. When
obtaining Spring with Maven or Ivy you have then to decide which place
you'll get it from. In general, if you care about OSGi, use the EBR,
since it houses OSGi compatible artifacts for all of Spring's
dependencies, such as Hibernate and Freemarker. If OSGi does not matter
to you, either place works, though there are some pros and cons between
them. In general, pick one place or the other for your project; do not
mix them. This is particularly important since EBR artifacts necessarily
use a different naming convention than Maven Central artifacts.</para>
<para><table>
<title>Comparison of Maven Central and SpringSource EBR
Repositories</title>
<tgroup cols="3">
<thead>
<row>
<entry>Feature</entry>
<entry>Maven Central</entry>
<entry>EBR</entry>
</row>
</thead>
<tbody>
<row>
<entry>OSGi Compatible</entry>
<entry>Not explicit</entry>
<entry>Yes</entry>
</row>
<row>
<entry>Number of Artifacts</entry>
<entry>Tens of thousands; all kinds</entry>
<entry>Hundreds; those that Spring integrates with</entry>
</row>
<row>
<entry>Consistent Naming Conventions</entry>
<entry>No</entry>
<entry>Yes</entry>
</row>
<row>
<entry>Naming Convention: GroupId</entry>
<entry>Varies. Newer artifacts often use domain name, e.g.
org.slf4j. Older ones often just use the artifact name, e.g.
log4j.</entry>
<entry>Domain name of origin or main package root, e.g.
org.springframework</entry>
</row>
<row>
<entry>Naming Convention: ArtifactId</entry>
<entry>Varies. Generally the project or module name, using a
hyphen "-" separator, e.g. spring-core, logj4.</entry>
<entry>Bundle Symbolic Name, derived from the main package
root, e.g. org.springframework.beans. If the jar had to be
patched to ensure OSGi compliance then com.springsource is
appended, e.g. com.springsource.org.apache.log4j</entry>
</row>
<row>
<entry>Naming Convention: Version</entry>
<entry>Varies. Many new artifacts use m.m.m or m.m.m.X (with
m=digit, X=text). Older ones use m.m. Some neither. Ordering
is defined but not often relied on, so not strictly
reliable.</entry>
<entry>OSGi version number m.m.m.X, e.g. 3.0.0.RC3. The text
qualifier imposes alphabetic ordering on versions with the
same numeric values.</entry>
</row>
<row>
<entry>Publishing</entry>
<entry>Usually automatic via rsync or source control updates.
Project authors can upload individual jars to JIRA.</entry>
<entry>Manual (JIRA processed by SpringSource)</entry>
</row>
<row>
<entry>Quality Assurance</entry>
<entry>By policy. Accuracy is responsibility of
authors.</entry>
<entry>Extensive for OSGi manifest, Maven POM and Ivy
metadata. QA performed by Spring team.</entry>
</row>
<row>
<entry>Hosting</entry>
<entry>Contegix. Funded by Sonatype with several
mirrors.</entry>
<entry>S3 funded by SpringSource.</entry>
</row>
<row>
<entry>Search Utilities</entry>
<entry>Various</entry>
<entry><ulink
url="http://www.springsource.com/repository">http://www.springsource.com/repository</ulink></entry>
</row>
<row>
<entry>Integration with SpringSource Tools</entry>
<entry>Integration through STS with Maven dependency
management</entry>
<entry>Extensive integration through STS with Maven, Roo,
CloudFoundry</entry>
</row>
</tbody>
</tgroup>
</table></para>
<section>
<title>Spring Dependencies and Depending on Spring</title>
<para>Although Spring provides integration and support for a huge
range of enterprise and other external tools, it intentionally keeps
its mandatory dependencies to an absolute minimum: you shouldn't have
to locate and download (even automatically) a large number of jar
libraries in order to use Spring for simple use cases. For basic
dependency injection there is only one mandatory external dependency,
and that is for logging (see below for a more detailed description of
logging options).</para>
<para>Next we outline the basic steps needed to configure an
application that depends on Spring, first with Maven and then with
Ivy. In all cases, if anything is unclear, refer to the documentation
of your dependency management system, or look at some sample code -
Spring itself uses Ivy to manage dependencies when it is building, and
our samples mostly use Maven.</para>
</section>
<section>
<title>Maven Dependency Management</title>
<para>If you are using Maven for dependency management you don't even
need to supply the logging dependency explicitly. For example, to
create an application context and use dependency injection to
configure an application, your Maven dependencies will look like
this:</para>
<para><programlisting>&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework&lt;/groupId&gt;
&lt;artifactId&gt;spring-context&lt;/artifactId&gt;
&lt;version&gt;3.0.0.RELEASE&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt; </programlisting></para>
<para>That's it. Note the scope can be declared as runtime if you
don't need to compile against Spring APIs, which is typically the case
for basic dependency injection use cases.</para>
<para>We used the Maven Central naming conventions in the example
above, so that works with Maven Central or the SpringSource S3 Maven
repository. To use the S3 Maven repository (e.g. for milestones or
developer snaphots), you need to specify the repository location in
your Maven configuration. For full releases:</para>
<programlisting>&lt;repositories&gt;
&lt;repository&gt;
&lt;id&gt;com.springsource.repository.maven.release&lt;/id&gt;
&lt;url&gt;http://maven.springframework.org/release/&lt;/url&gt;
&lt;snapshots&gt;&lt;enabled&gt;false&lt;/enabled&gt;&lt;/snapshots&gt;
&lt;/repository&gt;
&lt;/repositories&gt;</programlisting>
<para>For milestones:</para>
<programlisting>&lt;repositories&gt;
&lt;repository&gt;
&lt;id&gt;com.springsource.repository.maven.milestone&lt;/id&gt;
&lt;url&gt;http://maven.springframework.org/milestone/&lt;/url&gt;
&lt;snapshots&gt;&lt;enabled&gt;false&lt;/enabled&gt;&lt;/snapshots&gt;
&lt;/repository&gt;
&lt;/repositories&gt;</programlisting>
<para>And for snapshots:</para>
<programlisting>&lt;repositories&gt;
&lt;repository&gt;
&lt;id&gt;com.springsource.repository.maven.snapshot&lt;/id&gt;
&lt;url&gt;http://maven.springframework.org/snapshot/&lt;/url&gt;
&lt;snapshots&gt;&lt;enabled&gt;true&lt;/enabled&gt;&lt;/snapshots&gt;
&lt;/repository&gt;
&lt;/repositories&gt;</programlisting>
<para>To use the SpringSource EBR you would need to use a different
naming convention for the dependencies. The names are usually easy to
guess, e.g. in this case it is:</para>
<programlisting>&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework&lt;/groupId&gt;
&lt;artifactId&gt;org.springframework.context&lt;/artifactId&gt;
&lt;version&gt;3.0.0.RELEASE&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt;</programlisting>
<para>You also need to declare the location of the repository
explicitly (only the URL is important):</para>
<programlisting>&lt;repositories&gt;
&lt;repository&gt;
&lt;id&gt;com.springsource.repository.bundles.release&lt;/id&gt;
&lt;url&gt;http://repository.springsource.com/maven/bundles/release/&lt;/url&gt;
&lt;/repository&gt;
&lt;/repositories&gt;</programlisting>
<para>If you are managing your dependencies by hand, the URL in the
repository declaration above is not browseable, but there is a user
interface at <ulink
url="http://www.springsource.com/repository">http://www.springsource.com/repository</ulink>
that can be used to search for and download dependencies. It also has
handy snippets of Maven and Ivy configuration that you can copy and
paste if you are using those tools.</para>
</section>
<section>
<title>Ivy Dependency Management</title>
<para>If you prefer to use <ulink
url="http://ant.apache.org/ivy">Ivy</ulink> to manage dependencies
then there are similar names and configuration options. </para>
<para>To configure Ivy to point to the SpringSource EBR add the
following resolvers to your
<filename>ivysettings.xml</filename>:</para>
<programlisting>&lt;resolvers&gt;
&lt;url name="com.springsource.repository.bundles.release"&gt;
&lt;ivy pattern="http://repository.springsource.com/ivy/bundles/release/
[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /&gt;
&lt;artifact pattern="http://repository.springsource.com/ivy/bundles/release/
[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /&gt;
&lt;/url&gt;
&lt;url name="com.springsource.repository.bundles.external"&gt;
&lt;ivy pattern="http://repository.springsource.com/ivy/bundles/external/
[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /&gt;
&lt;artifact pattern="http://repository.springsource.com/ivy/bundles/external/
[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /&gt;
&lt;/url&gt;
&lt;/resolvers&gt;</programlisting>
<para>The XML above is not valid because the lines are too long - if
you copy-paste then remove the extra line endings in the middle of the
url patterns.</para>
<para>Once Ivy is configured to look in the EBR adding a dependency is
easy. Simply pull up the details page for the bundle in question in
the repository browser and you'll find an Ivy snippet ready for you to
include in your dependencies section. For example (in
<filename>ivy.xml</filename>): </para>
<programlisting>&lt;dependency org="org.springframework"
name="org.springframework.core" rev="3.0.0.RELEASE" conf="compile-&gt;runtime"/&gt;</programlisting>
</section>
</section>
<section>
<title>Logging</title>
<para>Logging is a very important dependency for Spring because a) it is
the only mandatory external dependency, b) everyone likes to see some
output from the tools they are using, and c) Spring integrates with lots
of other tools all of which have also made a choice of logging
dependency. One of the goals of an application developer is often to
have unified logging configured in a central place for the whole
application, including all external components. This is more difficult
than it might have been since there are so many choices of logging
framework.</para>
<para>The mandatory logging dependency in Spring is the Jakarta Commons
Logging API (JCL). We compile against JCL and we also make JCL
<classname>Log</classname> objects visible for classes that extend the
Spring Framework. It's important to users that all versions of Spring
use the same logging library: migration is easy because backwards
compatibility is preserved even with applications that extend Spring.
The way we do this is to make one of the modules in Spring depend
explicitly on <code>commons-logging</code> (the canonical implementation
of JCL), and then make all the other modules depend on that at compile
time. If you are using Maven for example, and wondering where you picked
up the dependency on <code>commons-logging</code>, then it is from
Spring and specifically from the central module called
<code>spring-core</code>.</para>
<para>The nice thing about <code>commons-logging</code> is that you
don't need anything else to make your application work. It has a runtime
discovery algorithm that looks for other logging frameworks in well
known places on the classpath and uses one that it thinks is appropriate
(or you can tell it which one if you need to). If nothing else is
available you get pretty nice looking logs just from the JDK
(java.util.logging or JUL for short). You should find that your Spring
application works and logs happily to the console out of the box in most
situations, and that's important.</para>
<section>
<title>Not Using Commons Logging</title>
<para>Unfortunately, the runtime discovery algorithm in
<code>commons-logging</code>, while convenient for the end-user, is
problematic. If we could turn back the clock and start Spring now
as a new project it would use a different logging dependency. The
first choice would probably be the Simple Logging Facade for Java (<ulink
url="http://www.slf4j.org">SLF4J</ulink>), which is also used by a lot
of other tools that people use with Spring inside their
applications.</para>
<para>Switching off <code>commons-logging</code> is easy: just make
sure it isn't on the classpath at runtime. In Maven terms you exclude
the dependency, and because of the way that the Spring dependencies
are declared, you only have to do that once.</para>
<programlisting>&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework&lt;/groupId&gt;
&lt;artifactId&gt;spring-context&lt;/artifactId&gt;
&lt;version&gt;3.0.0.RELEASE&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;exclusions&gt;
&lt;exclusion&gt;
&lt;groupId&gt;commons-logging&lt;/groupId&gt;
&lt;artifactId&gt;commons-logging&lt;/artifactId&gt;
&lt;/exclusion&gt;
&lt;/exclusions&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt; </programlisting>
<para>Now this application is probably broken because there is no
implementation of the JCL API on the classpath, so to fix it a new one
has to be provided. In the next section we show you how to provide an
alternative implementation of JCL using SLF4J as an example.</para>
</section>
<section>
<title>Using SLF4J</title>
</section>
<para>SLF4J is a cleaner dependency and more efficient at runtime than
<code>commons-logging</code> because it uses compile-time bindings
instead of runtime discovery of the other logging frameworks it
integrates. This also means that you have to be more explicit about what
you want to happen at runtime, and declare it or configure it
accordingly. SLF4J provides bindings to many common logging frameworks,
so you can usually choose one that you already use, and bind to that for
configuration and management.</para>
<para>SLF4J provides bindings to many common logging frameworks,
including JCL, and it also does the reverse: bridges between other
logging frameworks and itself. So to use SLF4J with Spring you need to
replace the <code>commons-logging</code> dependency with the SLF4J-JCL
bridge. Once you have done that then logging calls from within Spring
will be translated into logging calls to the SLF4J API, so if other
libraries in your application use that API, then you have a single place
to configure and manage logging.</para>
<para>A common choice might be to bridge Spring to SLF4J, and then
provide explicit binding from SLF4J to Log4J. You need to supply 4
dependencies (and exclude the existing <code>commons-logging</code>):
the bridge, the SLF4J API, the binding to Log4J, and the Log4J
implementation itself. In Maven you would do that like this</para>
<programlisting>&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework&lt;/groupId&gt;
&lt;artifactId&gt;spring-context&lt;/artifactId&gt;
&lt;version&gt;3.0.0.RELEASE&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;exclusions&gt;
&lt;exclusion&gt;
&lt;groupId&gt;commons-logging&lt;/groupId&gt;
&lt;artifactId&gt;commons-logging&lt;/artifactId&gt;
&lt;/exclusion&gt;
&lt;/exclusions&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.slf4j&lt;/groupId&gt;
&lt;artifactId&gt;jcl-over-slf4j&lt;/artifactId&gt;
&lt;version&gt;1.5.8&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.slf4j&lt;/groupId&gt;
&lt;artifactId&gt;slf4j-api&lt;/artifactId&gt;
&lt;version&gt;1.5.8&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.slf4j&lt;/groupId&gt;
&lt;artifactId&gt;slf4j-log4j12&lt;/artifactId&gt;
&lt;version&gt;1.5.8&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;log4j&lt;/groupId&gt;
&lt;artifactId&gt;log4j&lt;/artifactId&gt;
&lt;version&gt;1.2.14&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt; </programlisting>
<para>That might seem like a lot of dependencies just to get some
logging. Well it is, but it <emphasis>is</emphasis> optional, and it
should behave better than the vanilla <code>commons-logging</code> with
respect to classloader issues, notably if you are in a strict container
like an OSGi platform. Allegedly there is also a performance benefit
because the bindings are at compile-time not runtime.</para>
<para>A more common choice amongst SLF4J users, which uses fewer steps
and generates fewer dependencies, is to bind directly to <ulink type=""
url="http://logback.qos.ch">Logback</ulink>. This removes the extra
binding step because Logback implements SLF4J directly, so you only need
to depend on two libaries not four (<code>jcl-over-slf4j</code> and
<code>logback</code>). If you do that you might also need to exlude the
slf4j-api dependency from other external dependencies (not Spring),
because you only want one version of that API on the classpath.</para>
<section>
<title>Using Log4J</title>
<para>Many people use <ulink
url="http://logging.apache.org/log4j">Log4j</ulink> as a logging
framework for configuration and management purposes. It's efficient
and well-established, and in fact it's what we use at runtime when we
build and test Spring. Spring also provides some utilities for
configuring and initializing Log4j, so it has an optional compile-time
dependency on Log4j in some modules.</para>
<para>To make Log4j work with the default JCL dependency
(<code>commons-logging</code>) all you need to do is put Log4j on the
classpath, and provide it with a configuration file
(<code>log4j.properties</code> or <code>log4j.xml</code> in the root
of the classpath). So for Maven users this is your dependency
declaration:</para>
<programlisting>&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework&lt;/groupId&gt;
&lt;artifactId&gt;spring-context&lt;/artifactId&gt;
&lt;version&gt;3.0.0.RELEASE&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;log4j&lt;/groupId&gt;
&lt;artifactId&gt;log4j&lt;/artifactId&gt;
&lt;version&gt;1.2.14&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt; </programlisting>
<para>And here's a sample log4j.properties for logging to the
console:</para>
<programlisting>log4j.rootCategory=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n
log4j.category.org.springframework.beans.factory=DEBUG</programlisting>
<section>
<title>Runtime Containers with Native JCL</title>
<para>Many people run their Spring applications in a container that
itself provides an implementation of JCL. IBM Websphere Application
Server (WAS) is the archetype. This often causes problems, and
unfortunately there is no silver bullet solution; simply excluding
<code>commons-logging</code> from your application is not enough in
most situations.</para>
<para>To be clear about this: the problems reported are usually not
with JCL per se, or even with <code>commons-logging</code>: rather
they are to do with binding <code>commons-logging</code> to another
framework (often Log4J). This can fail because
<code>commons-logging</code> changed the way they do the runtime
discovery in between the older versions (1.0) found in some
containers and the modern versions that most people use now (1.1).
Spring does not use any unusual parts of the JCL API, so nothing
breaks there, but as soon as Spring or your application tries to do
any logging you can find that the bindings to Log4J are not
working.</para>
<para>In such cases with WAS the easiest thing to do is to invert
the class loader hierarchy (IBM calls it "parent last") so that the
application controls the JCL dependency, not the container. That
option isn't always open, but there are plenty of other suggestions
in the public domain for alternative approaches, and your mileage
may vary depending on the exact version and feature set of the
container.</para>
</section>
</section>
</section>
</section>
</chapter>

View File

@@ -0,0 +1,695 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="oxm">
<title>Marshalling XML using O/X Mappers</title>
<section id="oxm-introduction">
<title>Introduction</title>
<para>
In this chapter, we will describe Spring's Object/XML Mapping support. Object/XML Mapping, or O/X mapping
for short, is the act of converting an XML document to and from an object. This conversion process is also
known as XML Marshalling, or XML Serialization. This chapter uses these terms interchangeably.
</para>
<para>
Within the field of O/X mapping, a <emphasis>marshaller</emphasis> is responsible for serializing an
object (graph) to XML. In similar fashion, an <emphasis>unmarshaller</emphasis> deserializes the XML to an
object graph. This XML can take the form of a DOM document, an input or output stream, or a SAX handler.
</para>
<para>Some of the benefits of using Spring for your O/X mapping needs are:</para>
<formalpara>
<title>Ease of configuration</title>
<para>
Spring's bean factory makes it easy to configure marshallers, without needing to construct JAXB context,
JiBX binding factories, etc. The marshallers can be configured as any other bean in your application
context. Additionally, XML Schema-based configuration is available for a number of marshallers, making
the configuration even simpler.
</para>
</formalpara>
<formalpara>
<title>Consistent Interfaces</title>
<para>
Spring's O/X mapping operates through two global interfaces: the
<interfacename>Marshaller</interfacename> and <interfacename>Unmarshaller</interfacename> interface.
These abstractions allow you to switch O/X mapping
frameworks with relative ease, with little or no changes required on the classes that do the
marshalling. This approach has the additional benefit of making it possible to do XML marshalling with
a mix-and-match approach (e.g. some marshalling performed using JAXB, other using XMLBeans) in a
non-intrusive fashion, leveraging the strength of each technology.
</para>
</formalpara>
<formalpara>
<title>Consistent Exception Hierarchy</title>
<para>
Spring provides a conversion from exceptions from the underlying O/X mapping tool to its own exception
hierarchy with the <classname>XmlMappingException</classname> as the root exception. As can be expected,
these runtime exceptions wrap the original exception so no information is lost.
</para>
</formalpara>
</section>
<section id="oxm-marshaller-unmarshaller">
<title>Marshaller and Unmarshaller</title>
<para>
As stated in the introduction, a <emphasis>marshaller</emphasis> serializes an object to XML, and an
<emphasis>unmarshaller</emphasis> deserializes XML stream to an object. In this section, we will describe
the two Spring interfaces used for this purpose.
</para>
<section>
<title>Marshaller</title>
<para>
Spring abstracts all marshalling operations behind the
<interfacename>org.springframework.oxm.Marshaller</interfacename> interface, the main methods of which
is listed below.
<programlisting language="java"><![CDATA[
public interface Marshaller {
/**
* Marshals the object graph with the given root into the provided Result.
*/
void marshal(Object graph, Result result)
throws XmlMappingException, IOException;
}]]></programlisting>
The <interfacename>Marshaller</interfacename> interface has one main method, which marshals the given
object to a given <interfacename>javax.xml.transform.Result</interfacename>. Result is a tagging
interface that basically represents an XML output abstraction: concrete implementations wrap various XML
representations, as indicated in the table below.
<informaltable>
<tgroup cols="2">
<thead>
<row>
<entry><interfacename>Result</interfacename> implementation</entry>
<entry>Wraps XML representation</entry>
</row>
</thead>
<tbody>
<row>
<entry><classname>DOMResult</classname></entry>
<entry><interfacename>org.w3c.dom.Node</interfacename></entry>
</row>
<row>
<entry><classname>SAXResult</classname></entry>
<entry><interfacename>org.xml.sax.ContentHandler</interfacename></entry>
</row>
<row>
<entry><interfacename>StreamResult</interfacename></entry>
<entry>
<classname>java.io.File</classname>,
<classname>java.io.OutputStream</classname>, or
<classname>java.io.Writer</classname>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<note>
<para>
Although the <methodname>marshal()</methodname> method accepts a plain object as its first
parameter, most <classname>Marshaller</classname> implementations cannot handle arbitrary
objects. Instead, an object class must be mapped in a mapping file, marked with an annotation,
registered with the marshaller, or have a common base class. Refer to the further sections
in this chapter to determine how your O/X technology of choice manages this.
</para>
</note>
</para>
</section>
<section>
<title>Unmarshaller</title>
<para>
Similar to the <interfacename>Marshaller</interfacename>, there is the
<interfacename>org.springframework.oxm.Unmarshaller</interfacename> interface.
<programlisting language="java"><![CDATA[
public interface Unmarshaller {
/**
* Unmarshals the given provided Source into an object graph.
*/
Object unmarshal(Source source)
throws XmlMappingException, IOException;
}]]></programlisting>
This interface also has one method, which reads from the given
<interfacename>javax.xml.transform.Source</interfacename> (an XML input abstraction), and returns the
object read. As with Result, Source is a tagging interface that has three concrete implementations. Each
wraps a different XML representation, as indicated in the table below.
<informaltable>
<tgroup cols="2">
<thead>
<row>
<entry><interfacename>Source</interfacename> implementation</entry>
<entry>Wraps XML representation</entry>
</row>
</thead>
<tbody>
<row>
<entry><classname>DOMSource</classname></entry>
<entry><interfacename>org.w3c.dom.Node</interfacename></entry>
</row>
<row>
<entry><classname>SAXSource</classname></entry>
<entry>
<classname>org.xml.sax.InputSource</classname>, and
<interfacename>org.xml.sax.XMLReader</interfacename>
</entry>
</row>
<row>
<entry><classname>StreamSource</classname></entry>
<entry>
<classname>java.io.File</classname>,
<classname>java.io.InputStream</classname>, or
<classname>java.io.Reader</classname>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</section>
<para>
Even though there are two separate marshalling interfaces (<interfacename>Marshaller</interfacename>
and <interfacename>Unmarshaller</interfacename>), all implementations found in Spring-WS implement both in
one class. This means that you can wire up one marshaller class and refer to it both as a marshaller and an
unmarshaller in your <filename>applicationContext.xml</filename>.
</para>
<section>
<title>XmlMappingException</title>
<para>
Spring converts exceptions from the underlying O/X mapping tool to its own exception hierarchy with the
<classname>XmlMappingException</classname> as the root exception. As can be expected, these runtime
exceptions wrap the original exception so no information will be lost.
</para>
<para>
Additionally, the <classname>MarshallingFailureException</classname> and
<classname>UnmarshallingFailureException</classname> provide a distinction between marshalling and
unmarshalling operations, even though the underlying O/X mapping tool does not do so.
</para>
<para>
The O/X Mapping exception hierarchy is shown in the following figure:
<mediaobject>
<imageobject>
<imagedata fileref="images/oxm-exceptions.png" align="center"/>
</imageobject>
<caption>
<para>
O/X Mapping exception hierarchy
</para>
</caption>
</mediaobject>
</para>
</section>
</section>
<section id="oxm-usage">
<title>Using Marshaller and Unmarshaller</title>
<para>
Spring's OXM can be used for a wide variety of situations. In the following example, we will use it to
marshal the settings of a Spring-managed application as an XML file. We will use a simple JavaBean to
represent the settings:
<programlisting language="java"><![CDATA[
public class Settings {
private boolean fooEnabled;
public boolean isFooEnabled() {
return fooEnabled;
}
public void setFooEnabled(boolean fooEnabled) {
this.fooEnabled = fooEnabled;
}
}]]></programlisting>
</para>
<para>
The application class uses this bean to store its settings. Besides a main method, the class has two
methods: <methodname>saveSettings()</methodname> saves the settings bean to a file named
<filename>settings.xml</filename>, and <methodname>loadSettings()</methodname> loads these settings again. A
<methodname>main()</methodname> method constructs a Spring application context, and calls these two methods.
<programlisting language="java"><![CDATA[
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
public class Application {
private static final String FILE_NAME = "settings.xml";
private Settings settings = new Settings();
private Marshaller marshaller;
private Unmarshaller unmarshaller;
public void setMarshaller(Marshaller marshaller) {
this.marshaller = marshaller;
}
public void setUnmarshaller(Unmarshaller unmarshaller) {
this.unmarshaller = unmarshaller;
}
public void saveSettings() throws IOException {
FileOutputStream os = null;
try {
os = new FileOutputStream(FILE_NAME);
this.marshaller.marshal(settings, new StreamResult(os));
} finally {
if (os != null) {
os.close();
}
}
}
public void loadSettings() throws IOException {
FileInputStream is = null;
try {
is = new FileInputStream(FILE_NAME);
this.settings = (Settings) this.unmarshaller.unmarshal(new StreamSource(is));
} finally {
if (is != null) {
is.close();
}
}
}
public static void main(String[] args) throws IOException {
ApplicationContext appContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
Application application = (Application) appContext.getBean("application");
application.saveSettings();
application.loadSettings();
}
}]]></programlisting>
The <classname>Application</classname> requires both a <property>marshaller</property>
and <property>unmarshaller</property> property to be set. We can do so using the following
<filename>applicationContext.xml</filename>:
<programlisting language="xml"><![CDATA[
<beans>
<bean id="application" class="Application">
<property name="marshaller" ref="castorMarshaller" />
<property name="unmarshaller" ref="castorMarshaller" />
</bean>
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/>
</beans>
]]></programlisting>
This application context uses Castor, but we could have used any of the other marshaller instances described
later in this chapter. Note that Castor does not require any further configuration by default, so the bean
definition is rather simple. Also note that the <classname>CastorMarshaller</classname> implements both
<interfacename>Marshaller</interfacename> and <interfacename>Unmarshaller</interfacename>, so we can refer
to the <varname>castorMarshaller</varname> bean in both the <property>marshaller</property> and
<property>unmarshaller</property> property of the application.
</para>
<para>
This sample application produces the following <filename>settings.xml</filename> file:
<programlisting language="xml"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<settings foo-enabled="false"/>
]]></programlisting>
</para>
</section>
<section>
<title>XML Schema-based Configuration</title>
<para>
Marshallers could be configured more concisely using tags from the OXM namespace.
To make these tags available, the appropriate schema has to be referenced first in the preamble of the XML configuration file.
Note the 'oxm' related text below:
</para>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
]]><emphasis role="bold"><![CDATA[xmlns:oxm="http://www.springframework.org/schema/oxm"]]></emphasis>
<![CDATA[xsi:schemaLocation="http://www.springframework.org/schema/beans
]]><![CDATA[http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
]]><emphasis role="bold"><![CDATA[http://www.springframework.org/schema/oxm
]]><![CDATA[http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd"]]></emphasis><![CDATA[>
]]></programlisting>
<para>
Currently, the following tags are available:
<itemizedlist>
<listitem>
<para><link linkend="oxm-jaxb2-xsd"><literal>jaxb2-marshaller</literal></link></para>
</listitem>
<listitem>
<para><link linkend="oxm-xmlbeans-xsd"><literal>xmlbeans-marshaller</literal></link></para>
</listitem>
<listitem>
<para><link linkend="oxm-jibx-xsd"><literal>jibx-marshaller</literal></link></para>
</listitem>
</itemizedlist>
</para>
<para>
Each tag will be explained in its respective marshaller's section. As an example though, here is how
the configuration of a JAXB2 marshaller might look like:
</para>
<programlisting language="xml"><![CDATA[<oxm:jaxb2-marshaller id="marshaller" contextPath="org.springframework.ws.samples.airline.schema"/>]]></programlisting>
</section>
<section id="oxm-jaxb">
<title>JAXB</title>
<para>
The JAXB binding compiler translates a W3C XML Schema into one or more Java classes, a
<filename>jaxb.properties</filename> file, and possibly some resource files. JAXB also offers a
way to generate a schema from annotated Java classes.
</para>
<para>
Spring supports the JAXB 2.0 API as XML marshalling strategies, following the
<interfacename>Marshaller</interfacename> and <interfacename>Unmarshaller</interfacename>
interfaces described in <xref linkend="oxm-marshaller-unmarshaller"/>. The corresponding integration
classes reside in the <package>org.springframework.oxm.jaxb</package> package.
</para>
<section id="oxm-jaxb2">
<title>Jaxb2Marshaller</title>
<para>
The <classname>Jaxb2Marshaller</classname> class implements both the Spring
<interfacename>Marshaller</interfacename> and <interfacename>Unmarshaller</interfacename>interface. It
requires a context path to operate, which you can set using the <property>contextPath</property>
property. The context path is a list of colon (:) separated Java package names that contain schema
derived classes. It also offers a <property>classesToBeBound</property> property, which allows you to set an array of
classes to be supported by the marshaller. Schema validation is performed by specifying one or more
schema resource to the bean, like so:
</para>
<programlisting language="xml"><![CDATA[
<beans>
<bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>org.springframework.oxm.jaxb.Flight</value>
<value>org.springframework.oxm.jaxb.Flights</value>
</list>
</property>
<property name="schema" value="classpath:org/springframework/oxm/schema.xsd"/>
</bean>
...
</beans>]]></programlisting>
<section id="oxm-jaxb2-xsd">
<title>XML Schema-based Configuration</title>
<para>
The <literal>jaxb2-marshaller</literal> tag configures a <classname>org.springframework.oxm.jaxb.Jaxb2Marshaller</classname>.
Here is an example:
</para>
<programlisting language="xml"><![CDATA[<oxm:jaxb2-marshaller id="marshaller" contextPath="org.springframework.ws.samples.airline.schema"/>]]></programlisting>
<para>
Alternatively, the list of classes to bind can be provided to the marshaller via the <literal>class-to-be-bound</literal> child tag:
</para>
<programlisting language="xml"><![CDATA[<oxm:jaxb2-marshaller id="marshaller">
<oxm:class-to-be-bound name="org.springframework.ws.samples.airline.schema.Airport"/>
<oxm:class-to-be-bound name="org.springframework.ws.samples.airline.schema.Flight"/>
...
</oxm:jaxb2-marshaller>
]]></programlisting>
<para>
Available attributes are:
<informaltable>
<tgroup cols="3">
<colspec colwidth="1.5*"/>
<colspec colwidth="4*"/>
<colspec colwidth="1*"/>
<thead>
<row>
<entry>Attribute</entry>
<entry>Description</entry>
<entry>Required</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>id</literal></entry>
<entry>the id of the marshaller</entry>
<entry>no</entry>
</row>
<row>
<entry><literal>contextPath</literal></entry>
<entry>the JAXB Context path</entry>
<entry>no</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</section>
</section>
</section>
<section id="oxm-castor">
<title>Castor</title>
<para>
Castor XML mapping is an open source XML binding framework. It allows you to transform the data contained in
a java object model into/from an XML document. By default, it does not require any further configuration,
though a mapping file can be used to have more control over the behavior of Castor.
</para>
<para>
For more information on Castor, refer to the <ulink url="http://castor.org/xml-framework.html">
<citetitle>Castor web site</citetitle></ulink>. The Spring integration classes reside in the
<package>org.springframework.oxm.castor</package> package.
</para>
<section>
<title>CastorMarshaller</title>
<para>
As with JAXB, the <classname>CastorMarshaller</classname> implements both the
<interfacename>Marshaller</interfacename> and <interfacename>Unmarshaller</interfacename> interface.
It can be wired up as follows:
</para>
<programlisting language="xml"><![CDATA[
<beans>
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" />
...
</beans>]]></programlisting>
</section>
<section>
<title>Mapping</title>
<para>
Although it is possible to rely on Castor's default marshalling behavior, it might be necessary to have
more control over it. This can be accomplished using a Castor mapping file. For more information, refer
to <ulink url="http://castor.org/xml-mapping.html">Castor XML Mapping</ulink>.
</para>
<para>
The mapping can be set using the <property>mappingLocation</property> resource property, indicated
below with a classpath resource.
</para>
<programlisting language="xml"><![CDATA[
<beans>
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" >
<property name="mappingLocation" value="classpath:mapping.xml" />
</bean>
</beans>
]]></programlisting>
</section>
</section>
<section id="oxm-xmlbeans">
<title>XMLBeans</title>
<para>
XMLBeans is an XML binding tool that has full XML Schema support, and offers full XML Infoset
fidelity. It takes a different approach to that of most other O/X mapping frameworks, in that
all classes that are generated from an XML Schema are all derived from
<interfacename>XmlObject</interfacename>, and contain XML binding information in them.
</para>
<para>
For more information on XMLBeans, refer to the <ulink url="http://xmlbeans.apache.org/">
<citetitle>XMLBeans web site </citetitle></ulink>. The Spring-WS integration classes reside
in the <package>org.springframework.oxm.xmlbeans</package> package.
</para>
<section>
<title>XmlBeansMarshaller</title>
<para>
The <classname>XmlBeansMarshaller</classname>
implements both the <interfacename>Marshaller</interfacename>
and <interfacename>Unmarshaller</interfacename>
interfaces. It can be configured as follows:
</para>
<programlisting language="xml"><![CDATA[
<beans>
<bean id="xmlBeansMarshaller" class="org.springframework.oxm.xmlbeans.XmlBeansMarshaller" />
...
</beans>]]></programlisting>
<note>
<para>
Note that the <classname>XmlBeansMarshaller</classname>
can only marshal objects of type <interfacename>XmlObject</interfacename>,
and not every <classname>java.lang.Object</classname>.
</para>
</note>
<section id="oxm-xmlbeans-xsd">
<title>XML Schema-based Configuration</title>
<para>
The <literal>xmlbeans-marshaller</literal> tag configures a <classname>org.springframework.oxm.xmlbeans.XmlBeansMarshaller</classname>.
Here is an example:
</para>
<programlisting language="xml"><![CDATA[<oxm:xmlbeans-marshaller id="marshaller"/>]]></programlisting>
<para>
Available attributes are:
<informaltable>
<tgroup cols="3">
<colspec colwidth="1.5*"/>
<colspec colwidth="4*"/>
<colspec colwidth="1*"/>
<thead>
<row>
<entry>Attribute</entry>
<entry>Description</entry>
<entry>Required</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>id</literal></entry>
<entry>the id of the marshaller</entry>
<entry>no</entry>
</row>
<row>
<entry><literal>options</literal></entry>
<entry>the bean name of the XmlOptions that is to be used for this marshaller. Typically a
<classname>XmlOptionsFactoryBean</classname> definition</entry>
<entry>no</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</section>
</section>
</section>
<section id="oxm-jibx">
<title>JiBX</title>
<para>
The JiBX framework offers a solution similar to that which JDO provides for ORM: a binding definition defines the
rules for how your Java objects are converted to or from XML. After preparing the binding and compiling the
classes, a JiBX binding compiler enhances the class files, and adds code to handle converting instances of
the classes from or to XML.
</para>
<para>
For more information on JiBX, refer to the <ulink url="http://jibx.sourceforge.net/">
<citetitle>JiBX web site</citetitle></ulink>. The Spring integration classes reside in the
<package>org.springframework.oxm.jibx</package> package.
</para>
<section>
<title>JibxMarshaller</title>
<para>
The <classname>JibxMarshaller</classname> class implements both the
<interfacename>Marshaller</interfacename> and <interfacename>Unmarshaller</interfacename> interface.
To operate, it requires the name of the class to marshal in, which you can set using the
<property>targetClass</property> property. Optionally, you can set the binding name using the
<property>bindingName</property> property. In the next sample, we bind the
<classname>Flights</classname> class:
</para>
<programlisting language="xml"><![CDATA[
<beans>
<bean id="jibxFlightsMarshaller" class="org.springframework.oxm.jibx.JibxMarshaller">
<property name="targetClass">org.springframework.oxm.jibx.Flights</property>
</bean>
...
]]></programlisting>
<para>
A <classname>JibxMarshaller</classname> is configured for a single class. If you want to marshal
multiple classes, you have to configure multiple <classname>JibxMarshaller</classname>s with
different <property>targetClass</property> property values.
</para>
<section id="oxm-jibx-xsd">
<title>XML Schema-based Configuration</title>
<para>
The <literal>jibx-marshaller</literal> tag configures a <classname>org.springframework.oxm.jibx.JibxMarshaller</classname>.
Here is an example:
</para>
<programlisting language="xml"><![CDATA[<oxm:jibx-marshaller id="marshaller" target-class="org.springframework.ws.samples.airline.schema.Flight"/>]]></programlisting>
<para>
Available attributes are:
<informaltable>
<tgroup cols="3">
<colspec colwidth="1.5*"/>
<colspec colwidth="4*"/>
<colspec colwidth="1*"/>
<thead>
<row>
<entry>Attribute</entry>
<entry>Description</entry>
<entry>Required</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>id</literal></entry>
<entry>the id of the marshaller</entry>
<entry>no</entry>
</row>
<row>
<entry><literal>target-class</literal></entry>
<entry>the target class for this marshaller</entry>
<entry>yes</entry>
</row>
<row>
<entry><literal>bindingName</literal></entry>
<entry>the binding name used by this marshaller</entry>
<entry>no</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</section>
</section>
</section>
<section id="oxm-xstream">
<title>XStream</title>
<para>
XStream is a simple library to serialize objects to XML and back again. It does not require any mapping, and
generates clean XML.
</para>
<para>
For more information on XStream, refer to the <ulink url="http://xstream.codehaus.org/">
<citetitle>XStream web site</citetitle></ulink>. The Spring integration classes reside in the
<package>org.springframework.oxm.xstream</package> package.
</para>
<section>
<title>XStreamMarshaller</title>
<para>
The <classname>XStreamMarshaller</classname> does not require any configuration, and can be configured
in an application context directly. To further customize the XML, you can set an
<emphasis>alias map</emphasis>, which consists of string aliases mapped to classes:
</para>
<programlisting language="xml"><![CDATA[
<beans>
<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="aliases">
<props>
<prop key="Flight">org.springframework.oxm.xstream.Flight</prop>
</props>
</property>
</bean>
...
</beans>]]></programlisting>
<warning>
<para>
By default, XStream allows for arbitrary classes to be unmarshalled, which can result in security
vulnerabilities.
As such, it is recommended to set the <property>supportedClasses</property> property on the
<classname>XStreamMarshaller</classname>, like so:
<programlisting language="xml"><![CDATA[<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="supportedClasses" value="org.springframework.oxm.xstream.Flight"/>
...
</bean>]]></programlisting>
This will make sure that only the registered classes are eligible for unmarshalling.
</para>
<para>
Additionally, you can register <ulink url="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/oxm/xstream/XStreamMarshaller.html#setConverters(com.thoughtworks.xstream.converters.ConverterMatcher[])">
custom converters</ulink> to make sure that only your supported classes can be unmarshalled.
</para>
</warning>
<note>
<para>
Note that XStream is an XML serialization library, not a data binding library. Therefore, it has
limited namespace support. As such, it is rather unsuitable for usage within Web services.
</para>
</note>
</section>
</section>
</chapter>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<preface id="preface">
<title>Preface</title>
<para>Developing software applications is hard enough even with good tools
and technologies. Implementing applications using platforms which promise
everything but turn out to be heavy-weight, hard to control and not very
efficient during the development cycle makes it even harder. Spring provides
a light-weight solution for building enterprise-ready applications, while
still supporting the possibility of using declarative transaction
management, remote access to your logic using RMI or web services, and
various options for persisting your data to a database. Spring provides a
full-featured <link linkend="mvc-introduction">MVC framework</link>, and
transparent ways of integrating <link linkend="aop-introduction">AOP</link>
into your software.</para>
<para>Spring could potentially be a one-stop-shop for all your enterprise
applications; however, Spring is modular, allowing you to use just those
parts of it that you need, without having to bring in the rest. You can use
the IoC container, with Struts on top, but you could also choose to use just
the <link linkend="orm-hibernate">Hibernate integration code</link> or the
<link linkend="jdbc-introduction">JDBC abstraction layer</link></para>
<para>Spring has been (and continues to be) designed to be non-intrusive,
meaning dependencies, from your domain logic code, on the framework itself
are generally none. For your integration layer like the data access layer
there will of course be some dependencies on the data access technology in
use and also on the Spring libraries, but these dependencies should be easy
to isolate from the rest of your code base.</para>
<para>This document provides a reference guide to Spring's features. Since
this document is still to be considered very much work-in-progress, if you
have any requests or comments, please post them on the user mailing list or
on the support forums at <ulink url="http://forum.springsource.org/" />.
</para>
</preface>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,742 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="resources">
<title>Resources</title>
<section 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 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 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 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 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 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 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 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 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 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" 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 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 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 id="resources-app-ctx">
<title>Application contexts and <interfacename>Resource</interfacename> paths</title>
<section 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 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 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 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 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 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("&lt;someFileInsideTheJar&gt;")</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 resoltion
strategy described above is used for the wildcard subpath.</para>
</section>
<section 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 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 <interfacename>Resource</interfacename> will always be <classname>UrlResource</classname></lineannotation><![CDATA[
ctx.getResource("file:/some/resource/path/myTemplate.txt");]]></programlisting>
<programlisting language="java"><lineannotation>// force this FileSystemXmlApplicationContext to load its definition via a <classname>UrlResource</classname></lineannotation><![CDATA[
ApplicationContext ctx =
new FileSystemXmlApplicationContext("file:/conf/context.xml");]]></programlisting>
</section>
</section>
</chapter>

Some files were not shown because too many files have changed in this diff Show More