SPR-6092: add section on EBR/Maven and tidy up references to jar files throughout
This commit is contained in:
@@ -74,9 +74,9 @@
|
||||
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
|
||||
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.
|
||||
|
||||
@@ -199,16 +199,15 @@ TR: This section doesn't read well and I think we should try to rewrite it.-->Nu
|
||||
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?
|
||||
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-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
|
||||
@@ -346,10 +345,565 @@ TR: OK. Added to diagram.--></para>
|
||||
<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
|
||||
<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>
|
||||
<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 shot 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.*-<version>.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-*-<version>.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.*-<version>.jar</code>), and the
|
||||
dependencies are also in this "long" form, with external libraries
|
||||
(not from SpringSource) having the prefix
|
||||
<code>com.springsource</code>.</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). 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><dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.0.0.RELEASE</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies> </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><repositories>
|
||||
<repository>
|
||||
<id>com.springsource.repository.maven.release</id>
|
||||
<url>http://s3.amazonaws.com/maven.springsource.com/release/</url>
|
||||
<snapshots><enabled>false</enabled></snapshots>
|
||||
</repository>
|
||||
</repositories></programlisting>
|
||||
|
||||
<para>For milestones:</para>
|
||||
|
||||
<programlisting><repositories>
|
||||
<repository>
|
||||
<id>com.springsource.repository.maven.milestone</id>
|
||||
<url>http://s3.amazonaws.com/maven.springsource.com/milestone/</url>
|
||||
<snapshots><enabled>false</enabled></snapshots>
|
||||
</repository>
|
||||
</repositories></programlisting>
|
||||
|
||||
<para>And for snapshots:</para>
|
||||
|
||||
<programlisting><repositories>
|
||||
<repository>
|
||||
<id>com.springsource.repository.maven.snapshot</id>
|
||||
<url>http://s3.amazonaws.com/maven.springsource.com/snapshot/</url>
|
||||
<snapshots><enabled>true</enabled></snapshots>
|
||||
</repository>
|
||||
</repositories></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><dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>org.springframework.context</artifactId>
|
||||
<version>3.0.0.RELEASE</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies></programlisting>
|
||||
|
||||
<para>You also need to declare the location of the repository
|
||||
explicitly (only the URL is important):</para>
|
||||
|
||||
<programlisting><repositories>
|
||||
<repository>
|
||||
<id>com.springsource.repository.bundles.release</id>
|
||||
<url>http://repository.springsource.com/maven/bundles/release/</url>
|
||||
</repository>
|
||||
</repositories></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>
|
||||
|
||||
<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 there (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).</para>
|
||||
|
||||
</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 worst thing about <code>commons-logging</code>, and what
|
||||
has made it unpopular with new tools, is also the runtime discovery
|
||||
algorithm. If we could turn back the clock and start Spring now as a
|
||||
new project it would use a different logging dependency. Probably the
|
||||
first choice would be the Simple Logging Framework 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>To switch 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><dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.0.0.RELEASE</version>
|
||||
<scope>runtime</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies> </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 prvided. 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><dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.0.0.RELEASE</version>
|
||||
<scope>runtime</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-slf4j</artifactId>
|
||||
<version>1.5.8</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.5.8</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>1.5.8</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>1.2.14</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies> </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-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 have 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><dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.0.0.RELEASE</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>1.2.14</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies> </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>
|
||||
|
||||
Reference in New Issue
Block a user