Browse Source

Documentation fixes: SPR-5748, SPR-5723, SPR-5750, SPR-5753, SPR-5747

git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@1215 50f2f4bb-b051-0410-bef5-90022cba6387
pull/1/head
Mark Pollack 17 years ago
parent
commit
89087e91fc
  1. 5
      spring-framework-reference/src/beans.xml
  2. 326
      spring-framework-reference/src/expressions.xml
  3. 72
      spring-framework-reference/src/new-in-3.xml
  4. 130
      spring-framework-reference/src/rest.xml
  5. 2
      spring-framework-reference/src/spring-framework-reference.xml

5
spring-framework-reference/src/beans.xml

@ -2526,6 +2526,7 @@ public class ReplacementComputeValue implements MethodReplacer {
method override would look like this:</para> method override would look like this:</para>
<programlisting language="xml">&lt;bean id="myValueCalculator class="x.y.z.MyValueCalculator"&gt; <programlisting language="xml">&lt;bean id="myValueCalculator class="x.y.z.MyValueCalculator"&gt;
<lineannotation>&lt;!-- arbitrary method replacement --&gt;</lineannotation> <lineannotation>&lt;!-- arbitrary method replacement --&gt;</lineannotation>
&lt;replaced-method name="computeValue" replacer="replacementComputeValue"&gt; &lt;replaced-method name="computeValue" replacer="replacementComputeValue"&gt;
&lt;arg-type&gt;String&lt;/arg-type&gt; &lt;arg-type&gt;String&lt;/arg-type&gt;
@ -6545,7 +6546,7 @@ public Service userService() {
protected abstract Command createCommand(); protected abstract Command createCommand();
} ]]></programlisting></para> } ]]></programlisting></para>
<para>Using Java-configurtion support we can easily create a <para>Using Java-configuration support we can easily create a
subclass of <code>CommandManager</code> where the abstract subclass of <code>CommandManager</code> where the abstract
<code>createCommand()</code> is overridden in such a way that it <code>createCommand()</code> is overridden in such a way that it
'looks up' a brand new (prototype) command object: <programlisting 'looks up' a brand new (prototype) command object: <programlisting
@ -6851,4 +6852,4 @@ public class CachingMovieCatalog implements MovieCatalog {
for more detail. For more on AspectJ load-time weaving, see <xref for more detail. For more on AspectJ load-time weaving, see <xref
linkend="aop-aj-ltw" />.</para> linkend="aop-aj-ltw" />.</para>
</section> </section>
</chapter> </chapter>

326
spring-framework-reference/src/expressions.xml

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<chapter id="expressions"> <chapter id="expressions">
<title>Spring Expression Language (SpEL)</title> <title>Spring Expression Language (SpEL)</title>
@ -12,24 +11,24 @@
expression language that supports querying and manipulating an object expression language that supports querying and manipulating an object
graph at runtime. The language syntax is similar to Unified EL but offers graph at runtime. The language syntax is similar to Unified EL but offers
additional features, most notably method invocation and basic string additional features, most notably method invocation and basic string
templating functionality. </para> templating functionality.</para>
<para>While there are several other Java expression languages available, <para>While there are several other Java expression languages available,
OGNL, MVEL, and JBoss EL, to name a few, the Spring Expression Language OGNL, MVEL, and JBoss EL, to name a few, the Spring Expression Language
was created to provide the Spring community with a single well supported was created to provide the Spring community with a single well supported
expression language that can used across all the products in the Spring expression language that can be used across all the products in the Spring
portfolio. Its language features are driven by the requirements of the portfolio. Its language features are driven by the requirements of the
projects in the Spring portfolio, including tooling requirements for code projects in the Spring portfolio, including tooling requirements for code
completion support within the eclipse based SpringSource Tool Suite. That completion support within the eclipse based SpringSource Tool Suite. That
said, SpEL is based on an technology agnostic API allowing other said, SpEL is based on an technology agnostic API allowing other
expression language implementations to be integreated should the need expression language implementations to be integrated should the need
arise.</para> arise.</para>
<para>While SpEL serves as the foundation for expression evaluation within <para>While SpEL serves as the foundation for expression evaluation within
the Spring portfolio, it is not directly tied to Spring and can be used the Spring portfolio, it is not directly tied to Spring and can be used
independently. In order to be self contained, many of the examples in this independently. In order to be self contained, many of the examples in this
chapter use SpEL as if it was an independent expression language. This chapter use SpEL as if it was an independent expression language. This
requires creating a few boostrapping infrastructure classes such as the requires creating a few bootstrapping infrastructure classes such as the
parser. Most Spring users will not need to deal with this infrastructure parser. Most Spring users will not need to deal with this infrastructure
and will instead only author expression strings for evaluation. An example and will instead only author expression strings for evaluation. An example
of this typical use is the integration of SpEL into creating XML or of this typical use is the integration of SpEL into creating XML or
@ -38,16 +37,16 @@
definitions.</link></para> definitions.</link></para>
<para>This chapter covers the features of the expression language, its <para>This chapter covers the features of the expression language, its
API, and its language sytnax. In several places an Inventor and Inventor's API, and its language syntax. In several places an Inventor and Inventor's
Society class are used as the target objects for expression evaluation. Society class are used as the target objects for expression evaluation.
These class declarations and the data used to populate them are listed at These class declarations and the data used to populate them are listed at
the end of the chapter. </para> the end of the chapter.</para>
</section> </section>
<section id="expressions-features"> <section id="expressions-features">
<title>Feature Overview</title> <title>Feature Overview</title>
<para>The expression language support the following functionality</para> <para>The expression language supports the following functionality</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
@ -126,11 +125,11 @@
<para><programlisting language="java">ExpressionParser parser = new SpelAntlrExpressionParser(); <para><programlisting language="java">ExpressionParser parser = new SpelAntlrExpressionParser();
Expression exp = parser.parseExpression("<emphasis role="bold">'Hello World'</emphasis>"); Expression exp = parser.parseExpression("<emphasis role="bold">'Hello World'</emphasis>");
String message = (String) exp.getValue();</programlisting>The value of the String message = (String) exp.getValue();</programlisting>The value of the
message variable is simply 'Hello World'. </para> message variable is simply 'Hello World'.</para>
<para>The SpEL classes and interfaces you are most likely to use are <para>The SpEL classes and interfaces you are most likely to use are
located in the packages <package>org.springframework.expression</package> located in the packages <package>org.springframework.expression</package>
and its subpackages <package>spel.antlr</package> and and its sub packages <package>spel.antlr</package> and
<package>spel.support</package>.</para> <package>spel.support</package>.</para>
<para>The expression language is based on a grammar and uses ANTLR to <para>The expression language is based on a grammar and uses ANTLR to
@ -143,10 +142,10 @@ String message = (String) exp.getValue();</programlisting>The value of the
can be thrown, <classname>ParseException</classname> and can be thrown, <classname>ParseException</classname> and
<classname>EvaluationException</classname> when calling <classname>EvaluationException</classname> when calling
'<literal>parser.parseExpression</literal>' and '<literal>parser.parseExpression</literal>' and
'<literal>exp.getValue</literal>' respectedly.</para> '<literal>exp.getValue</literal>' respectfully.</para>
<para>SpEL supports a wide range of features, such a calling methods, <para>SpEL supports a wide range of features, such as calling methods,
accessing properties and calling constructors. </para> accessing properties and calling constructors.</para>
<para>As an example of method invocation, we call the 'concat' method on <para>As an example of method invocation, we call the 'concat' method on
the string literal</para> the string literal</para>
@ -155,23 +154,28 @@ String message = (String) exp.getValue();</programlisting>The value of the
Expression exp = parser.parseExpression("<emphasis role="bold">'Hello World'.concat('!')</emphasis>"); Expression exp = parser.parseExpression("<emphasis role="bold">'Hello World'.concat('!')</emphasis>");
String message = (String) exp.getValue();</programlisting> String message = (String) exp.getValue();</programlisting>
<para>The value of message is now 'Hello World!'. </para> <para>The value of message is now 'Hello World!'.</para>
<para>As an example of calling a JavaBean property, the String property <para>As an example of calling a JavaBean property, the String property
'Bytes' can be called as shown below</para> 'Bytes' can be called as shown below</para>
<programlisting language="java">ExpressionParser parser = new SpelAntlrExpressionParser(); <programlisting language="java">ExpressionParser parser = new SpelAntlrExpressionParser();
Expression exp = parser.parseExpression("<emphasis role="bold">'Hello World'.bytes</emphasis>"); // invokes 'getBytes()'
// invokes 'getBytes()'
Expression exp = parser.parseExpression("<emphasis role="bold">'Hello World'.bytes</emphasis>");
byte[] bytes = (byte[]) exp.getValue();</programlisting> byte[] bytes = (byte[]) exp.getValue();</programlisting>
<para> <para>SpEL also supports nested properties using standard 'dot' notation,
SpEL also supports nested properties using standard 'dot' notation, i.e. i.e. prop1.prop2.prop3 and the setting of property values</para>
prop1.prop2.prop3 and the setting of property values</para>
<para>Public fields may also be accessed</para> <para>Public fields may also be accessed</para>
<programlisting language="java">ExpressionParser parser = new SpelAntlrExpressionParser(); <programlisting language="java">ExpressionParser parser = new SpelAntlrExpressionParser();
Expression exp = parser.parseExpression("<emphasis role="bold">'Hello World'.bytes.length</emphasis>"); // invokes 'getBytes().length'
// invokes 'getBytes().length'
Expression exp = parser.parseExpression("<emphasis role="bold">'Hello World'.bytes.length</emphasis>");
int length = (Integer) exp.getValue();</programlisting> int length = (Integer) exp.getValue();</programlisting>
<para>The String's constructor can be called instead of using a string <para>The String's constructor can be called instead of using a string
@ -191,7 +195,7 @@ String message = exp.getValue(String.class);</programlisting>
<para>The more common usage of SpEL is provide an expression string that <para>The more common usage of SpEL is provide an expression string that
is evaluated against a specific object instance. In the following example is evaluated against a specific object instance. In the following example
we retrieve the <literal>Name</literal> property from an instance of the we retrieve the <literal>Name</literal> property from an instance of the
Inventor class. </para> Inventor class.</para>
<para><programlisting language="java">// Create and set a calendar <para><programlisting language="java">// Create and set a calendar
GregorianCalendar c = new GregorianCalendar(); GregorianCalendar c = new GregorianCalendar();
@ -211,7 +215,7 @@ String name = (String) exp.getValue(context);</programlisting>In the last
Tesla". The class StandardEvaluationContext is where you can specify which Tesla". The class StandardEvaluationContext is where you can specify which
object the "Name" property will be evaluated against. You can reuse the object the "Name" property will be evaluated against. You can reuse the
same expression over and over again and set a new root object on the same expression over and over again and set a new root object on the
evaluation context. Expressions are evaluated using reflection. </para> evaluation context. Expressions are evaluated using reflection.</para>
<para><note> <para><note>
<para>In standalone usage of SpEL you will need to create the parser <para>In standalone usage of SpEL you will need to create the parser
@ -227,10 +231,10 @@ String name = (String) exp.getValue(context);</programlisting>In the last
boolean result = exp.getValue(context, Boolean.class); // evaluates to true</programlisting> boolean result = exp.getValue(context, Boolean.class); // evaluates to true</programlisting>
<section> <section>
<title>The EvaluationContext interface </title> <title>The EvaluationContext interface</title>
<para>The interface <interfacename>EvaluationContext</interfacename> is <para>The interface <interfacename>EvaluationContext</interfacename> is
used when evaluating an expression to resolve properties, methods, used when evaluating an expression to resolve properties, methods,
fields, and to help perform type conversion. The out-of-the-box fields, and to help perform type conversion. The out-of-the-box
implementation, <classname>StandardEvaluationContext</classname>, uses implementation, <classname>StandardEvaluationContext</classname>, uses
reflection to manipulate the object, caching reflection to manipulate the object, caching
@ -257,22 +261,24 @@ boolean result = exp.getValue(context, Boolean.class); // evaluates to true</pr
<section> <section>
<title>Type Conversion</title> <title>Type Conversion</title>
<para>By default SpEL uses the conversion service available in <para>By default SpEL uses the conversion service available in Spring
Spring core (<literal>org.springframework.core.convert.ConversionService</literal>). core
This conversion service comes with many converters built in for common conversions (<literal>org.springframework.core.convert.ConversionService</literal>).
but is also fully extensible so custom conversions between This conversion service comes with many converters built in for common
types can be added. Additionally it has the key capability that it conversions but is also fully extensible so custom conversions between
is generics aware. This means that when working with generic types in types can be added. Additionally it has the key capability that it is
expressions, SpEL will attempt conversions to maintain type correctness for any generics aware. This means that when working with generic types in
objects it encounters. expressions, SpEL will attempt conversions to maintain type
</para> correctness for any objects it encounters.</para>
<para>What does this mean in practice? Suppose assignment, using <literal>setValue()</literal>, <para>What does this mean in practice? Suppose assignment, using
is being used to set a <literal>List</literal> property. The type of the property is <literal>setValue()</literal>, is being used to set a
actually <literal>List&lt;Boolean&gt;</literal>. SpEL will recognize that the elements <literal>List</literal> property. The type of the property is actually
of the list need to be converted to <literal>Boolean</literal> before being placed in it. <literal>List&lt;Boolean&gt;</literal>. SpEL will recognize that the
A simple example:</para> elements of the list need to be converted to
<literal>Boolean</literal> before being placed in it. A simple
example:</para>
<programlisting>class Simple { <programlisting>class Simple {
public List&lt;Boolean&gt; booleanList = new ArrayList&lt;Boolean&gt;(); public List&lt;Boolean&gt; booleanList = new ArrayList&lt;Boolean&gt;();
} }
@ -395,33 +401,33 @@ Boolean b = simple.booleanList.get(0);
<programlisting language="java">public class SimpleMovieLister { <programlisting language="java">public class SimpleMovieLister {
private MovieFinder movieFinder; private MovieFinder movieFinder;
private String defaultLocale; private String defaultLocale;
@Autowired @Autowired
public void configure(MovieFinder movieFinder, public void configure(MovieFinder movieFinder,
@Value("#{ systemProperties['user.region'] } String defaultLocale) { @Value("#{ systemProperties['user.region']"} String defaultLocale) {
this.movieFinder = movieFinder; this.movieFinder = movieFinder;
this.defaultLocale = defaultLocale; this.defaultLocale = defaultLocale;
} }
// ... // ...
}</programlisting> }</programlisting>
<para><programlisting language="java">public class MovieRecommender { <para><programlisting language="java">public class MovieRecommender {
private String defaultLocale; private String defaultLocale;
private CustomerPreferenceDao customerPreferenceDao; private CustomerPreferenceDao customerPreferenceDao;
@Autowired @Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao, public MovieRecommender(CustomerPreferenceDao customerPreferenceDao,
@Value("#{ systemProperties['user.country'] } String defaultLocale) { @Value("#{ systemProperties['user.country']"} String defaultLocale) {
this.customerPreferenceDao = customerPreferenceDao; this.customerPreferenceDao = customerPreferenceDao;
this.defaultLocale = defaultLocale; this.defaultLocale = defaultLocale;
} }
// ... // ...
}</programlisting></para> }</programlisting></para>
</section> </section>
</section> </section>
@ -438,15 +444,17 @@ Boolean b = simple.booleanList.get(0);
the backslash character. The following listing shows simple usage of the backslash character. The following listing shows simple usage of
literals. Typically they would not be used in isolation like this, but literals. Typically they would not be used in isolation like this, but
as part of a more complex expression, for example using a literal on one as part of a more complex expression, for example using a literal on one
side of a logical comparison operator. </para> side of a logical comparison operator.</para>
<programlisting language="java">ExpressionParser parser = new SpelAntlrExpressionParser(); <programlisting language="java">ExpressionParser parser = new SpelAntlrExpressionParser();
String helloWorld = (String) parser.parseExpression("'Hello World'").getValue(); // evals to "Hello World" // evals to "Hello World"
String helloWorld = (String) parser.parseExpression("'Hello World'").getValue();
double avogadrosNumber = (Double) parser.parseExpression("6.0221415E+23").getValue(); double avogadrosNumber = (Double) parser.parseExpression("6.0221415E+23").getValue();
int maxValue = (Integer) parser.parseExpression("0x7FFFFFFF").getValue(); // evals to 2147483647 // evals to 2147483647
int maxValue = (Integer) parser.parseExpression("0x7FFFFFFF").getValue();
boolean trueValue = (Boolean) parser.parseExpression("true").getValue(); boolean trueValue = (Boolean) parser.parseExpression("true").getValue();
@ -463,19 +471,20 @@ Object nullValue = parser.parseExpression("null").getValue();
<para>Navigating with property references is easy, just use a period to <para>Navigating with property references is easy, just use a period to
indicate a nested property value. The instances of Inventor class, pupin indicate a nested property value. The instances of Inventor class, pupin
and tesla, were populated with data listed in section Section <link and tesla, were populated with data listed in the section <link
linkend="expressions-example-classes">Classes used in the linkend="expressions-example-classes">Classes used in the
examples</link>. To navigate "down" and get Tesla's year of birth and examples</link>. To navigate "down" and get Tesla's year of birth and
Pupin's city of birth the following expressions are used </para> Pupin's city of birth the following expressions are used</para>
<programlisting lang="" language="java">int year = (Integer) parser.parseExpression("Birthdate.Year + 1900").getValue(context); // 1856 <programlisting lang="" language="java">// evals to 1856
int year = (Integer) parser.parseExpression("Birthdate.Year + 1900").getValue(context);
String city = (String) parser.parseExpression("placeOfBirth.City").getValue(context);</programlisting> String city = (String) parser.parseExpression("placeOfBirth.City").getValue(context);</programlisting>
<para>Case insensitivity is allowed for the first letter of property <para>Case insensitivity is allowed for the first letter of property
names. The contents of arrays and lists are obtained using square names. The contents of arrays and lists are obtained using square
bracket notation. </para> bracket notation.</para>
<programlisting language="java">ExpressionParser parser = new SpelAntlrExpressionParser(); <programlisting language="java">ExpressionParser parser = new SpelAntlrExpressionParser();
@ -484,7 +493,8 @@ StandardEvaluationContext teslaContext = new StandardEvaluationContext();
teslaContext.setRootObject(tesla); teslaContext.setRootObject(tesla);
// evaluates to "Induction motor" // evaluates to "Induction motor"
String invention = parser.parseExpression("inventions[3]").getValue(teslaContext, String.class); String invention = parser.parseExpression("inventions[3]").getValue(teslaContext,
String.class);
// Members List // Members List
@ -496,23 +506,27 @@ String name = parser.parseExpression("Members[0].Name").getValue(societyContext,
// List and Array navigation // List and Array navigation
// evaluates to "Wireless communication" // evaluates to "Wireless communication"
String invention = parser.parseExpression("Members[0].Inventions[6]").getValue(societyContext, String.class); String invention = parser.parseExpression("Members[0].Inventions[6]").getValue(societyContext,
String.class);
</programlisting> </programlisting>
<para>The contents of maps are obtained by specifying the <para>The contents of maps are obtained by specifying the literal key
literal key value within the brackets. In this case, because keys for value within the brackets. In this case, because keys for the Officers
the Officers map are strings, we can specify string map are strings, we can specify string literal.</para>
literal.</para>
<programlisting lang="" language="java">// Officer's Dictionary <programlisting lang="" language="java">// Officer's Dictionary
Inventor pupin = parser.parseExpression("Officers['president']").getValue(societyContext, Inventor.class); Inventor pupin = parser.parseExpression("Officers['president']").getValue(societyContext,
Inventor.class);
// evaluates to "Idvor" // evaluates to "Idvor"
String city = parser.parseExpression("Officers['president'].PlaceOfBirth.City").getValue(societyContext, String.class); String city =
parser.parseExpression("Officers['president'].PlaceOfBirth.City").getValue(societyContext,
String.class);
// setting values // setting values
parser.parseExpression("Officers['advisors'][0].PlaceOfBirth.Country").setValue(societyContext, "Croatia"); parser.parseExpression("Officers['advisors'][0].PlaceOfBirth.Country").setValue(societyContext,
"Croatia");
</programlisting> </programlisting>
</section> </section>
@ -527,7 +541,8 @@ parser.parseExpression("Officers['advisors'][0].PlaceOfBirth.Country").setValue(
String c = parser.parseExpression("'abc'.substring(2, 3)").getValue(String.class); String c = parser.parseExpression("'abc'.substring(2, 3)").getValue(String.class);
// evaluates to true // evaluates to true
boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(societyContext, Boolean.class);</programlisting> boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(societyContext,
Boolean.class);</programlisting>
</section> </section>
<section> <section>
@ -538,7 +553,7 @@ boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(
<para>The relational operators; equal, not equal, less than, less than <para>The relational operators; equal, not equal, less than, less than
or equal, greater than, and greater than or equal are supported using or equal, greater than, and greater than or equal are supported using
standard operator notation. </para> standard operator notation.</para>
<para><programlisting language="java">// evaluates to true <para><programlisting language="java">// evaluates to true
boolean trueValue = parser.parseExpression("2 == 2").getValue(Boolean.class); boolean trueValue = parser.parseExpression("2 == 2").getValue(Boolean.class);
@ -555,10 +570,12 @@ boolean trueValue = parser.parseExpression("'black' &lt; 'block'").getValue(Bool
boolean falseValue = parser.parseExpression("'xyz' instanceof T(int)").getValue(Boolean.class); boolean falseValue = parser.parseExpression("'xyz' instanceof T(int)").getValue(Boolean.class);
// evaluates to true // evaluates to true
boolean trueValue = parser.parseExpression("'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class); boolean trueValue =
parser.parseExpression("'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
//evaluates to false //evaluates to false
boolean falseValue = parser.parseExpression("'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class); boolean falseValue =
parser.parseExpression("'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
</programlisting> </programlisting>
</section> </section>
@ -605,12 +622,13 @@ boolean falseValue = parser.parseExpression(expression).getValue(societyContext,
Subtraction can be used on numbers and dates. Multiplication and Subtraction can be used on numbers and dates. Multiplication and
division can be used only on numbers. Other mathematical operators division can be used only on numbers. Other mathematical operators
supported are modulus (%) and exponential power (^). Standard operator supported are modulus (%) and exponential power (^). Standard operator
precedence is enforced. These operators are demonstrated below </para> precedence is enforced. These operators are demonstrated below</para>
<para><programlisting language="java">// Addition <para><programlisting language="java">// Addition
int two = parser.parseExpression("1 + 1").getValue(Integer.class); // 2 int two = parser.parseExpression("1 + 1").getValue(Integer.class); // 2
String testString = parser.parseExpression("'test' + ' ' + 'string'").getValue(String.class); // 'test string' String testString =
parser.parseExpression("'test' + ' ' + 'string'").getValue(String.class); // 'test string'
// Subtraction // Subtraction
int four = parser.parseExpression("1 - -3").getValue(Integer.class); // 4 int four = parser.parseExpression("1 - -3").getValue(Integer.class); // 4
@ -644,7 +662,7 @@ int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class);
<para>Setting of a property is done by using the assignment operator. <para>Setting of a property is done by using the assignment operator.
This would typically be done within a call to This would typically be done within a call to
<literal>setValue</literal> but can also be done inside a call to <literal>setValue</literal> but can also be done inside a call to
<literal>getValue</literal> </para> <literal>getValue</literal></para>
<programlisting language="java">Inventor inventor = new Inventor(); <programlisting language="java">Inventor inventor = new Inventor();
StandardEvaluationContext inventorContext = new StandardEvaluationContext(); StandardEvaluationContext inventorContext = new StandardEvaluationContext();
@ -654,7 +672,8 @@ parser.parseExpression("Name").setValue(inventorContext, "Alexander Seovic2");
// alternatively // alternatively
String aleks = parser.parseExpression("Name = 'Alexandar Seovic'").getValue(inventorContext, String.class); String aleks = parser.parseExpression("Name = 'Alexandar Seovic'").getValue(inventorContext,
String.class);
</programlisting> </programlisting>
<para></para> <para></para>
@ -665,18 +684,20 @@ String aleks = parser.parseExpression("Name = 'Alexandar Seovic'").getValue(inve
<para>The special 'T' operator can be used to specify an instance of <para>The special 'T' operator can be used to specify an instance of
java.lang.Class (the 'type'). Static methods are invoked using this java.lang.Class (the 'type'). Static methods are invoked using this
operator as well. The <classname>StandardEvaluationContext</classname> operator as well. The <classname>StandardEvaluationContext</classname>
uses a <classname>TypeLocator</classname> to find types and uses a <classname>TypeLocator</classname> to find types and the
the <classname>StandardTypeLocator</classname> (which can be replaced) <classname>StandardTypeLocator</classname> (which can be replaced) is
is built with an understanding of the java.lang package. This means T() built with an understanding of the java.lang package. This means T()
references to types within java.lang do not need to be fully qualified, references to types within java.lang do not need to be fully qualified,
but all other type references must be.</para> but all other type references must be.</para>
<programlisting language="java">Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class); <programlisting language="java">Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class);
Class stringClass = parser.parseExpression("T(String)").getValue(Class.class); Class stringClass = parser.parseExpression("T(String)").getValue(Class.class);
boolean trueValue = parser.parseExpression("T(java.math.RoundingMode).CEILING &lt; T(java.math.RoundingMode).FLOOR").getValue(Boolean.class); boolean trueValue =
parser.parseExpression("T(java.math.RoundingMode).CEILING &lt; T(java.math.RoundingMode).FLOOR")
.getValue(Boolean.class);
</programlisting> </programlisting>
</section> </section>
@ -688,19 +709,23 @@ boolean trueValue = parser.parseExpression("T(java.math.RoundingMode).CEILING &l
String (where int, float, etc, can be used).</para> String (where int, float, etc, can be used).</para>
<programlisting language="java">Inventor einstein = <programlisting language="java">Inventor einstein =
parser.parseExpression("new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German')").getValue(Inventor.class); p.parseExpression("new org.spring.samples.spel.inventor.Inventor('Albert Einstein',
'German')")
.getValue(Inventor.class);
//create new inventor instance within add method of List //create new inventor instance within add method of List
parser.parseExpression("Members.add(new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German'))").getValue(societyContext); p.parseExpression("Members.add(new org.spring.samples.spel.inventor.Inventor('Albert Einstein',
'German'))")
.getValue(societyContext);
</programlisting> </programlisting>
</section> </section>
<section id="expressions-ref-variables"> <section id="expressions-ref-variables">
<title>Variables</title> <title>Variables</title>
<para>Variables can referenced in the expression using the syntax <para>Variables can be referenced in the expression using the syntax
#variableName. Variables are set using the method setVariable on the #variableName. Variables are set using the method setVariable on the
StandardEvaluationContext. </para> StandardEvaluationContext.</para>
<programlisting language="java">Inventor tesla = new Inventor("Nikola Tesla", "Serbian"); <programlisting language="java">Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
StandardEvaluationContext context = new StandardEvaluationContext(); StandardEvaluationContext context = new StandardEvaluationContext();
@ -716,9 +741,9 @@ System.out.println(tesla.getName()) // "Mike Tesla"</programlisting>
<section> <section>
<title>The #this variable</title> <title>The #this variable</title>
<para>The variable #this is always defined and refers to the <para>The variable #this is always defined and refers to the current
current evaluation object (the object against which unqualified evaluation object (the object against which unqualified references
references will be resolved). </para> will be resolved).</para>
<programlisting language="java">// create an array of integers <programlisting language="java">// create an array of integers
List&lt;Integer&gt; primes = new ArrayList&lt;Integer&gt;(); List&lt;Integer&gt; primes = new ArrayList&lt;Integer&gt;();
@ -730,10 +755,13 @@ StandardEvaluationContext context = new StandardEvaluationContext();
context.setVariable("primes",primes); context.setVariable("primes",primes);
// all prime numbers &gt; 10 from the list (using selection ?{...}) // all prime numbers &gt; 10 from the list (using selection ?{...})
List&lt;Integer&gt; primesGreaterThanTen = (List&lt;Integer&gt;) parser.parseExpression("#primes.?[#this&gt;10]").getValue(context); // evaluates to [11, 13, 17]
List&lt;Integer&gt; primesGreaterThanTen =
(List&lt;Integer&gt;) parser.parseExpression("#primes.?[#this&gt;10]").getValue(context);
//evaluates to [11, 13, 17]</programlisting> </programlisting>
</section> </section>
<!-- <!--
<section> <section>
<title>The #root variable</title> <title>The #root variable</title>
@ -772,7 +800,7 @@ List&lt;Integer&gt; primesGreaterThanTen = (List&lt;Integer&gt;) parser.parseExp
public static String reverseString(String input) { public static String reverseString(String input) {
StringBuilder backwards = new StringBuilder(); StringBuilder backwards = new StringBuilder();
for (int i = 0; i &lt; input.length(); i++) { for (int i = 0; i &lt; input.length(); i++)
backwards.append(input.charAt(input.length() - 1 - i)); backwards.append(input.charAt(input.length() - 1 - i));
} }
return backwards.toString(); return backwards.toString();
@ -786,18 +814,21 @@ List&lt;Integer&gt; primesGreaterThanTen = (List&lt;Integer&gt;) parser.parseExp
StandardEvaluationContext context = new StandardEvaluationContext(); StandardEvaluationContext context = new StandardEvaluationContext();
context.registerFunction("reverseString", context.registerFunction("reverseString",
StringUtils.class.getDeclaredMethod("reverseString", new Class[] { String.class })); StringUtils.class.getDeclaredMethod("reverseString",
new Class[] { String.class }));
String helloWorldReversed = parser.parseExpression("#reverseString('hello')").getValue(context, String.class);</programlisting> String helloWorldReversed =
parser.parseExpression("#reverseString('hello')").getValue(context, String.class);</programlisting>
</section> </section>
<section> <section>
<title>Ternary Operator (If-Then-Else)</title> <title>Ternary Operator (If-Then-Else)</title>
<para>You can use the ternary operator for performing if-then-else <para>You can use the ternary operator for performing if-then-else
conditional logic inside the expression. A minimal example is; </para> conditional logic inside the expression. A minimal example is;</para>
<programlisting language="java">String falseString = parser.parseExpression("false ? 'trueExp' : 'falseExp'").getValue(String.class);</programlisting> <programlisting language="java">String falseString =
parser.parseExpression("false ? 'trueExp' : 'falseExp'").getValue(String.class);</programlisting>
<para>In this case, the boolean false results in returning the string <para>In this case, the boolean false results in returning the string
value 'falseExp'. A less artificial example is shown below.</para> value 'falseExp'. A less artificial example is shown below.</para>
@ -808,59 +839,65 @@ societyContext.setVariable("queryName", "Nikola Tesla");
expression = "isMember(#queryName)? #queryName + ' is a member of the ' " + expression = "isMember(#queryName)? #queryName + ' is a member of the ' " +
"+ Name + ' Society' : #queryName + ' is not a member of the ' + Name + ' Society'"; "+ Name + ' Society' : #queryName + ' is not a member of the ' + Name + ' Society'";
String queryResultString = parser.parseExpression(expression).getValue(societyContext, String.class); String queryResultString =
parser.parseExpression(expression).getValue(societyContext, String.class);
// queryResultString = "Nikola Tesla is a member of the IEEE Society"</programlisting> // queryResultString = "Nikola Tesla is a member of the IEEE Society"</programlisting>
</section> </section>
<section> <section>
<title>Collection Selection</title> <title>Collection Selection</title>
<para>Selection is a powerful expression language feature that <para>Selection is a powerful expression language feature that allow you
allow you to transform some source collection into another by selecting to transform some source collection into another by selecting from its
from its entries.</para> entries.</para>
<para>Selection uses the syntax <literal>?[selectionExpression]</literal>. This will <para>Selection uses the syntax
filter the collection and return a new collection containing a subset of the <literal>?[selectionExpression]</literal>. This will filter the
original elements. For example, selection would allow us to easily collection and return a new collection containing a subset of the
get a list of Serbian inventors:</para> original elements. For example, selection would allow us to easily get a
list of Serbian inventors:</para>
<programlisting language="java">List&lt;Inventor&gt; list = (List&lt;Inventor&gt;) parser.parseExpression("Members.?[Nationality == 'Serbian']").getValue(societyContext);</programlisting>
<programlisting language="java">List&lt;Inventor&gt; list = (List&lt;Inventor&gt;)
<para>Selection is possible upon both lists and maps. In the former case the parser.parseExpression("Members.?[Nationality == 'Serbian']").getValue(societyContext);</programlisting>
selection criteria is evaluated against each individual list element whilst against
a map the selection criteria is evaluated against each map entry (objects of the Java <para>Selection is possible upon both lists and maps. In the former case
type <literal>Map.Entry</literal>). Map entries have their key and value accessible the selection criteria is evaluated against each individual list element
as properties for use in the selection.</para> whilst against a map the selection criteria is evaluated against each
map entry (objects of the Java type <literal>Map.Entry</literal>). Map
<para>This expression will return a new map consisting of those elements of the entries have their key and value accessible as properties for use in the
original map where the entry value is less than 27.</para> selection.</para>
<para>This expression will return a new map consisting of those elements
of the original map where the entry value is less than 27.</para>
<programlisting language="java">Map newMap = parser.parseExpression("map.?[value&lt;27]").getValue();</programlisting> <programlisting language="java">Map newMap = parser.parseExpression("map.?[value&lt;27]").getValue();</programlisting>
<para>In addition to returning all the selected elements, it is possible to retrieve <para>In addition to returning all the selected elements, it is possible
just the first or the last value. To obtain the first entry matching the selection to retrieve just the first or the last value. To obtain the first entry
the syntax is <literal>^[...]</literal> whilst to obtain the last matching selection matching the selection the syntax is <literal>^[...]</literal> whilst to
the syntax is <literal>$[...]</literal>. obtain the last matching selection the syntax is
</para> <literal>$[...]</literal>.</para>
</section> </section>
<section> <section>
<title>Collection Projection</title> <title>Collection Projection</title>
<para>Projection allows a collection to drive the evaluation of a sub-expression and <para>Projection allows a collection to drive the evaluation of a
the result is a new collection. The syntax for projection is <literal>![projectionExpression]</literal>. sub-expression and the result is a new collection. The syntax for
Most easily understood by example, suppose we have projection is <literal>![projectionExpression]</literal>. Most easily
a list of inventors but want the list of cities where they were born. Effectively understood by example, suppose we have a list of inventors but want the
we want to evaluate 'placeOfBirth.city' for every entry in the inventor list. Using list of cities where they were born. Effectively we want to evaluate
'placeOfBirth.city' for every entry in the inventor list. Using
projection:</para> projection:</para>
<programlisting language="java">// returns [ 'Smiljan', 'Idvor' ] <programlisting language="java">// returns [ 'Smiljan', 'Idvor' ]
List placesOfBirth = (List)parser.parseExpression("Members.![placeOfBirth.city]");</programlisting> List placesOfBirth = (List)parser.parseExpression("Members.![placeOfBirth.city]");</programlisting>
<para>A map can also be used to drive projection and in this case the projection <para>A map can also be used to drive projection and in this case the
expression is evaluated against each entry in the map (represented as a Java projection expression is evaluated against each entry in the map
<literal>Map.Entry</literal>). The result of a projection across a map is a list consisting (represented as a Java <literal>Map.Entry</literal>). The result of a
of the evaluation of the projection expression against each map entry.</para> projection across a map is a list consisting of the evaluation of the
projection expression against each map entry.</para>
</section> </section>
<section> <section>
@ -872,7 +909,8 @@ List placesOfBirth = (List)parser.parseExpression("Members.![placeOfBirth.city]"
<literal>${} </literal>as the delimiters. For example,</para> <literal>${} </literal>as the delimiters. For example,</para>
<programlisting language="java">String randomPhrase = <programlisting language="java">String randomPhrase =
parser.parseExpression("random number is ${T(java.lang.Math).random()}", new TemplatedParserContext()).getValue(String.class); parser.parseExpression("random number is ${T(java.lang.Math).random()}",
new TemplatedParserContext()).getValue(String.class);
// evaluates to "random number is 0.7038186818312008"</programlisting> // evaluates to "random number is 0.7038186818312008"</programlisting>
@ -1057,4 +1095,4 @@ public class Society {
} }
</programlisting> </programlisting>
</section> </section>
</chapter> </chapter>

72
spring-framework-reference/src/new-in-3.xml

@ -67,10 +67,11 @@
<section id="new-in-3-new-tutorial"> <section id="new-in-3-new-tutorial">
<title>New getting started tutorial</title> <title>New getting started tutorial</title>
<para>There is now a new getting started tutorial for developing a basic <para>There is now a new getting started tutorial for developing a basic
Spring 3.0 MVC web application. This tutorial is a separate document that can Spring 3.0 MVC web application. This tutorial is a separate document that
be found at the <ulink url="http://www.springsource.org/documentation"> can be found at the <ulink
Spring Documentation</ulink> page.</para> url="http://www.springsource.org/documentation"> Spring
Documentation</ulink> page.</para>
</section> </section>
<section id="new-in-3-modules-build"> <section id="new-in-3-modules-build">
@ -205,39 +206,36 @@
<listitem> <listitem>
<para>Early support for Java EE 6</para> <para>Early support for Java EE 6</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Embedded database support</para> <para>Embedded database support</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<section id="new-feature-java5"> <section id="new-feature-java5">
<title>Core APIs updated for Java 5</title> <title>Core APIs updated for Java 5</title>
<para>BeanFactory interface returns typed bean instances as far as possible: <para>BeanFactory interface returns typed bean instances as far as
<itemizedlist> possible: <itemizedlist>
<listitem> <listitem>
<para>T getBean(Stringname, Class&lt;T&gt; requiredType)</para> <para>T getBean(Stringname, Class&lt;T&gt; requiredType)</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Map&lt;String, T&gt; getBeansOfType(Class&lt;T&gt; type)</para> <para>Map&lt;String, T&gt; getBeansOfType(Class&lt;T&gt;
</listitem> type)</para>
</itemizedlist> </listitem>
</para> </itemizedlist></para>
<para>Spring's TaskExecutor interface now extends <para>Spring's TaskExecutor interface now extends
<classname>java.util.concurrent.Executor</classname>: <classname>java.util.concurrent.Executor</classname>: <itemizedlist>
<itemizedlist>
<listitem> <listitem>
<para>extended AsyncTaskExecutor supports standard Callables with <para>extended AsyncTaskExecutor supports standard Callables with
Futures</para> Futures</para>
</listitem> </listitem>
</itemizedlist></para> </itemizedlist></para>
<para>New Java 5 based converter API and SPI: <para>New Java 5 based converter API and SPI: <itemizedlist>
<itemizedlist>
<listitem> <listitem>
<para>stateless ConversionService and Converters</para> <para>stateless ConversionService and Converters</para>
</listitem> </listitem>
@ -297,13 +295,10 @@ public class RewardsTestDatabase {
<section id="new-java-configuration"> <section id="new-java-configuration">
<title>Java based bean metadata</title> <title>Java based bean metadata</title>
<para> <para>Some core features from the <ulink
Some core features from the url="http://www.springsource.org/javaconfig">JavaConfig</ulink>
<ulink url="http://www.springsource.org/javaconfig">JavaConfig</ulink> project have been added to the Spring Framework now. This means that
project have been added to the Spring Framework now. This means the following annotations are now directly supported: <itemizedlist>
that the following annotations are now directly supported:
<itemizedlist>
<listitem> <listitem>
<para>@Configuration</para> <para>@Configuration</para>
</listitem> </listitem>
@ -327,8 +322,7 @@ public class RewardsTestDatabase {
<listitem> <listitem>
<para>@Value</para> <para>@Value</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist></para>
</para>
<para>Here is an example of a Java class providing basic configuration <para>Here is an example of a Java class providing basic configuration
using the new JavaConfig features: <programlisting language="java">@Configuration using the new JavaConfig features: <programlisting language="java">@Configuration
@ -383,8 +377,8 @@ public class AppConfig{
<para>Object to XML mapping functionality (OXM) from the Spring Web <para>Object to XML mapping functionality (OXM) from the Spring Web
Services project has been moved to the core Spring Framework now. The Services project has been moved to the core Spring Framework now. The
functionality is found in the <literal>org.springframework.oxm</literal> functionality is found in the <literal>org.springframework.oxm</literal>
package. More information on the use of the <literal>OXM</literal> module package. More information on the use of the <literal>OXM</literal>
can be found in the <link linkend="oxm">Marshalling XML using O/X module can be found in the <link linkend="oxm">Marshalling XML using O/X
Mappers</link> chapter.</para> Mappers</link> chapter.</para>
</section> </section>
@ -409,7 +403,7 @@ public class AppConfig{
conversion between objects and their representation in HTTP request conversion between objects and their representation in HTTP request
and replies.</para> and replies.</para>
<para>The <classname>MarhsallingHttpMessageConverter</classname> uses <para>The <classname>MarshallingHttpMessageConverter</classname> uses
the <emphasis>Object to XML mapping</emphasis> functionality mentioned the <emphasis>Object to XML mapping</emphasis> functionality mentioned
earlier.</para> earlier.</para>
@ -449,13 +443,13 @@ public class AppConfig{
<para>Work in progress... not part of the Spring 3.0 M3 release.</para> <para>Work in progress... not part of the Spring 3.0 M3 release.</para>
</section> </section>
<section id="new-feature-embedded-databases"> <section id="new-feature-embedded-databases">
<title>Support for embedded databases</title> <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>Convenient support for <link
</para> linkend="jdbc-embedded-database-support">embedded Java database
engines</link>, including HSQL, H2, and Derby, is now provided.</para>
</section> </section>
</section> </section>
</chapter> </chapter>

130
spring-framework-reference/src/rest.xml

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<chapter id="rest"> <chapter id="rest">
<title>REST support</title> <title>REST support</title>
@ -9,7 +8,7 @@
<title>Introduction</title> <title>Introduction</title>
<para>The goal of Spring's REST support is to make the development of <para>The goal of Spring's REST support is to make the development of
RESTful Web services and applications easier. </para> RESTful Web services and applications easier.</para>
<para>Client-side access to RESTful resources is greatly simplified using <para>Client-side access to RESTful resources is greatly simplified using
Spring <classname>RestTemplate</classname>. Spring <classname>RestTemplate</classname>.
@ -18,7 +17,7 @@
<classname>JmsTemplate</classname>. Instead of dealing with a verbose <classname>JmsTemplate</classname>. Instead of dealing with a verbose
lower level API such as Apache Commons <classname>HttpClient</classname> lower level API such as Apache Commons <classname>HttpClient</classname>
to create RESTful request, RestTemplate provides one liner methods that to create RESTful request, RestTemplate provides one liner methods that
are purpose built for RESTful programming. </para> are purpose built for RESTful programming.</para>
<para>On the server-side, Spring's REST support is based upon Spring's <para>On the server-side, Spring's REST support is based upon Spring's
existing annotation based MVC framework. (For those interested in the existing annotation based MVC framework. (For those interested in the
@ -32,12 +31,11 @@
header.</para> header.</para>
<para>In this chapter we describe all the features of Spring's REST <para>In this chapter we describe all the features of Spring's REST
support. It is divided into two main two chapters, one for the server-side support. It is divided into two main chapters, one for the server-side and
and one for the client-side. For those new to Spring's <link one for the client-side. For those new to Spring's <link linkend="mvc">MVC
linkend="mvc">MVC framework</link>, you may want to read through the framework</link>, you may want to read through the reference documentation
reference documentation on <link linkend="mvc-annotation">annotation-based on <link linkend="mvc-annotation">annotation-based controller
controller configuration</link> to understand the general programming configuration</link> to understand the general programming model.</para>
model.</para>
</section> </section>
<section id="rest-creating-services"> <section id="rest-creating-services">
@ -75,7 +73,7 @@
variable. A Spring controller method to process above example is shown variable. A Spring controller method to process above example is shown
below;</para> below;</para>
<programlisting language="java">@RequestMapping(value="/users/{userid}", method=RequestMethod.GET) <programlisting language="java">@RequestMapping(value="/users/{userId}", method=RequestMethod.GET)
public String getUser(@PathVariable String userId) { public String getUser(@PathVariable String userId) {
// implementation omitted... // implementation omitted...
}</programlisting> }</programlisting>
@ -172,7 +170,7 @@ public class RelativePathUriTemplateController {
<para>The <classname>@RequestBody</classname> method parameter <para>The <classname>@RequestBody</classname> method parameter
annotation is used to indicate that a method parameter should be bound annotation is used to indicate that a method parameter should be bound
to the value of the HTTP request body. For example, </para> to the value of the HTTP request body. For example,</para>
<programlisting language="java">@RequestMapping(value = "/something", method = RequestMethod.PUT) <programlisting language="java">@RequestMapping(value = "/something", method = RequestMethod.PUT)
public void handle(@RequestBody String body, Writer writer) throws IOException { public void handle(@RequestBody String body, Writer writer) throws IOException {
@ -182,8 +180,8 @@ public void handle(@RequestBody String body, Writer writer) throws IOException {
<para>The conversion of the request body to the method argument is <para>The conversion of the request body to the method argument is
done using a <interfacename>HttpMessageConverter</interfacename>. done using a <interfacename>HttpMessageConverter</interfacename>.
<interfacename>HttpMessageConverter</interfacename> is responsible for <interfacename>HttpMessageConverter</interfacename> is responsible for
converting from the HTTP request message to an object converting from the HTTP request message to an object and converting
and converting from an object to the HTTP response body. from an object to the HTTP response body.
<classname>DispatcherServlet</classname> supports annotation based <classname>DispatcherServlet</classname> supports annotation based
processing using the processing using the
<classname>DefaultAnnotationHandlerMapping</classname> and <classname>DefaultAnnotationHandlerMapping</classname> and
@ -210,20 +208,20 @@ public void handle(@RequestBody String body, Writer writer) throws IOException {
</listitem> </listitem>
<listitem> <listitem>
<para><classname>SourceHttpMessageConverter</classname> - convert <para><classname>SourceHttpMessageConverter</classname> - converts
to/from a javax.xml.transform.Source;</para> to/from a javax.xml.transform.Source;</para>
</listitem> </listitem>
<listitem> <listitem>
<para><classname>MarshallingHttpMessageConverter</classname> - <para><classname>MarshallingHttpMessageConverter</classname> -
convert to/from an object using the converts to/from an object using the
<classname>org.springframework.oxm</classname> package.</para> <classname>org.springframework.oxm</classname> package.</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>More information on these converters can be found in the section <para>More information on these converters can be found in the section
<link linkend="rest-message-conversion">Message Converters</link>. <link linkend="rest-message-conversion">Message
</para> Converters</link>.</para>
<para>The <classname>MarshallingHttpMessageConverter</classname> <para>The <classname>MarshallingHttpMessageConverter</classname>
requires a <interfacename>Marshaller</interfacename> and requires a <interfacename>Marshaller</interfacename> and
@ -411,7 +409,7 @@ public class ContentController {
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para><classname>AbstractAtomFeedView</classname> - return an Atom <para><classname>AbstractAtomFeedView</classname> - returns an Atom
feed</para> feed</para>
</listitem> </listitem>
@ -442,7 +440,7 @@ public class ContentController {
and RSS Feed views respectfully. They are based on java.net's <ulink and RSS Feed views respectfully. They are based on java.net's <ulink
url="https://rome.dev.java.net">ROME</ulink> project and are located url="https://rome.dev.java.net">ROME</ulink> project and are located
in the package in the package
<literal>org.springframework.web.servlet.view.feed</literal>. </para> <literal>org.springframework.web.servlet.view.feed</literal>.</para>
<para><classname>AbstractAtomFeedView</classname> requires you to <para><classname>AbstractAtomFeedView</classname> requires you to
implement the <methodname>buildFeedEntries</methodname> method and implement the <methodname>buildFeedEntries</methodname> method and
@ -488,10 +486,10 @@ public class ContentController {
<para>The <methodname>buildFeedItems</methodname> and <para>The <methodname>buildFeedItems</methodname> and
<methodname>buildFeedEntires</methodname> pass in the HTTP request in <methodname>buildFeedEntires</methodname> pass in the HTTP request in
case you need to access the Locale. The HTTP response in passed in case you need to access the Locale. The HTTP response is passed in
only for the setting of cookies or other HTTP headers. The feed will only for the setting of cookies or other HTTP headers. The feed will
automatically be written to the response object after the method automatically be written to the response object after the method
returns. </para> returns.</para>
<para>For an example of creating a Atom view please refer to Alef <para>For an example of creating a Atom view please refer to Alef
Arendsen's SpringSource TeamBlog <ulink Arendsen's SpringSource TeamBlog <ulink
@ -508,7 +506,11 @@ public class ContentController {
explicitly using <classname>MarhsallingView</classname>'s explicitly using <classname>MarhsallingView</classname>'s
<property>modelKey</property> bean property. Alternatively, the view <property>modelKey</property> bean property. Alternatively, the view
will iterate over all model properties marhsall only those types that will iterate over all model properties marhsall only those types that
are supported by the <interfacename>Marshaller</interfacename>.</para> are supported by the <interfacename>Marshaller</interfacename>. For
more information on the functionality in the
<classname>org.springframework.oxm</classname> package refer to the
chapter <link linkend="oxm">Marshalling XML using O/X
Mappers</link>.</para>
</section> </section>
</section> </section>
@ -517,7 +519,7 @@ public class ContentController {
<para>A key principle of REST is the use of the Uniform Interface. This <para>A key principle of REST is the use of the Uniform Interface. This
means that all resources (URLs) can be manipulated using the same four means that all resources (URLs) can be manipulated using the same four
HTTP method: GET, PUT, POST, and DELETE. For each methods, the HTTP HTTP methods: GET, PUT, POST, and DELETE. For each methods, the HTTP
specification defines the exact semantics. For instance, a GET should specification defines the exact semantics. For instance, a GET should
always be a safe operation, meaning that is has no side effects, and a always be a safe operation, meaning that is has no side effects, and a
PUT or DELETE should be idempotent, meaning that you can repeat these PUT or DELETE should be idempotent, meaning that you can repeat these
@ -566,26 +568,26 @@ public String deletePet(@PathVariable int ownerId, @PathVariable int petId) {
used to determine change in content at a given URL. It can be considered used to determine change in content at a given URL. It can be considered
to be the more sophisticated successor to the to be the more sophisticated successor to the
<literal>Last-Modified</literal> header. When a server returns a <literal>Last-Modified</literal> header. When a server returns a
representation with an ETag header, client can use this header in representation with an ETag header, the client can use this header in
subsequent GETs, in a <literal>If-None-Match</literal> header. If the subsequent GETs, in an <literal>If-None-Match</literal> header. If the
content has not changed, the server will return <literal>304: Not content has not changed, the server will return <literal>304: Not
Modified</literal>.</para> Modified</literal>.</para>
<para>Support for ETags is provided by the servlet filter <para>Support for ETags is provided by the servlet filter
<classname>ShallowEtagHeaderFilter</classname>. Since it is a plain <classname>ShallowEtagHeaderFilter</classname>. Since it is a plain
Servlet Filter, and thus can be used in combination any web framework. Servlet Filter, and thus can be used in combination with any web
The <classname>ShallowEtagHeaderFilter</classname> filter creates framework. The <classname>ShallowEtagHeaderFilter</classname> filter
so-called shallow ETags (as opposed to a deep ETags, more about that creates so-called shallow ETags (as opposed to deep ETags, more about
later). The way it works is quite simple: the filter simply caches the that later). The way it works is quite simple: the filter simply caches
content of the rendered JSP (or other content), generates a MD5 hash the content of the rendered JSP (or other content), generates an MD5
over that, and returns that as a ETag header in the response. The next hash over that, and returns that as an ETag header in the response. The
time a client sends a request for the same resource, it use that hash as next time a client sends a request for the same resource, it uses that
the <literal>If-None-Match</literal> value. The filter notices this, hash as the <literal>If-None-Match</literal> value. The filter notices
renders the view again, and compares the two hashes. If they are equal, this, renders the view again, and compares the two hashes. If they are
a <literal>304</literal> is returned. It is important to note that this equal, a <literal>304</literal> is returned. It is important to note
filter will not save processing power, as the view is still rendered. that this filter will not save processing power, as the view is still
The only thing it saves is bandwidth, as the rendered response is not rendered. The only thing it saves is bandwidth, as the rendered response
sent back over the wire.</para> is not sent back over the wire.</para>
<para>Deep ETags are a bit more complicated. In this case, the ETag is <para>Deep ETags are a bit more complicated. In this case, the ETag is
based on the underlying domain objects, RDMBS tables, etc. Using this based on the underlying domain objects, RDMBS tables, etc. Using this
@ -623,18 +625,18 @@ public class SimpleController {
the types in the list, then the method annotated with the matching the types in the list, then the method annotated with the matching
<classname>@ExceptionHandler</classname> will be invoked. If the <classname>@ExceptionHandler</classname> will be invoked. If the
annotation value is not set then the exception types listed as method annotation value is not set then the exception types listed as method
arguments are used. </para> arguments are used.</para>
<para>Much like standard controller methods annotated with a <para>Much like standard controller methods annotated with a
<classname>@RequestMapping</classname> annotation, the method arguments <classname>@RequestMapping</classname> annotation, the method arguments
and return values of <classname>@ExceptionHandler</classname> methods and return values of <classname>@ExceptionHandler</classname> methods
are very flexible. For example, the are very flexible. For example, the
<classname>HttpServletRequest</classname> can be access in Servlet <classname>HttpServletRequest</classname> can be accessed in Servlet
environments and the <classname>PortletRequest</classname> in Portlet environments and the <classname>PortletRequest</classname> in Portlet
environments. The return type can be a <classname>String</classname>, environments. The return type can be a <classname>String</classname>,
which is interpreted as a view name or a which is interpreted as a view name or a
<classname>ModelAndView</classname> object. Please refer to the API <classname>ModelAndView</classname> object. Please refer to the API
documentation for more details. </para> documentation for more details.</para>
</section> </section>
</section> </section>
@ -655,7 +657,7 @@ public class SimpleController {
uses the Object-to-XML framework that is part of the uses the Object-to-XML framework that is part of the
<classname>org.springframework.oxm</classname> package. This gives you a <classname>org.springframework.oxm</classname> package. This gives you a
wide range of choices of XML to Object mapping technologies to choose wide range of choices of XML to Object mapping technologies to choose
from. </para> from.</para>
<para>This section describes how to use the <para>This section describes how to use the
<classname>RestTemplate</classname> and its associated <classname>RestTemplate</classname> and its associated
@ -684,9 +686,9 @@ if (HttpStatus.SC_CREATED == post.getStatusCode()) {
} }
}</programlisting> }</programlisting>
<para> RestTemplate provides higher level methods that correspond to <para>RestTemplate provides higher level methods that correspond to each
each of the six main HTTP methods that make invoking many RESTful of the six main HTTP methods that make invoking many RESTful services a
services a one-liner and enforce REST best practices.</para> one-liner and enforce REST best practices.</para>
<table> <table>
<title>Overview of RestTemplate methods</title> <title>Overview of RestTemplate methods</title>
@ -756,9 +758,9 @@ if (HttpStatus.SC_CREATED == post.getStatusCode()) {
naming convention, the first part indicates what HTTP method is being naming convention, the first part indicates what HTTP method is being
invoked and the second part indicates what is returned. For example, the invoked and the second part indicates what is returned. For example, the
method <methodname>getForObject</methodname> will perform a GET, convert method <methodname>getForObject</methodname> will perform a GET, convert
the HTTP response into an object type of your choice, and returns that the HTTP response into an object type of your choice and return that
object. The method <methodname>postForLocation</methodname> will do a object. The method <methodname>postForLocation</methodname> will do a
POST, converting the given object into a HTTP request, and returns the POST, converting the given object into a HTTP request and return the
response HTTP Location header where the newly created object can be response HTTP Location header where the newly created object can be
found In case of an exception processing the HTTP request, an exception found In case of an exception processing the HTTP request, an exception
of the type <classname>RestClientException</classname> will be of the type <classname>RestClientException</classname> will be
@ -781,20 +783,20 @@ if (HttpStatus.SC_CREATED == post.getStatusCode()) {
<para>Each method takes URI template arguments in two forms, either as a <para>Each method takes URI template arguments in two forms, either as a
<literal>String</literal> variable length argument or a <literal>String</literal> variable length argument or a
<literal>Map&lt;String,String&gt;</literal>. For example, </para> <literal>Map&lt;String,String&gt;</literal>. For example,</para>
<programlisting language="java">String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}", <programlisting language="java">String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}",
String.class,"42", "21"); String.class,"42", "21");
</programlisting> </programlisting>
<para>using variable length arguments and </para> <para>using variable length arguments and</para>
<programlisting language="java">Map&lt;String, String&gt; vars = Collections.singletonMap("hotel", 42); <programlisting language="java">Map&lt;String, String&gt; vars = Collections.singletonMap("hotel", "42");
String result = String result =
restTemplate.getForObject("http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars); restTemplate.getForObject("http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);
</programlisting> </programlisting>
<para>using a <literal>Map&lt;String,String&gt;</literal>. </para> <para>using a <literal>Map&lt;String,String&gt;</literal>.</para>
<para>To create an instance of <classname>RestTemplate</classname> you <para>To create an instance of <classname>RestTemplate</classname> you
can simply call the default constructor. This will use standard Java can simply call the default constructor. This will use standard Java
@ -813,7 +815,7 @@ String result =
<para>The previous example using Jakarta Commons <para>The previous example using Jakarta Commons
<classname>HttpClient</classname> directly rewritten to use the <classname>HttpClient</classname> directly rewritten to use the
<classname>RestTemplate</classname> is shown below </para> <classname>RestTemplate</classname> is shown below</para>
<programlisting>uri = "http://example.com/hotels/{id}/bookings"; <programlisting>uri = "http://example.com/hotels/{id}/bookings";
@ -836,7 +838,7 @@ URI location = template.postForLocation(uri, booking, String.class, "1");
// also has an overload with urlVariables as a Map&lt;String, String&gt;.</programlisting> // also has an overload with urlVariables as a Map&lt;String, String&gt;.</programlisting>
<para>The <interfacename>RequestCallback</interfacename> interface is <para>The <interfacename>RequestCallback</interfacename> interface is
defined as </para> defined as</para>
<programlisting language="java">public interface RequestCallback { <programlisting language="java">public interface RequestCallback {
void doWithRequest(ClientHttpRequest request) throws IOException; void doWithRequest(ClientHttpRequest request) throws IOException;
@ -859,7 +861,7 @@ URI location = template.postForLocation(uri, booking, String.class, "1");
<methodname>put</methodname> are converted to HTTP requests and from <methodname>put</methodname> are converted to HTTP requests and from
HTTP responses by <interfacename>HttpMessageConverters</interfacename>. HTTP responses by <interfacename>HttpMessageConverters</interfacename>.
The <interfacename>HttpMessageConverter</interfacename> interface is The <interfacename>HttpMessageConverter</interfacename> interface is
show below to give you a better feel for its functionality</para> shown below to give you a better feel for its functionality</para>
<programlisting language="java">public interface HttpMessageConverter&lt;T&gt; { <programlisting language="java">public interface HttpMessageConverter&lt;T&gt; {
@ -883,7 +885,7 @@ URI location = template.postForLocation(uri, booking, String.class, "1");
provided in the framework and are registered by default with the provided in the framework and are registered by default with the
<classname>RestTemplate</classname> on the client-side and with <classname>RestTemplate</classname> on the client-side and with
<classname>AnnotationMethodHandlerAdapter</classname> on the <classname>AnnotationMethodHandlerAdapter</classname> on the
server-side. </para> server-side.</para>
<para>The implementations of <para>The implementations of
<classname>HttpMessageConverter</classname>s are described in the <classname>HttpMessageConverter</classname>s are described in the
@ -894,7 +896,7 @@ URI location = template.postForLocation(uri, booking, String.class, "1");
<section id="rest-string-converter"> <section id="rest-string-converter">
<title>StringHttpMessageConverter</title> <title>StringHttpMessageConverter</title>
<para>A <interfacename>HttpMessageConverter</interfacename> <para>An <interfacename>HttpMessageConverter</interfacename>
implementation that can read and write Strings from the HTTP request implementation that can read and write Strings from the HTTP request
and response. By default, this converter supports all text media types and response. By default, this converter supports all text media types
(<literal>text/*</literal>), and writes with a (<literal>text/*</literal>), and writes with a
@ -905,31 +907,31 @@ URI location = template.postForLocation(uri, booking, String.class, "1");
<section id="rest-form-converter"> <section id="rest-form-converter">
<title>FormHttpMessageConverter</title> <title>FormHttpMessageConverter</title>
<para>A <interfacename>HttpMessageConverter</interfacename> <para>An <interfacename>HttpMessageConverter</interfacename>
implementation that can read and write form data from the HTTP request implementation that can read and write form data from the HTTP request
and response. By default, this converter reads and writes the media and response. By default, this converter reads and writes the media
type (<literal>application/x-www-form-urlencoded</literal>). Form data type (<literal>application/x-www-form-urlencoded</literal>). Form data
is read from and written into a <literal>MultiValueMap&lt;String, is read from and written into a <literal>MultiValueMap&lt;String,
String&gt;</literal>. </para> String&gt;</literal>.</para>
</section> </section>
<section id="rest-byte-converter"> <section id="rest-byte-converter">
<title>ByteArrayMessageConverter</title> <title>ByteArrayMessageConverter</title>
<para>A <interfacename>HttpMessageConverter</interfacename> <para>An <interfacename>HttpMessageConverter</interfacename>
implementation that can read and write byte arrays from the HTTP implementation that can read and write byte arrays from the HTTP
request and response. By default, this converter supports all media request and response. By default, this converter supports all media
types (<literal>*/*</literal>), and writes with a types (<literal>*/*</literal>), and writes with a
<literal>Content-Type</literal> of <literal>Content-Type</literal> of
<literal>application/octet-stream</literal>. This can be overridden by <literal>application/octet-stream</literal>. This can be overridden by
setting the <property>supportedMediaTypes</property> property, and setting the <property>supportedMediaTypes</property> property, and
overriding <literal>getContentType(byte[])</literal>. </para> overriding <literal>getContentType(byte[])</literal>.</para>
</section> </section>
<section id="rest-marhsalling-converter"> <section id="rest-marhsalling-converter">
<title>MarshallingHttpMessageConverter</title> <title>MarshallingHttpMessageConverter</title>
<para>A <interfacename>HttpMessageConverter</interfacename> <para>An <interfacename>HttpMessageConverter</interfacename>
implementation that can read and write XML using Spring's implementation that can read and write XML using Spring's
<interfacename>Marshaller</interfacename> and <interfacename>Marshaller</interfacename> and
<interfacename>Unmarshaller</interfacename> abstractions from the <interfacename>Unmarshaller</interfacename> abstractions from the
@ -944,7 +946,7 @@ URI location = template.postForLocation(uri, booking, String.class, "1");
<section id="rest-source-converter"> <section id="rest-source-converter">
<title>SourceHttpMessageConverter</title> <title>SourceHttpMessageConverter</title>
<para>A <interfacename>HttpMessageConverter</interfacename> <para>An <interfacename>HttpMessageConverter</interfacename>
implementation that can read and write implementation that can read and write
<classname>javax.xml.transform.Source</classname> from the HTTP <classname>javax.xml.transform.Source</classname> from the HTTP
request and response. Only <classname>DOMSource</classname>, request and response. Only <classname>DOMSource</classname>,
@ -955,4 +957,4 @@ URI location = template.postForLocation(uri, booking, String.class, "1");
</section> </section>
</section> </section>
</section> </section>
</chapter> </chapter>

2
spring-framework-reference/src/spring-framework-reference.xml

@ -157,7 +157,7 @@
approach to software development is certainly advocated by approach to software development is certainly advocated by
the Spring team, and so coverage of Spring's support for the Spring team, and so coverage of Spring's support for
integration testing is covered (alongside best practices for integration testing is covered (alongside best practices for
unit testing). The Spring team have found that the correct unit testing). The Spring team has found that the correct
use of IoC certainly does make both unit and integration use of IoC certainly does make both unit and integration
testing easier (in that the presence of setter methods and testing easier (in that the presence of setter methods and
appropriate constructors on classes makes them appropriate constructors on classes makes them

Loading…
Cancel
Save